From 2becb7f0eca050787c1c7f29a1080a1b4cbfcb1b Mon Sep 17 00:00:00 2001 From: Benoit Verkindt Date: Fri, 4 Oct 2019 19:06:50 +0200 Subject: [PATCH] [CHRON-9704] Update Blockchain Interface to Parity v2.5.9-stable (#41) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Merge Machine and WithRewards (#10071) * refactor(trim_right_matches -> trim_end_matches) (#10159) * fix(android): remove dependency to libusb (#10161) * Ping nodes from discovery (#10167) * Bump JSON-RPC (#10151) * Bump JSON-RPC * Fix test casing. * fix(whisper): correct PoW calculation (#10166) * Fix off-by-one error on `leading_zeros` which was used to index in the hash to get leading zeros when not aligned on byte boundary (i.e, all the bits in a byte was not zero such as 0001 1111) * Fix overflow by shifting with bigger value than 63 * Fix _cannot recursively call into `Core`_ issue (#10144) * Change igd to github:maufl/rust-igd * Run `igd::search_gateway_from_timeout` from own thread * Fix #9822: trace_filter does not return failed contract creation (#10140) currently trace_filter can't return failed contract creation transaction but trace_block can query the failed contract creation transaction.it because the logic of parity-ethereum/ethcore/src/trace/types/filter.rs Line 109 in 9982eba ``` _ => false ``` this patch correct the logic: ``` _ => self.to_address.matches_all() ``` Signed-off-by: Deshi Xiao * Remove reference to ui-interface command-line option (#10170) * Skip locking in statedb for non-canon blocks (#10141) * version: bump nightly to 2.4 (#10165) * version: bump nightly to 2.4 * revert rand downgrade * Drop `runtime` after others (especially `ws_server`) (#10179) * Align personal_unlockAccount behaviour when permanent unlock is disabled (#10060) * align with docs > If permanent unlocking is disabled (the default) then the duration argument will be ignored, and the account will be unlocked for a single signing. Current behaviour throws an error that is no longer relevant. * fix test * Change back to throwing error * Fix test again * formatting * oops * whitespace fixes * Handle the case for contract creation on an empty but exist account with storage items (#10065) * Add is_base_storage_root_unchanged * Fix compile, use a shortcut for check, and remove ignored tests * Add a warn! * Update ethereum/tests to v6.0.0-beta.2 * grumble: use {:#x} instead of 0x{:x} Co-Authored-By: sorpaas * version: bump fork blocks for kovan and foundation (#10186) * Update for Android cross-compilation. (#10180) * build-unix update * .gitlab-ci update * Update build-unix.sh add android postprocessing * path to android lib libparity.so * fix path to libparity * add android lib to artifacts * pull constantinople on ethereum network (#10189) * ethcore: pull constantinople on ethereum network * version: mark update as critical * ethcore: remove constantinople alltogether from chain spec * version: revert fork block for ethereum * Run all `igd` methods in its own thread (#10195) * Adds cli interface to allow reseting chain to a particular block (#9782) * added BlockChainReset trait, client impl, and cli interface * show block hashes to be deleted and new best block, update best block in db, better cli interface * delete BlockNumber from COL_EXTRA * add TODO comment * add BlockReciepts to imports * refactor block_headers_from_best_block, better cli documentation * exit gracefully if reset arg isn't supplied * fix cli usage macro * removed stray int literals * use Vec::with_capacity Co-Authored-By: seunlanlege * cast n to usize * correct imports * make db reset arg required * Cancel Constantinople HF on POA Core (#10198) * Update the changelogs for 2.1.11, 2.2.6, 2.2.7, and 2.3.0 (#10197) * docs: move 2.2 changelog to docs/ * docs: mark parity 2.1 end of life * docs: add changelog for 2.1.11 * docs: add changelog for 2.2.6 * docs: add changelog for 2.2.7 * docs: add changelog for 2.3.0 * docs: add release notes for 2.3.0 * Extract CallContract and RegistryInfo traits into their own crate (#10178) * Create call-contract crate * Add license * First attempt at using extracted CallContract trait * Remove unneeded `extern crate` calls * Move RegistryInfo trait into call-contract crate * Move service-transaction-checker from ethcore to ethcore-miner * Update Cargo.lock file * Re-export call_contract * Merge CallContract and RegistryInfo imports * Remove commented code * Add documentation to call_contract crate * Add TODO for removal of re-exports * Update call-contract crate description Co-Authored-By: HCastano * Rename call-contract crate to ethcore-call-contract * Remove CallContract and RegistryInfo re-exports from `ethcore/client` (#10205) * Remove re-export of `CallContract` and `RegistryInfo` from `ethcore/client` * Remove CallContract and RegistryInfo re-exports again This was missed while fixing merge conflicts * perform stripping during build (#10208) * perform stripping during build * var RUSTFLAGS * Happy New Year! (#10211) * Happy New Year! * Happy New Year! * Update README.md * Echo CORS request headers by default (#10221) * Echo CORS request headers by default More details in https://github.com/paritytech/parity-ethereum/issues/6616. * fixup: Single line * Add EIP-1283 disable transition (#10214) * Enable St-Peters-Fork ("Constantinople Fix") (#10223) * ethcore: disable eip-1283 on kovan block 10255201 * ethcore: disable eip-1283 on ropsten block 4939394 * ethcore: enable st-peters-fork on mainnet block 7280000 * ethcore: fix kovan chain spec * version: update fork blocks * ethcore: disable eip-1283 on sokol block 7026400 * import rpc transactions sequentially (#10051) * import rpc transactions sequentially * use impl trait in argument position, renamed ProspectiveDispatcher to WithPostSign * grouped imports * integrates PostSign with ProspectiveSigner * fix spaces, removed unnecessary type cast and duplicate polling * clean up code style * Apply suggestions from code review * fix(ManageNetwork): replace Range with RangeInclusive (#10209) * fix(ManageNetwork): replace Range -> RangeIncls Fixes `TODO: Range should be changed to RangeInclusive once stable (https://github.com/rust-lang/rust/pull/50758)` * fix(tests) * fix(grumbles): off-by-one error in debug_asserts * RangeInclusive::end() is inclusive which means that if start and end is equal the `debug_assert(range.end() > range.start()` will fail which is shouldn't * fixed: types::transaction::SignedTransaction; (#10229) * Update copyright year to 2019. (#10181) * Update copyright year to 2019. Have a great year. * add `(UK)` * 2018-2019 * Fix typo: CHANGELOG-2.1 -> CHANGELOG-2.2 (#10233) * Update CHANGELOG.md (#10249) change 2018 to 2019 * Take in account zero gas price certification when doing transact_contract (#10232) * Tx permission contract improvement * Take in account zero gas price certification when doing transact_contract * DRY in ServiceTransactionChecker * Fix typos and regroup mod * Fix imports * Simplify code in struct instantiation Co-Authored-By: VladLupashevskyi * Allow specifying local accounts via CLI (#9960) * Allow specifying local accounts via CLI * Add `tx-queue-locals` CLI option * ethcore: modify miner to check options vec before importing transaction * modify tests (ethcore/parity) Resolves #9634 * fix formatting * fixes: Make prefer HashSet over Vec<>, add test, comment formatting * Update ethcore/src/miner/miner.rs Co-Authored-By: insipx * Fix comments and add helper for set->vec conversion * remove blank line from use statement * fix helper test * formatting * fix test to pass on nightly * revert test fix for nightly * Macos heapsize force jemalloc (#10234) * Switch to non prefixed malloc_size_of on macos * Fix * Testing darwin build * Fix import * conflict * switch heapsize deps commit * switch heapsize commit * Rename branch * Restore gitlab ci to origin * test for mac * mac tests? * Switch of macos CI tests. * Update CHANGELOG-2.2.md (#10254) * Fix join-set test to be deterministic. (#10263) * prevent silent errors in daemon mode (#10007) * prevent silent errors in daemon mode * change author in Cargo.toml, add preamble to pipe.rs * set the uid and gid on daemon process, fix permission errors when writing to pid file * call setup_logger before daemonize to prevent crashing when attempting to create logfile * map_err for calls to splice and ioctl, fix spaces in Cargo.toml * split out daemonize to own repo * removed util/daemonize * renamed dep to parity-daemonize * fix(parity-clib): enable `logger` * bump parity-daemonize * remove obsolete comment Co-Authored-By: seunlanlege * fix(grumbles): docs and log in ParityParams * Add FIXME comment regarding @tomaka grumbles * Unify logger with the C-API in ParityParams (less type-safety with more from_raw() conversions) * Add better documentation in the `parity.h` * Apply suggestions from code review Co-Authored-By: seunlanlege * docs(parity lib): add link to logging issue * fix(parity-clib): JNI enable `logger` * fix(parity-clib): update `Java example` * Update example to the API changes * Remove needless printouts which can be controlled via logger instead * Additional tests for uint deserialization. (#10279) * Don't run the CPP example on CI (#10285) * Don't run the CPP example on CI * Add comment * Fix Windows build (#10284) * Convert to jsonrpc-derive, use jsonrpc-* from crates.io (#10298) * Use jsonrpc crates on local path * Convert all RPC traits to use jsonrpc-derive * Use local jsonrpc at top level * Upgrade remaining jsonrpc dependencies * Checkout Cargo.lock to master HEAD * Use jsonrpc-* 10.0.1 from crates.io * Attribute after docs * Update to jsonrpc-derive 10.0.2, fixes aliases bug (#10300) * fix(secret-store): deprecation warning (#10301) use of deprecated item 'core::str::::trim_left_matches': superseded by `trim_start_matches` * update ring to 0.14 (#10262) * cargo upgrade hyper-rustls --all * cargo upgrade parity-crypto --all * update Cargo.lock * propagate NonZeroU32 * use NonZeroU32::new_unchecked for crypto::KEY_ITERATIONS * update Cargo.lock * replace unsafe code with lazy_static * Call private contract methods from another private contract (read-only) (#10086) * Patch available private contracts during private transaction * Key acl ABI added * Work with secret store keys moved to the separate struct * Private tx test refactored * Revert "Private tx test refactored" This reverts commit 476c132d692c7a886bc7b7cd7fe47b3d7692bd63. * Test for calling private contract from another one added * Test fixed * Redundant tab removed * ACL contract processing fixed, test added * Merge with head * Expect replaced with closure * Add missing step for Using `systemd` service file (#10175) * Add missing step for Using `systemd` service file Copy Parity release from target folder to bin, write `cp -R ./target/release/parity /usr/bin/` to match `ExecStart=/usr/bin/parity --config /etc/parity/config.toml` from `https://github.com/paritytech/parity-ethereum/blob/master/scripts/parity.service` * Copy release to bin folder using sudo install `sudo install ./target/release/parity /usr/bin/parity` * fix(osx and windows builds): bump parity-daemonize (#10291) * Properly handle check_epoch_end_signal errors (#10015) * Make check_epoch_end_signal to only use immutable data * Move check_epoch_end_signals out of commit_block * Make check_epoch_end_signals possible to fail * Actually return the error from check_epoch_end_signals * Remove a clone * Fix import error * Deprecate account management (#10213) * Extract accounts from ethcore. * Fix ethcore. * Get rid of AccountProvider in test_helpers * Fix rest of the code. * Re-use EngineSigner, fix tests. * Simplify EngineSigner to always have an Address. * Fix RPC tests. * Add deprecation notice to RPCs. * Feature to disable accounts. * extract accounts in RPC * Run with accounts in tests. * Fix RPC compilation and tests. * Fix compilation of the binary. * Fix compilation of the binary. * Fix compilation with accounts enabled. * Fix tests. * Update submodule. * Remove android. * Use derive for Default * Don't build secretstore by default. * Add link to issue. * Refresh Cargo.lock. * Fix miner tests. * Update rpc/Cargo.toml Co-Authored-By: tomusdrw * Fix private tests. * Increase number of requested block bodies in chain sync (#10247) * Increase the number of block bodies requested during Sync. * Increase the number of block bodies requested during Sync. * Check if our peer is an older parity client with the bug of not handling large requests properly * Add a ClientVersion struct and a ClientCapabilites trait * Make ClientVersion its own module * Refactor and extend use of ClientVersion * Replace strings with ClientVersion in PeerInfo * Group further functionality in ClientCapabilities * Move parity client version data from tuple to its own struct. * Implement accessor methods for ParityClientData and remove them from ClientVersion. * Minor fixes * Make functions specific to parity return types specific to parity. * Test for shorter ID strings * Fix formatting and remove unneeded dependencies. * Roll back Cargo.lock * Commit last Cargo.lock * Convert from string to ClientVersion * * When checking if peer accepts service transactions just check if it's parity, remove version check. * Remove dependency on semver in ethcore-sync * Remove unnecessary String instantiation * Rename peer_info to peer_version * Update RPC test helpers * Simplify From * Parse static version string only once * Update RPC tests to new ClientVersion struct * Document public members * More robust parsing of ID string * Minor changes. * Update version in which large block bodies requests appear. * Update ethcore/sync/src/block_sync.rs Co-Authored-By: elferdo * Update util/network/src/client_version.rs Co-Authored-By: elferdo * Update util/network/src/client_version.rs Co-Authored-By: elferdo * Update tests. * Minor fixes. * CI optimizations (#10297) * CI optimizations * fix stripping * new dockerfile * no need n submodule upd * review * moved dockerfile * it becomes large * onchain update depends on s3 * fix dependency * fix cache status * fix cache status * new cache status * fix: parity-clib/examples/cpp/CMakeLists.txt (#10313) * use of ${CMAKE_SHARED_LIBRARY_PREFIX} & ${CMAKE_SHARED_LIBRARY_SUFFIX} to support other operating systems. * Make specification of protocol in SyncRequester::send_request explicit (#10295) * Make the specification of the protocol to which a packet_id belongs to explicit when calling "SyncRequester::send_packet". * Remove "SyncIO::send" and leave only "SyncIO::send_protocol" * Adapt tests to new code. * Strengthen tests to check if packet_id and protocol match when sending a devp2p packet. * Secure WS-RPC: grant access to all apis (#10246) * fix publish job (#10317) * fix publish job * dashes and colonels * fix(light-rpc): Make `light_sync` generic (#10238) * fix(light-rpc): Make `light_sync` generic The motivation behind this change is to easily mock `light-sync` to make it possible to enable `rpc-integration` tests for the light-client. Currently the `rpc's` requires the concrete type `sync::LightSync` which makes it very hard to do so * fix(bad merge) * fix(parity-clib): grumbles that were not addressed in #9920 (#10154) * fix(remove needless unsafe blocks) * style(nits) * fix(parity-clib): eliminate repetitive event loops * revert(java bindings): safe rust -> unsafe rust These functions can still end up with `UB` thus should be unsafe * fix(grumbles): make Callback trait `pub (crate)` * Add Statetest support for Constantinople Fix (#10323) * Update Ethereum tests repo to v6.0.0-beta.3 tag * Add spec for St.Peter's / ConstantinopleFix statetests * Revive parity_setMinGasPrice RPC call (#10294) * Add function to update minimum gas price * Update TestMinerService to handle min_gas_price changes * Place minimum gas price test behind feature flag * Update check for fixed gas pricer to be more explicit * Use errors::unsupported instead of errors::request_rejected * Add test that fails to set minimum gas price * Fix test that should fail when setting new gas price * Put dev dependencies behind feature flag * Fix deadlock in set_minimal_gas_price() * Update RPC tests with mocked error response * Remove unnecessary cfg flag * Remove duplicate crate imports * Additional error for invalid gas (#10327) * Tag sensible place (ECHECH) * Additional overflows checks. * fix(add helper for timestamp overflows) (#10330) * fix(add helper timestamp overflows) * fix(simplify code) * fix(make helper private) * snap: official image / test (#10168) * official image / test * fix / test * bit more necromancy * fix paths * add source bin/df /test * add source bin/df /test2 * something w paths /test * something w paths /test * add source-type /test * show paths /test * copy plugin /test * plugin -> nil * install rhash * no questions while installing rhash * publish snap only for release * fix(docker): fix not receives SIGINT (#10059) * fix(docker): fix not receives SIGINT * fix: update with reviews * update with review * update * update * Don't add discovery initiators to the node table (#10305) * Don't add discovery initiators to the node table * Use enums for tracking state of the nodes in discovery * Dont try to ping ourselves * Fix minor nits * Update timeouts when observing an outdated node * Extracted update_bucket_record from update_node * Fixed typo * Fix two final nits from @todr * change docker image based on debian instead of ubuntu due to the chan… (#10336) * change docker image based on debian instead of ubuntu due to the changes of the build container * role back docker build image and docker deploy image to ubuntu:xenial based (#10338) * Bundle protocol and packet_id together in chain sync (#10315) Define a new `enum` where devp2p subprotocol packet ids (currently eth and par) are defined. Additionally provide functionality to query id value and protocol of a given id object. * snap: prefix version and populate candidate channel (#10343) * snap: populate candidate releases with beta snaps to avoid stale channel * snap: prefix version with v* * Fixed misstype (#10351) * Fixed misstype BadTransactonType => BadTransactionType * fixed other insances of transacton * no volumes are needed, just run -v volume:/path/in/the/container (#10345) * fix(compilation warns): `no-default-features` (#10346) * snap: release untagged versions from branches to the candidate snap channel (#10357) * Add fields to `memzero`'s Cargo.toml (#10362) * Add fields to Cargo.toml before publishing to crates.io * Change license from MIT to GPL-3.0 * Add docs page * SecretStore: use in-memory transport in cluster tests (#9850) * fixing SS tests * removed some redundant clones * fixed grumbles * replaced hash.clone() with *hash + fixed comment * lost files * chore(bump parity-daemonize): require rust >= 1.31 (#10359) * Add message to IO errors (#10324) * snap: add the removable-media plug (#10377) This interface allows the snap to access the directories in /media. This is needed when the storage is in a separate disk, not part of home. * ethash: implement Progpow (#9762) * ethash: initial implementation of progpow * progpow: use wrapping arithmetic * progpow: cleanup comments * progpow: fix keccak_f800 * progpow: reorder definitions * progpow: general fixing * progpow: add basic tests from geth * progpow: generate c_dag and add test * progpow: fix progpow_init and progpow_loop * progpow: fix and add new test * progpow: tabify * progpow: add shared testvectors from geth and aleth * progpow: add benchmarks * progpow: don't read bytes from dag * ethash: use criterion for progpow benchmarks * progpow: dont borrow hash on fnv1a_hash * progpow: don't borrow operand on progpow merge * progpow: hardcode dag lookup function we only support light verification anyway * progpow: read double words directly from the dag * progpow: inline some small functions * progpow: remove some bounds checking from the main loop * progpow: remove unreachable match cases * progpow: remove bounds check in keccak_f800_round * progpow: fix ptr::swap * progpow: force loop unroll in keccak_f800_round * progpow: remove unnecessary branching in progpow_loop * progpow: force loop unroll in fill_mix * progpow: silence unused warning * progpow: dont run last keccak_f800_round out of the loop rustc generates the same assembly, it unrolls the loop * progpow: fix output of keccak_f800_short * ethcore: support progpow in ethash engine * ethash: fix typo * ethcore, ethash: fix tests * json: fix ethash spec tests * ethash: update quick_get_difficulty for progpow * ethash: drop light cache on progpow transition block * ethash: fix quick_get_difficulty tests * progpow: update to spec v0.9.0 * progpow: update to spec v0.9.1 * progpow: update to spec v0.9.2 * ethash: rename progpow benchmarks * fix Cargo.lock bad merge * ethash: only export modules for benchmarks * ethash: progpow: remove unsafe unchecked indexing * ethash: create enum for pow algorithm * ethash: box the progpow cdag * ethash: skip slow progpow test vectors on ci * ethash: don't skip progpow test vectors they don't take too long when running in release mode which is the case for CI. * ethash: progpow: update copyright date Co-Authored-By: andresilva * ethcore: remove verification of ci-skip-tests on non-test builds * exchanged old(azure) bootnodes with new(ovh) ones (#10309) * exchanged old(azure) bootnodes with new(ovh) ones * Fix indent * fix(trace_main! macro): don't re-export (#10384) * tx pool: always accept local transactions (#10375) * tx pool: always accept local transactions * tx pool: `choose` local txs with same sender and nonce * Update to latest mem-db, hash-db and trie-db. (#10314) * Switch to 'trie' crates, there is an unpublished deps to staging parity-common triehash still. * Use crates.io dependency. * indentation * Update util/journaldb/src/traits.rs indentation Co-Authored-By: cheme * Update ethcore/src/snapshot/tests/state.rs Co-Authored-By: cheme * chore(bump ethereum-types) (#10396) Fixes a de-serialization bug in `ethereum-tyes` * fix(jni): bump to jni to 0.11 & remove unsafe impl (#10394) * no-git for publish jobs, empty artifacts dir (#10393) * no-git for publish jobs, empty artifacts dir * fix syntax * prettiness * fix prettiness * should get rid of git in publishing * version: bump nightly to 2.5 (#10392) * version: bump nightly to 2.5 * revert(rand 0.3.22) * revert some changes, could be buggy (#10399) * Fix to_pod storage trie value decoding (#10368) * fix #10390 (#10391) * snap: reenable i386, arm64, armhf architecture publishing (#10386) * snap: reenable i386, arm64, armhf architecture publishing * gitlab: fix indent * gitlab: fix yml syntax * Linker for crosscomile * fix target to linker * new docker image * fix lint, add build to this PR * calc SHA3 using rhash * add new images for i386, armhf * show snap target & artifacts * set CARGO_TARGET for publish snap * move detect Version to publish snap * rm libc6 dep from snap-template up pub-snap script * clean up cargo config before add linker * move linker config to docker images * fix(rpc-types): replace uint and hash with `ethereum_types v0.4` (#10217) * fix(rpc-types): remove uint and hash wrappers * fix(tests) * fix(cleanup) * grumbles(rpc-api): revert `verify_signature` * revert change of `U64` -> `u64` * fix(cleanup after bad merge) * chore(bump ethereum-types) * fix(bad merge) * feat(tests ethereum-types): add tests * chore(update `ethereum-types` to 0.4.2) * feat(tests for h256) * chore(rpc): remove `ethbloom` import Use re-export from `ethereum-types` instead * fix(bad merge): remove `DefaultAccount` type * doc(add TODO with issue link) * 10000 > 5000 (#10422) addresses #10418 * Refactor ethcore::client::TransactResult to use it inside std::result::Result (#10366) * Refactor TransactResult * Adapt evmbin and tests * fix panic when logging directory does not exist, closes #10420 (#10424) * parity/main.rs uses eprintln instead of raw stderr interface (#10427) * Remove duplicate test cases (#10385) Case create_account() is same as new_account() * remove redundant macro println_stderr from parity/cli/usage.rs (#10425) * fix underflow in pip, closes #10419 (#10423) * ci: clean up gitlab-ci.yml leftovers from previous merge (#10429) * panic_hook module uses eprintln instead of raw stderr interface (#10426) * Update hardcoded headers for Foundation, Ropsten, Kovan and Classic (#10417) * update foundation to #7262209 * update kovan to #10434561 * update ropsten to #5027841 * update classic to #7555073 * Update Ropsten headers to #5101569 * Use correct name for documentation field in Cargo.toml (#10440) * Silence Error::cause deprecations (#10438) * CI publish to aws (#10446) * move publish aws from gitlab.yml to gitlab scripts * gitlab.yml cleaning move publish AWS to gitlab scripts remove dependencies from android build * Implement parity_versionInfo & parity_setChain on LC; fix parity_setChain (#10312) * Light client: implement parity_versionInfo RPC * Light client: implement set_exit_handler & parity_setChain RPC * parity_setChain RPC: return an error if failed (instead of `true`) * Implement eth_subscribe('syncing') RPC for full node & light node * Fix indentation * Revert commit: Implement eth_subscribe('syncing') * Revert change to Cr callback function * CI aws git checkout (#10451) * Updating the CI system with the publication of releases and binary files on github Signed-off-by: Denis S. Soldatov aka General-Beck * move publish aws from gitlab.yml to gitlab scripts Signed-off-by: Denis S. Soldatov aka General-Beck * gitlab.yml cleaning move publish AWS to gitlab scripts remove dependencies from android build Signed-off-by: Denis S. Soldatov aka General-Beck * Revert "Updating the CI system with the publication of releases and binary files on github" This reverts commit da87e06f2e4751dbca08a898b52926aef5ad0aba. * remove no-git for aws * microfix * no need in no_git then * perf(ethcore): `micro-opt` (#10405) Mostly fixes that changes `eagerly eval` to `lazy eval` * Revert "CI aws git checkout (#10451)" (#10456) * Revert "CI aws git checkout (#10451)" This reverts commit 3e1d73126c41779e36a05383a4278822ccc6023a. * Update .gitlab-ci.yml revert aws script with small fixes * Delete publish-aws.sh * docs: update changelogs for 2.2.{8,9,10,11}, 2.3.{1,2,3,4,5}, and 2.4.0 (#10389) * docs: move changelog 2-3 to docs/ * docs: fix changelog 2-3 path * docs: add changelogs for 2.2.{8,9,10,11} * docs: add changelogs for 2.3.{1,2,3,4} * Update CHANGELOG.md * Update CHANGELOG-2.3.md * Update CHANGELOG.md * Update CHANGELOG.md * simplify ethcore machine by removing redundant traits (#10454) * docs(spec): remove link to obsolete issue (#10464) * Tests parallelized (#10452) * tests splitted, phase 1 * typo * fix wrong launch commands * typos * rearrangements * use `nproc` function for threads * use nproc for threads * let theads be auto, build-andriod no more in regular run * split val chain and cargo check * renamed some files * wrong phase * check rust files before test jobs * lint error * rust files modivied var * test except changes * add rust_changes except * lint error * fixes * .gitlab-ci.yml can't be excluded * pipeline shouldn't start * pipeline must go * pipeline must go 2 * pipeline must go 3 * pipeline must go 4 * pipeline must go 5 * pipeline must go 6 * pipeline must go 7 * pipeline must not go 1 * pipeline must go 8 * avoid skippng tests yet, reintroducing them after the caching * test theory * parallelized cargo check with combusting helicopters * less uploads * alias for cargo checks * nice template * Ensure static validator set changes are recognized (#10467) * simplify parity machine (#10469) * simplify ethcore machine by removing redundant traits * further ethereum machine simplifications * removed obsolete todo * further simplify machine (#10472) * removed AuxiliaryRequest from Machin trait * removed AncestryAction from Machine trait * removed AuxiliaryData from Machine trait * removed LocalizedMachine trait * remove unused Engine::is_proposal (#10475) * remove unused Engine::maximum_uncle_age (#10476) * simplify block module and usage (#10479) * removed trait IsBlock and simplify block usage * removed redundant ClosedBlock::hash function * OpenBlock::new take IntoIterator instead of mutable ref to Iterator (#10480) * Сaching through docker volume (#10477) * _old codebase_ before docker update * before docker update, testing runnr * docker update, testing the caching * distributed job cargo homes * distributed job cargo homes 2 * distributed job cargo homes 3 * dockerfile with gitlab checkout, audit uses template * dockerfile gets repo in volume * change builds_dir * trying docker cache for repo * repo cached automatically * after script is not concatenated * check sccache non-cacheable reasons nature * watch cache * log sccache * log sccache 2 * debug log sccache * fix debug log sccache * fix debug log sccache 2 * debug log cache 3 * debug log cache 3 * trace log all sccache * test wo cargo cache * test w removed cargo cache * report non-cacheable reasons, cargo cache is back and empty * report non-cacheable reasons, cargo cache is back and empty 2 * report non-cacheable reasons, cargo cache is back and empty 3 * wrap into after_script * restore CI tags `qa` -> `linux-docker` * return to main runners, this will fail until config on runners And Dockerfile won't be updated * typo fix CI lint * return to docker tag * fix win&mac build (#10486) add CARGO_HOME: "${CI_PROJECT_DIR}/.cargo" * fix(rpc): lint `unused_extern_crates` + fix warns (#10489) * fix(extract `timestamp_checked_add` as lib) (#10383) * fix(extract `timestamp_checked_add` as lib) * fix(whisper types): remove unused `EmptyTopics` * fix(time-lib): feature-flag to use time-lib or std This commit adds conditional compilation checks that falls back to `our time-lib` when `time_checked_add` is not available in the standard library Note, `time_checked_add` covers both `checked_add` and `checked_sub` * fix(grumble): use cfg_attr to define rustc feature * fix(time-utils): add missing license (#10497) * whisper/cli: add p2p port and ip parameters (#10057) * whisper/cli: add p2p port and ip parameters This is so that those params don't change randomly and are in sync with the URL that is displayed. * feedback: Result instead of panic Co-Authored-By: gballet * feedback: Map error in port conversion Co-Authored-By: gballet * whisper/cli: User can specify enode private key So that the enode doesn't change at every run. * whipser/cli: finish integrating review feedback. * Accomodate error API change * Update rustc-hex version in whisper/cli/Cargo.toml Co-Authored-By: gballet * Update README with new whisper cli options * Fix typo in error message Co-Authored-By: gballet * Fix Cargo.lock and build issue after lib version upgrade * Fix another typo Co-Authored-By: gballet * Add additional request tests (#10503) * fix Sha3/keccak256 hash calculation for binaries (#10509) https://github.com/paritytech/parity-ethereum/issues/10495 * fix(rpc): fix a bunch of clippy lints (#10493) * fix(rpc): fix a bunch of clippy lints * fix(rpc clippy): remove unused ignored lints * fix(clippy): fix all redundant_field_names This commit fixes all uses of `redundant_field_names` and removes the ignored lint `redundant_field_names` * fix(brain unwrap): replace with expect * docs: add changelogs for 2.3.{6,7,8} and 2.4.{1,2,3} (#10494) * docs: add changelogs for 2.3.{6,7} and 2.4.{1,2} * docs: add changelogs for 2.4.3 beta and 2.3.8 stable * Update docs/CHANGELOG-2.3.md Co-Authored-By: soc1c <47772477+soc1c@users.noreply.github.com> * Update docs/CHANGELOG-2.3.md Co-Authored-By: soc1c <47772477+soc1c@users.noreply.github.com> * docs: remove empty lines * Add a more realistic Batch test (#10511) * Remove unrealistic tests * Add test that more closely resembles real usage * verbose flag for cpp tests (#10524) * ethcore: add clique engine (#9981) * fix broken sync * correct seal fields * ethcore: fix comment * parity: remove duplicate params * clique: fix whitespaces * ethcore: fix goerli chain spec * refactor signer_snapshot into pending/finalized state * move close_block_extra_data after seal is applied * refactor most of the logic into the signer_snapshot * clique: refactor locking logic out of the consensus engine interface * Fix jsonspec and add an unittest * Replace space with tabs * Unbroke sync * Fix broken sync * 1/2 state tracking without votes * 2/2 implement vote tracking * ci: use travis for goerli * ci: setup a clique network * ci: sync a görli node * add clique deploy script * ci: fix paths in clique deploy script * ci: use docker compose * ci: fix travis job names * ci: fix build deps * ci: massively reduce tests * Revert "ci: massively reduce tests" This reverts commit 6369f0b069ed2607a7e9f2e1d85489bacdc43384. * ci: run cargo test directly * ci: separate build and test stages * ci: cache rust installation * ci: simplify ci stages * ci: make clique deploy script executable * ci: shutdown goerli sync after 20min * ci: remove slow sync stage * ci: use timeout to finish jobs * ci: fix build path * ci: use absolute paths to end this confusion * ci: add geth and parity to path * ci: be more verbose * ci: allow for more relaxed caching timeout * ci: update repositories for custom ppa * ci: fix typo in file name * ci: fix docker compose file * ci: add ethkey to docker * ci: make sure deploy script is up to date with upstream * ci: stop docker container after certain time * ci: force superuser to update permissions on docker files * ci: reduce run time of script to ~30 min * ci: remove duplicate caching in travis * remove trace statements * clique: add more validation involving the recent signer list * ethcore: enable constantinople for rinkeby * ethcore: fix whitespaces in rinkeby spec * ethcore: reformat goerli.json * Revert "ci: remove duplicate caching in travis" This reverts commit a562838d3d194d37f9871dcbe00b783637978f89. * tmp commit * another tmp commit * it builds! * add sealing capabilities * add seal_header hook to allow separation of block seal/importing code paths * clique: remove populate_from_parent. * add panic * make turn delay random * initialize OpenBlock properly in 'enact' * misc: remove duplicate lines * misc: fix license headers * misc: convert spaces to tabs * misc: fix tabs * Update Cargo.toml * Update Cargo.toml * Update Cargo.toml * clique: ensure validator restores state before trying to seal * clique: make 'state' return an Error. Make some error messages more clear * Fix compile error after rebase & toolchain upgrade * fix a bunch of import warnings * Refactor code * Fix permissions * Refactoring syncing * Implement full validator checks * Refactor util functions to seperate file * mining 1 * ethcore: add chainspec for kotti * ethcore: rename pre-goerli configs * ethcore: load kotti chain spec * cli: add kotti to params * Implement working local sealing * making sealing & syncing work together * Relax timestamp checking * ethcore: prepare for the real goerli to launch * Implement NOTURN wiggle properly & cleanupnup warnings * Implement vote casting * Update docs & skip signing if no signer * Optimize step-service interval * Record state on local sealed block * Fix script filemode * Cleaning up codebase * restore enact trace logging * Delete clique.sh and move sync.sh * remove travis.yml * Remove dead code * Cleanup compile warning * address review comments * adding more comments and removing unwrap() * ci: remove sync script * Address review comments * fix compile error * adding better debugging for timing * Implement an dedicated thread for sealing timing * fix(add helper for timestamp overflows) (#10330) * fix(add helper timestamp overflows) * fix(simplify code) * fix(make helper private) * snap: official image / test (#10168) * official image / test * fix / test * bit more necromancy * fix paths * add source bin/df /test * add source bin/df /test2 * something w paths /test * something w paths /test * add source-type /test * show paths /test * copy plugin /test * plugin -> nil * install rhash * no questions while installing rhash * publish snap only for release * fix(docker): fix not receives SIGINT (#10059) * fix(docker): fix not receives SIGINT * fix: update with reviews * update with review * update * update * Don't add discovery initiators to the node table (#10305) * Don't add discovery initiators to the node table * Use enums for tracking state of the nodes in discovery * Dont try to ping ourselves * Fix minor nits * Update timeouts when observing an outdated node * Extracted update_bucket_record from update_node * Fixed typo * Fix two final nits from @todr * change docker image based on debian instead of ubuntu due to the chan… (#10336) * change docker image based on debian instead of ubuntu due to the changes of the build container * role back docker build image and docker deploy image to ubuntu:xenial based (#10338) * Bundle protocol and packet_id together in chain sync (#10315) Define a new `enum` where devp2p subprotocol packet ids (currently eth and par) are defined. Additionally provide functionality to query id value and protocol of a given id object. * snap: prefix version and populate candidate channel (#10343) * snap: populate candidate releases with beta snaps to avoid stale channel * snap: prefix version with v* * addressing review comments * engine: fix copyright header * scripts: restore permissions on sign command * ethcore: enforce tabs * ethcore: enforce tabs * ethcore: enforce tabs * addressing comments * addressing comments * addressing more comments * addressing more comments * addressing more comments * addressing more comments * addressing more comments * json-spec: fix clique epoch to non-zero u64 * ci: enable travis for parity goerli * ci: don't separate build and test step * ci: don't run c++ tests on travis * ci: simplify cargo test to squeeze into travis timeout * ci: don't run tests on travis at all * style(fixes) * fix(add tests) * fix(recent_signer bug) * fix(complete all tests) * fix(nits) * fix(simplify asserts) * fix(cliqueState): simplify code * fix(nits) * docs(comments what's need to fixed) * fix(revert unintended changes) * fix(tests) * fix(logs): voting logs * fix(readability + more logs) * fix(sync) * docs(add missing licens header) * fix(log): info! -> trace! * docs(fix nits) + fix(remove assert) * perf(use counter instead of vec) * fix(remove needless block in match) * fix(faulty comment) * grumbles(docs for tests) * fix(nits) * fix(revert_vote): only remove vote when votes == 0 * fix(vote counter): checked arithmetics * fix(simplify tests) * fix(nits) * fix(clique): err types * fix(clique utils): make use of errors * fix(cleanup nits) * fix(clique sealing): don't read state no signer * fix(replace Vec with BTreeSet) * fix(tests): BTreeSet and more generic helpers * fix(nits) * fix(ethcore_block_seal): remove needless `Box` * fix(faulty log): info -> trace * fix(checked SystemTime): prevent SystemTime panics * style(chain cfg): space after `:` * style(fn enact): fix whitespace * docs(clique): StepService * docs(nit): fix faulty comment * docs(fix typo) * style(fix bad indentation) * fix(bad regex match) * grumble(on_seal_block): make `&mut` to avoid clone * docs(on_seal_block): fix faulty documentation * Delete .travis.yml * docs: remove eth hf references in spec * Update client.rs * fix(nits) * fix(clique step): `RwLock` -> `AtomicBool` * fix(clique): use `Duration::as_millis` * Clean up some Clique documentation Co-authored-by: soc1c Co-authored-by: HCastano Co-authored-by: niklasad1 Co-authored-by: jwasinger Co-authored-by: ChainSafe Co-authored-by: thefallentree Co-authored-by: 5chdn <5chdn@users.noreply.github.com> * Add trace information to eth_estimateGas (#10519) * Add trace information to eth_estimateGas * replace unwrap better version * change vm::Error formatter to more user-friendly * remove extra error format * use map_or instead sequence of map/unwrap_or * private-tx: replace error_chain (#10510) * Update to vanilla tx pool error * private-tx: remove error-chain, implement Error, derive Display * private-tx: replace ErrorKind and bail! * private-tx: add missing From impls and other compiler errors * private-tx: use original tx-pool error * Don't be silly cargo * fix(light): make `OnDemand` generic instead of using the concrete type (#10514) * ethcore: add clique engine (#9981) * fix broken sync * correct seal fields * ethcore: fix comment * parity: remove duplicate params * clique: fix whitespaces * ethcore: fix goerli chain spec * refactor signer_snapshot into pending/finalized state * move close_block_extra_data after seal is applied * refactor most of the logic into the signer_snapshot * clique: refactor locking logic out of the consensus engine interface * Fix jsonspec and add an unittest * Replace space with tabs * Unbroke sync * Fix broken sync * 1/2 state tracking without votes * 2/2 implement vote tracking * ci: use travis for goerli * ci: setup a clique network * ci: sync a görli node * add clique deploy script * ci: fix paths in clique deploy script * ci: use docker compose * ci: fix travis job names * ci: fix build deps * ci: massively reduce tests * Revert "ci: massively reduce tests" This reverts commit 6369f0b069ed2607a7e9f2e1d85489bacdc43384. * ci: run cargo test directly * ci: separate build and test stages * ci: cache rust installation * ci: simplify ci stages * ci: make clique deploy script executable * ci: shutdown goerli sync after 20min * ci: remove slow sync stage * ci: use timeout to finish jobs * ci: fix build path * ci: use absolute paths to end this confusion * ci: add geth and parity to path * ci: be more verbose * ci: allow for more relaxed caching timeout * ci: update repositories for custom ppa * ci: fix typo in file name * ci: fix docker compose file * ci: add ethkey to docker * ci: make sure deploy script is up to date with upstream * ci: stop docker container after certain time * ci: force superuser to update permissions on docker files * ci: reduce run time of script to ~30 min * ci: remove duplicate caching in travis * remove trace statements * clique: add more validation involving the recent signer list * ethcore: enable constantinople for rinkeby * ethcore: fix whitespaces in rinkeby spec * ethcore: reformat goerli.json * Revert "ci: remove duplicate caching in travis" This reverts commit a562838d3d194d37f9871dcbe00b783637978f89. * tmp commit * another tmp commit * it builds! * add sealing capabilities * add seal_header hook to allow separation of block seal/importing code paths * clique: remove populate_from_parent. * add panic * make turn delay random * initialize OpenBlock properly in 'enact' * misc: remove duplicate lines * misc: fix license headers * misc: convert spaces to tabs * misc: fix tabs * Update Cargo.toml * Update Cargo.toml * Update Cargo.toml * clique: ensure validator restores state before trying to seal * clique: make 'state' return an Error. Make some error messages more clear * Fix compile error after rebase & toolchain upgrade * fix a bunch of import warnings * Refactor code * Fix permissions * Refactoring syncing * Implement full validator checks * Refactor util functions to seperate file * mining 1 * ethcore: add chainspec for kotti * ethcore: rename pre-goerli configs * ethcore: load kotti chain spec * cli: add kotti to params * Implement working local sealing * making sealing & syncing work together * Relax timestamp checking * ethcore: prepare for the real goerli to launch * Implement NOTURN wiggle properly & cleanupnup warnings * Implement vote casting * Update docs & skip signing if no signer * Optimize step-service interval * Record state on local sealed block * Fix script filemode * Cleaning up codebase * restore enact trace logging * Delete clique.sh and move sync.sh * remove travis.yml * Remove dead code * Cleanup compile warning * address review comments * adding more comments and removing unwrap() * ci: remove sync script * Address review comments * fix compile error * adding better debugging for timing * Implement an dedicated thread for sealing timing * fix(add helper for timestamp overflows) (#10330) * fix(add helper timestamp overflows) * fix(simplify code) * fix(make helper private) * snap: official image / test (#10168) * official image / test * fix / test * bit more necromancy * fix paths * add source bin/df /test * add source bin/df /test2 * something w paths /test * something w paths /test * add source-type /test * show paths /test * copy plugin /test * plugin -> nil * install rhash * no questions while installing rhash * publish snap only for release * fix(docker): fix not receives SIGINT (#10059) * fix(docker): fix not receives SIGINT * fix: update with reviews * update with review * update * update * Don't add discovery initiators to the node table (#10305) * Don't add discovery initiators to the node table * Use enums for tracking state of the nodes in discovery * Dont try to ping ourselves * Fix minor nits * Update timeouts when observing an outdated node * Extracted update_bucket_record from update_node * Fixed typo * Fix two final nits from @todr * change docker image based on debian instead of ubuntu due to the chan… (#10336) * change docker image based on debian instead of ubuntu due to the changes of the build container * role back docker build image and docker deploy image to ubuntu:xenial based (#10338) * Bundle protocol and packet_id together in chain sync (#10315) Define a new `enum` where devp2p subprotocol packet ids (currently eth and par) are defined. Additionally provide functionality to query id value and protocol of a given id object. * snap: prefix version and populate candidate channel (#10343) * snap: populate candidate releases with beta snaps to avoid stale channel * snap: prefix version with v* * addressing review comments * engine: fix copyright header * scripts: restore permissions on sign command * ethcore: enforce tabs * ethcore: enforce tabs * ethcore: enforce tabs * addressing comments * addressing comments * addressing more comments * addressing more comments * addressing more comments * addressing more comments * addressing more comments * json-spec: fix clique epoch to non-zero u64 * ci: enable travis for parity goerli * ci: don't separate build and test step * ci: don't run c++ tests on travis * ci: simplify cargo test to squeeze into travis timeout * ci: don't run tests on travis at all * style(fixes) * fix(add tests) * fix(recent_signer bug) * fix(complete all tests) * fix(nits) * fix(simplify asserts) * fix(cliqueState): simplify code * fix(nits) * docs(comments what's need to fixed) * fix(revert unintended changes) * fix(tests) * fix(logs): voting logs * fix(readability + more logs) * fix(sync) * docs(add missing licens header) * fix(log): info! -> trace! * docs(fix nits) + fix(remove assert) * perf(use counter instead of vec) * fix(remove needless block in match) * fix(faulty comment) * grumbles(docs for tests) * fix(nits) * fix(revert_vote): only remove vote when votes == 0 * fix(vote counter): checked arithmetics * fix(simplify tests) * fix(nits) * fix(clique): err types * fix(clique utils): make use of errors * fix(cleanup nits) * fix(clique sealing): don't read state no signer * fix(replace Vec with BTreeSet) * fix(tests): BTreeSet and more generic helpers * fix(nits) * fix(ethcore_block_seal): remove needless `Box` * fix(faulty log): info -> trace * fix(checked SystemTime): prevent SystemTime panics * style(chain cfg): space after `:` * style(fn enact): fix whitespace * docs(clique): StepService * docs(nit): fix faulty comment * docs(fix typo) * style(fix bad indentation) * fix(bad regex match) * grumble(on_seal_block): make `&mut` to avoid clone * docs(on_seal_block): fix faulty documentation * Delete .travis.yml * docs: remove eth hf references in spec * Update client.rs * fix(nits) * fix(clique step): `RwLock` -> `AtomicBool` * fix(clique): use `Duration::as_millis` * Clean up some Clique documentation * Add trace information to eth_estimateGas (#10519) * Add trace information to eth_estimateGas * replace unwrap better version * change vm::Error formatter to more user-friendly * remove extra error format * use map_or instead sequence of map/unwrap_or * fix(light/on_demand): extract as a trait * fix(grumble): OnDemand remove needless trait bound * Initial support sccache for windows build (#10520) * Initial support sccache for win build * show sccache stats * cache paths for shared runners * sccache status is in the script. * removed windows test for now * ethcore: remove eth social and easthub chain configs (#10531) * Fix max_gas (#10537) Fix max_gas * fix(bump dependencies) (#10540) * cargo update -p log:0.4.5 * cargo update -p regex:1.0.5 * cargo update -p parking_lot * cargo update -p serde_derive * cargo update -p serde_json * cargo update -p serde * cargo update -p lazy_static * cargo update -p num_cpus * cargo update -p toml * separate docker image to build docs (#10543) * updated lru-cache to 0.1.2 (#10542) * clique: make state backfill time measurement more accurate (#10551) * build android with cache, win fixes (#10546) * build android with cache! * windows fixes * windows fixes 2 * windows fixes 3 * windows fixes 4 * windows should have sccache variables in env variables * Implement caching for service transactions checker (#10088) * Tx permission contract improvement * Take in account zero gas price certification when doing transact_contract * DRY in ServiceTransactionChecker * Fix typos and regroup mod * Introduce CertifiedAddressesCache * Introduce refresh_cache for CertifiedAddressesCache * Add CertifiedAddressesCache read and write on checking * Refresh CertifiedAddressesCache on new imported block * Separate ChainInfo trait and fix errors after merge * Do not fire an error when service txes contract does not exist * WIP: Shared certified addresses cache between miner and client + use HashMap instead of BTreeMap * Refactor refresh_cache for ServiceTransactionChecker * Refresh cache fixes * Add cache read in check_address + log when cache is used + improve code * Remove ChainInfo from ServiceTransaction dependencies * DRY ServiceTransactionChecker * Fix Client and Miner in tests * Fix node_filter test * Fix Client::new in add_peer_with_private_config * WIP: Separated ChainNotify from ethcore trait and implemented ChainNotify for ServiceTransactionChecker * Fix watcher test * Revert "Merge branch 'master' into master" This reverts commit 4e7371dc109d022efe3087defc33d827998ce648, reversing changes made to bffd73e5fd58a516bbf404281b51cf26422e181e. * Revert "Fix watcher test" This reverts commit bffd73e5fd58a516bbf404281b51cf26422e181e. * Revert "WIP: Separated ChainNotify from ethcore trait and implemented ChainNotify for ServiceTransactionChecker" This reverts commit 6e73d1e61fa15dc10ffd4fab63df29eabe9c3b3a. * Revert "Fix Client::new in add_peer_with_private_config" This reverts commit ec610a30bee95588d58b79edcc9e43c2ff90f1ad. * Revert "Fix node_filter test" This reverts commit 06a4b2de86317c902f579e912b40de0b0fbf6d78. * Revert "Fix Client and Miner in tests" This reverts commit 51bbad330ea6e7bdfc1516208cc8705d5d11516d. * Implement ServiceTransactionChecker in miner and delegate it to client + revert unnecessary changes * Merge master * Code improvements * Merge branch 'master' of https://github.com/paritytech/parity-ethereum # Conflicts: # Cargo.lock # ethcore/private-tx/src/lib.rs # ethcore/src/miner/miner.rs # ethcore/src/miner/pool_client.rs * fix(light eth_gasPrice): ask network if not in cache (#10535) * fix(light eth_gasPrice): ask N/W if not in cache * fix(bad rebase) * Update light client harcoded headers (#10547) * kovan #10643457 * ropsten #5296129 * foundation #7460865 * classic #7747585 * indentation * morden #3973121 * fix(light account response): update `tx_queue` (#10545) * tx-pool: check transaction readiness before replacing (#10526) * Update to vanilla tx pool error * Prevent a non ready tx replacing a ready tx * Make tests compile * Test ready tx not replaced by future tx * Transaction indirection * Use StateReadiness to calculate Ready in `should_replace` * Test existing txs from same sender are used to compute Readiness * private-tx: Wire up ShouldReplace * Revert "Use StateReadiness to calculate Ready in `should_replace`" This reverts commit af9e69c8 * Make replace generic so it works with private-tx * Rename Replace and add missing docs * ShouldReplace no longer mutable * tx-pool: update to transaction-pool 2.0 from crates.io * tx-pool: generic error type alias * Exit early for first unmatching nonce * Fix private-tx test, use existing write lock * Use read lock for pool scoring * version: betalize 2.5 * beta backports (#10576) * Reject crazy timestamps instead of truncating. * fix(light cull): poll light cull instead of timer (#10559) * fix(light cull): poll light cull instead of timer * fix(grumbles): remove error + updated docs * fix(on-demand request): `expect()` reason * docs(remove misleading info) * beta 2.5.1 (#10643) * version: bump beta to 2.5.1 * fix(whisper expiry): current time + work + ttl (#10587) * update bootnodes (#10595) * config: update goerli bootnodes * config: update kotti bootnodes * adds rpc error message for --no-ancient-blocks (#10608) * adds error message for --no-ancient-blocks, closes #10261 * Apply suggestions from code review Co-Authored-By: seunlanlege * Constantinople HF on POA Core (#10606) * Constantinople HF on POA Core Plan Constantinople/St.Petersfork HF on POA Core network at block 8582254. Original PR in POA repository: https://github.com/poanetwork/poa-chain-spec/pull/110 * Remove extra empty line * evm: add some mulmod benches (#10600) * evm: add blockhash_mulmod bench * evm: use num-bigint for mod ops * Clique: zero-fill extradata when the supplied value is less than 32 bytes in length (#10605) * Update kovan.json to switch validator set to POA Consensus Contracts (#10628) * Fix publish docs (#10635) * Fix publish docs * this never should be forced, either way compiling previous versions will produce outdated docs * fix array, var was moved to the group project global variables list * Fix rinkeby petersburg fork (#10632) * ci: publish docs debug (#10638) (#10660) * beta ci: backport missing diff from master (#10661) * ci: publish docs debug (#10638) * ci: backport missing diff from master * backports for beta 2.5.2 (#10737) * version: bump beta to 2.5.2 * [CI] allow cargo audit to fail (#10676) * [CI] allow cargo audit to fail * [.gitlab-ci.yml] add a comment about cargo audit * [Cargo.lock] cargo update -p protobuf * Reset blockchain properly (#10669) * delete BlockDetails from COL_EXTRA * better proofs * added tests * PR suggestions * new image (#10673) * Update publishing (#10644) * docker images are now built on k8s: test run * copy check_sync.sh in build-linux job * copy scripts/docker/hub/* in build-linux job * removed cache var * cleanup, no more nightly dockers * cleanup in dockerfile * some new tags * removed sccsche debug log, cleanup * no_gits, new artifacts dir, changed scripts. Test run. * define version once * one source for TRACK * stop kovan onchain updates * moved changes for two images to a new branch * rename Dockerfile * no need in libudev-dev * enable lto for release builds (#10717) * Use RUSTFLAGS to set the optimization level (#10719) * Use RUSTFLAGS to set the optimization level Cargo has a [quirk]() in how configuration settings are propagated when `cargo test` runs: local code respect the settings in `[profile.test]` but all dependencies use the `[profile.dev]` settings. Here we force `opt-level=3` for all dependencies. * Remove unused profile settings * Maybe like this? * Turn off incremental compilation * Remove colors; try again with overflow-checks on * Use quiet CI machine * Turn overflow checking back on * Be explicit about what options we use * Remove "quiet machine" override * ethcore: enable ECIP-1054 for classic (#10731) * config: enable atlantis on ethereum classic * config: enable atlantis on morden classic * config: enable atlantis on morden classic * config: enable atlantis on kotti classic * ethcore: move kotti fork block to 0xAEF49 * ethcore: move morden fork block to 0x4829BA * ethcore: move classic fork block to 0x81B320 * remove trailing comma * remove trailing comma * fix chainspec * ethcore: move classic fork block to 0x7fffffffffffffff * Beta 2.5.3 (#10776) * ethcore/res: activate atlantis classic hf on block 8772000 (#10766) * fix docker tags for publishing (#10741) * fix: aura don't add `SystemTime::now()` (#10720) This commit does the following: - Prevent overflow in `verify_timestamp()` by not adding `now` to found faulty timestamp - Use explicit `CheckedSystemTime::checked_add` to prevent potential consensus issues because SystemTime is platform depedent - remove `#[cfg(not(time_checked_add))]` conditional compilation * Update version * Treat empty account the same as non-exist accounts in EIP-1052 (#10775) * DevP2p: Get node IP address and udp port from Socket, if not included in PING packet (#10705) * get node IP address and udp port from Socket, if not included in PING packet * prevent bootnodes from being added to host nodes * code corrections * code corrections * code corrections * code corrections * docs * code corrections * code corrections * Apply suggestions from code review Co-Authored-By: David * Add a way to signal shutdown to snapshotting threads (#10744) * Add a way to signal shutdown to snapshotting threads * Pass Progress to fat_rlps() so we can abort from there too. * Checking for abort in a single spot * Remove nightly-only weak/strong counts * fix warning * Fix tests * Add dummy impl to abort snapshots * Add another dummy impl for TestSnapshotService * Remove debugging code * Return error instead of the odd Ok(()) Switch to AtomicU64 * revert .as_bytes() change * fix build * fix build maybe * Beta 2.5.4 (#10827) * cargo update -p smallvec (#10822) Fixes https://github.com/servo/rust-smallvec/issues/148 * Update version to v2.5.3 Signed-off-by: Martin Pugh * version: stabilise v2.5 (#10857) * V2.5.6 stable (#10961) - Fix cargo audit (#10921) - Add support for Energy Web Foundation's new chains (#10957) - Kaspersky AV whitelisting (#10919) - Avast whitelist script (#10900) - Docker images renaming (#10863) - Remove excessive warning (#10831) - Allow --nat extip:your.host.here.org (#10830) - When updating the client or when called from RPC, sleep should mean sleep (#10814) - added new ropsten-bootnode and removed old one (#10794) - ethkey no longer uses byteorder (#10786) - Do not drop the peer with None difficulty (#10772) - docs: Update Readme with TOC, Contributor Guideline. Update Cargo package descriptions (#10652) * v2.5.7 stable (#11006) * [trace] check mem diff within range (#11002) * Update version (v2.5.7-stable) * v2.5.8-stable (#11041) * add more tx tests (#11038) * Fix parallel transactions race-condition (#10995) * Add blake2_f precompile (#11017) * [trace] introduce trace failed to Ext (#11019) * Edit publish-onchain.sh to use https (#11016) * Fix deadlock in network-devp2p (#11013) * EIP 1108: Reduce alt_bn128 precompile gas costs (#11008) * xDai chain support and nodes list update (#10989) * EIP 2028: transaction gas lowered from 68 to 16 (#10987) * EIP-1344 Add CHAINID op-code (#10983) * manual publish jobs for releases, no changes for nightlies (#10977) * [blooms-db] Fix benchmarks (#10974) * Verify transaction against its block during import (#10954) * Better error message for rpc gas price errors (#10931) * tx-pool: accept local tx with higher gas price when pool full (#10901) * Fix fork choice (#10837) * Cleanup unused vm dependencies (#10787) * Fix compilation on recent nightlies (#10991) * Don't build rpc with ethcore test-helpers (#11048) * v2.5.8-stable (rev2) (#11051) * EIP 1884 Re-pricing of trie-size dependent operations (#10992) * Implement EIP-1283 reenable transition, EIP-1706 and EIP-2200 (#10191) * update CHANGELOG.md (#11057) * v2.5.9-stable (#11089) * ethcore/res: activate Istanbul on Ropsten, Görli, Rinkeby, Kovan (#11068) * ethcore/res: activate Istanbul on Ropsten block 6485846 * ethcore/res: activate Istanbul on Goerli block 1561651 * ethcore/res: use hex values for Istanbul specs * ethcore/res: fix trailing comma * ethcore/res: be pedantic about EIP-1283 in Petersburg and Istanbul test specs * ethcore/res: activate Istanbul on Rinkeby block 5435345 * ethcore/res: activate Istanbul on Kovan block 14111141 * ethcore/res: fix kovan istanbul number to 0xd751a5 * [json-spec] make blake2 pricing spec more readable (#11034) * [json-spec] make blake2 pricing spec more readable * [ethcore] fix compilation * Manual backport of #11033 * Update CHANGELOG.md and version (#11093) * Update CHANGELOG.md and version --- .github/CONTRIBUTING.md | 37 +- .gitlab-ci.yml | 295 +- CHANGELOG.md | 414 +- Cargo.lock | 2633 ++--- Cargo.toml | 30 +- README.md | 249 +- accounts/Cargo.toml | 28 + accounts/ethkey/Cargo.toml | 6 +- accounts/ethkey/README.md | 4 +- accounts/ethkey/cli/Cargo.toml | 3 +- accounts/ethkey/cli/src/main.rs | 2 +- accounts/ethkey/src/extended.rs | 5 +- accounts/ethkey/src/lib.rs | 1 - accounts/ethstore/Cargo.toml | 6 +- accounts/ethstore/README.md | 2 +- accounts/ethstore/cli/Cargo.toml | 1 + accounts/ethstore/cli/src/main.rs | 2 +- accounts/ethstore/src/account/crypto.rs | 21 +- accounts/ethstore/src/account/kdf.rs | 3 +- accounts/ethstore/src/account/safe_account.rs | 21 +- accounts/ethstore/src/accounts_dir/disk.rs | 20 +- accounts/ethstore/src/accounts_dir/mod.rs | 5 +- accounts/ethstore/src/accounts_dir/vault.rs | 18 +- accounts/ethstore/src/ethstore.rs | 18 +- accounts/ethstore/src/json/kdf.rs | 3 +- accounts/ethstore/src/json/vault_file.rs | 9 +- accounts/ethstore/src/json/vault_key_file.rs | 9 +- accounts/ethstore/src/lib.rs | 2 + accounts/ethstore/src/presale.rs | 4 +- accounts/src/account_data.rs | 73 + accounts/src/error.rs | 56 + .../mod.rs => accounts/src/lib.rs | 126 +- .../src}/stores.rs | 20 +- chainspec/Cargo.toml | 1 + cli-signer/Cargo.toml | 5 +- cli-signer/rpc-client/Cargo.toml | 9 +- cli-signer/rpc-client/src/lib.rs | 1 + cli-signer/rpc-client/src/signer_client.rs | 3 +- cli-signer/src/lib.rs | 4 +- docs/CHANGELOG-2.0.md | 2 +- docs/CHANGELOG-2.1.md | 24 +- docs/CHANGELOG-2.2.md | 392 + docs/CHANGELOG-2.3.md | 288 + docs/CHANGELOG-2.4.md | 128 + ethash/Cargo.toml | 13 +- ethash/benches/basic.rs | 28 +- ethash/benches/progpow.rs | 86 + ethash/res/progpow_testvectors.json | 86 + ethash/src/cache.rs | 8 +- ethash/src/compute.rs | 109 +- ethash/src/lib.rs | 69 +- ethash/src/progpow.rs | 595 ++ ethcore/Cargo.toml | 32 +- ethcore/blockchain/Cargo.toml | 10 +- ethcore/blockchain/src/blockchain.rs | 86 +- ethcore/blockchain/src/generator.rs | 33 +- ethcore/blockchain/src/lib.rs | 2 +- ethcore/call-contract/Cargo.toml | 1 + ethcore/evm/Cargo.toml | 3 + ethcore/evm/benches/basic.rs | 52 +- ethcore/evm/src/evm.rs | 18 +- ethcore/evm/src/factory.rs | 2 +- ethcore/evm/src/instructions.rs | 13 +- ethcore/evm/src/interpreter/gasometer.rs | 3 + ethcore/evm/src/interpreter/mod.rs | 120 +- ethcore/evm/src/lib.rs | 3 + ethcore/evm/src/tests.rs | 49 +- ethcore/light/Cargo.toml | 9 +- ethcore/light/src/cht.rs | 12 +- ethcore/light/src/client/mod.rs | 25 + ethcore/light/src/lib.rs | 7 +- ethcore/light/src/on_demand/mod.rs | 163 +- ethcore/light/src/on_demand/request.rs | 8 +- ethcore/light/src/on_demand/tests.rs | 2 +- ethcore/light/src/types/request/batch.rs | 59 + ethcore/light/src/types/request/mod.rs | 4 +- ethcore/node-filter/Cargo.toml | 2 +- ethcore/private-tx/Cargo.toml | 8 +- ethcore/private-tx/res/keys_acl.json | 43 + ethcore/private-tx/src/encryptor.rs | 70 +- ethcore/private-tx/src/error.rs | 297 +- ethcore/private-tx/src/key_server_keys.rs | 173 + ethcore/private-tx/src/lib.rs | 216 +- .../private-tx/src/private_transactions.rs | 15 +- ethcore/private-tx/tests/private_contract.rs | 136 +- ethcore/res/authority_round.json | 47 +- ...authority_round_block_reward_contract.json | 47 +- ethcore/res/basic_authority.json | 47 +- ethcore/res/constructor.json | 47 +- ethcore/res/ethereum/byzantium_test.json | 44 +- ethcore/res/ethereum/callisto.json | 47 +- ethcore/res/ethereum/classic.json | 229 +- ethcore/res/ethereum/constantinople_test.json | 44 +- ethcore/res/ethereum/easthub.json | 87 - ethcore/res/ethereum/eip210_test.json | 44 +- ethcore/res/ethereum/ellaism.json | 44 +- ethcore/res/ethereum/ewc.json | 213 + ethcore/res/ethereum/expanse.json | 44 +- ethcore/res/ethereum/foundation.json | 122 +- ethcore/res/ethereum/goerli.json | 936 ++ ethcore/res/ethereum/istanbul_test.json | 120 + ethcore/res/ethereum/kotti.json | 907 ++ ethcore/res/ethereum/kovan.json | 182 +- ethcore/res/ethereum/kovan_wasm_test.json | 44 +- ethcore/res/ethereum/mcip3_test.json | 47 +- ethcore/res/ethereum/mix.json | 44 +- ethcore/res/ethereum/morden.json | 2025 +++- ethcore/res/ethereum/musicoin.json | 47 +- ethcore/res/ethereum/poacore.json | 53 +- ethcore/res/ethereum/poasokol.json | 46 +- ethcore/res/ethereum/rinkeby.json | 919 ++ ethcore/res/ethereum/ropsten.json | 140 +- ethcore/res/ethereum/social.json | 8854 ----------------- ethcore/res/ethereum/st_peters_test.json | 45 +- ethcore/res/ethereum/tobalaba.json | 80 - ethcore/res/ethereum/transition_test.json | 45 +- ethcore/res/ethereum/volta.json | 207 + ethcore/res/ethereum/xdai.json | 157 + ethcore/res/instant_seal.json | 47 +- ethcore/res/null.json | 47 +- ethcore/service/Cargo.toml | 1 + ethcore/service/src/error.rs | 9 +- ethcore/service/src/service.rs | 38 +- ethcore/src/account_db.rs | 35 +- ethcore/src/block.rs | 169 +- ethcore/src/builtin.rs | 619 +- ethcore/src/client/client.rs | 221 +- ethcore/src/client/evm_test_client.rs | 89 +- ethcore/src/client/mod.rs | 5 +- ethcore/src/client/test_client.rs | 4 +- ethcore/src/client/traits.rs | 8 +- ethcore/src/engines/authority_round/mod.rs | 209 +- ethcore/src/engines/basic_authority.rs | 35 +- ethcore/src/engines/block_reward.rs | 29 +- ethcore/src/engines/clique/block_state.rs | 367 + ethcore/src/engines/clique/mod.rs | 774 ++ .../src/engines/clique/params.rs | 32 +- ethcore/src/engines/clique/step_service.rs | 77 + ethcore/src/engines/clique/tests.rs | 804 ++ ethcore/src/engines/clique/util.rs | 115 + ethcore/src/engines/instant_seal.rs | 40 +- ethcore/src/engines/mod.rs | 154 +- ethcore/src/engines/null_engine.rs | 24 +- ethcore/src/engines/signer.rs | 83 +- ethcore/src/engines/validator_set/contract.rs | 13 +- ethcore/src/engines/validator_set/multi.rs | 21 +- .../engines/validator_set/safe_contract.rs | 23 +- ethcore/src/error.rs | 23 +- ethcore/src/ethereum/ethash.rs | 41 +- ethcore/src/ethereum/mod.rs | 57 +- ethcore/src/executed.rs | 6 +- ethcore/src/executive.rs | 39 +- ethcore/src/externalities.rs | 16 +- ethcore/src/json_tests/executive.rs | 2 + ethcore/src/json_tests/skip.rs | 7 +- ethcore/src/json_tests/state.rs | 9 +- ethcore/src/json_tests/trie.rs | 5 +- ethcore/src/lib.rs | 37 +- ethcore/src/{machine.rs => machine/impls.rs} | 68 +- ethcore/src/machine/mod.rs | 7 + ethcore/src/machine/traits.rs | 37 + ethcore/src/miner/miner.rs | 310 +- ethcore/src/miner/mod.rs | 12 +- ethcore/src/miner/pool_client.rs | 31 +- ethcore/src/pod_account.rs | 2 +- ethcore/src/snapshot/account.rs | 71 +- ethcore/src/snapshot/consensus/authority.rs | 6 +- ethcore/src/snapshot/consensus/work.rs | 4 +- ethcore/src/snapshot/error.rs | 3 + ethcore/src/snapshot/io.rs | 5 +- ethcore/src/snapshot/mod.rs | 112 +- ethcore/src/snapshot/service.rs | 31 +- ethcore/src/snapshot/tests/helpers.rs | 13 +- .../src/snapshot/tests/proof_of_authority.rs | 12 +- ethcore/src/snapshot/tests/service.rs | 11 +- ethcore/src/snapshot/tests/state.rs | 29 +- ethcore/src/snapshot/traits.rs | 3 + ethcore/src/spec/spec.rs | 79 +- ethcore/src/state/account.rs | 27 +- ethcore/src/state/backend.rs | 56 +- ethcore/src/state/mod.rs | 77 +- ethcore/src/state_db.rs | 53 +- ethcore/src/test_helpers.rs | 20 +- ethcore/src/tests/client.rs | 25 +- ethcore/src/tests/trace.rs | 6 +- ethcore/src/trace/executive_tracer.rs | 34 +- ethcore/src/trace/mod.rs | 3 + ethcore/src/trace/types/filter.rs | 42 +- ethcore/src/trace/types/trace.rs | 2 +- ethcore/src/verification/verification.rs | 45 +- ethcore/sync/Cargo.toml | 12 +- ethcore/sync/src/api.rs | 84 +- ethcore/sync/src/block_sync.rs | 21 +- ethcore/sync/src/chain/handler.rs | 99 +- ethcore/sync/src/chain/mod.rs | 45 +- ethcore/sync/src/chain/propagator.rs | 71 +- ethcore/sync/src/chain/requester.rs | 41 +- ethcore/sync/src/chain/supplier.rs | 184 +- ethcore/sync/src/chain/sync_packet.rs | 141 + ethcore/sync/src/lib.rs | 4 +- ethcore/sync/src/sync_io.rs | 22 +- ethcore/sync/src/tests/consensus.rs | 13 +- ethcore/sync/src/tests/helpers.rs | 36 +- ethcore/sync/src/tests/private.rs | 36 +- ethcore/sync/src/tests/snapshot.rs | 2 + ethcore/types/Cargo.toml | 8 +- ethcore/types/src/engines/epoch.rs | 25 - ethcore/types/src/header.rs | 57 +- ethcore/types/src/ids.rs | 2 +- ethcore/types/src/lib.rs | 1 - ethcore/types/src/restoration_status.rs | 2 +- ethcore/types/src/transaction/error.rs | 16 +- ethcore/types/src/transaction/transaction.rs | 20 +- ethcore/vm/Cargo.toml | 4 +- ethcore/vm/src/env_info.rs | 2 +- ethcore/vm/src/ext.rs | 9 +- ethcore/vm/src/lib.rs | 1 - ethcore/vm/src/return_data.rs | 6 +- ethcore/vm/src/schedule.rs | 38 +- ethcore/vm/src/tests.rs | 21 +- ethcore/wasm/Cargo.toml | 1 + ethcore/wasm/run/Cargo.toml | 1 + evmbin/Cargo.toml | 2 +- evmbin/README.md | 2 +- evmbin/src/info.rs | 6 +- evmbin/src/main.rs | 7 +- ipfs/Cargo.toml | 6 +- ipfs/src/lib.rs | 26 +- json/Cargo.toml | 1 + json/src/lib.rs | 1 - json/src/misc/mod.rs | 52 - json/src/spec/builtin.rs | 37 + json/src/spec/clique.rs | 57 + json/src/spec/engine.rs | 18 +- json/src/spec/ethash.rs | 5 + json/src/spec/mod.rs | 2 + json/src/spec/params.rs | 10 + json/src/spec/spec.rs | 1 + machine/Cargo.toml | 8 - machine/src/lib.rs | 135 - miner/Cargo.toml | 4 +- miner/src/gas_pricer.rs | 2 +- miner/src/lib.rs | 1 + .../src/local_accounts.rs | 39 +- miner/src/pool/listener.rs | 2 +- miner/src/pool/local_transactions.rs | 2 +- miner/src/pool/mod.rs | 3 +- miner/src/pool/queue.rs | 28 +- miner/src/pool/replace.rs | 513 + miner/src/pool/scoring.rs | 171 - miner/src/pool/tests/mod.rs | 18 +- miner/src/pool/verifier.rs | 6 +- miner/src/service_transaction_checker.rs | 58 +- miner/stratum/Cargo.toml | 5 +- miner/stratum/src/lib.rs | 4 +- parity-clib/Cargo.toml | 2 +- parity-clib/Parity.java | 8 +- parity-clib/examples/cpp/CMakeLists.txt | 2 +- parity-clib/examples/cpp/main.cpp | 9 +- parity-clib/examples/java/Main.java | 12 +- parity-clib/parity.h | 32 +- parity-clib/src/java.rs | 115 +- parity-clib/src/lib.rs | 200 +- parity/account.rs | 166 +- parity/account_utils.rs | 244 + parity/blockchain.rs | 50 +- parity/cli/mod.rs | 27 +- parity/cli/tests/config.full.toml | 1 + parity/cli/usage.rs | 21 +- parity/cli/usage_header.txt | 7 +- parity/cli/version.txt | 9 +- parity/configuration.rs | 97 +- parity/helpers.rs | 27 +- parity/informant.rs | 4 +- parity/lib.rs | 56 +- parity/light_helpers/epoch_fetch.rs | 4 +- parity/light_helpers/mod.rs | 2 - parity/light_helpers/queue_cull.rs | 105 - parity/logger/Cargo.toml | 2 +- parity/logger/src/lib.rs | 2 +- parity/main.rs | 48 +- parity/params.rs | 66 +- parity/presale.rs | 34 +- parity/rpc.rs | 2 +- parity/rpc_apis.rs | 197 +- parity/run.rs | 210 +- parity/secretstore.rs | 7 +- parity/snapshot.rs | 6 +- parity/upgrade.rs | 13 +- rabbitmq/Cargo.toml | 2 +- rpc/Cargo.toml | 42 +- rpc/src/authcodes.rs | 12 +- rpc/src/http_common.rs | 2 +- rpc/src/lib.rs | 60 +- rpc/src/tests/helpers.rs | 6 +- rpc/src/tests/http_client.rs | 22 +- rpc/src/tests/rpc.rs | 27 + rpc/src/tests/ws.rs | 4 +- rpc/src/v1/extractors.rs | 20 +- rpc/src/v1/helpers/deprecated.rs | 111 + rpc/src/v1/helpers/dispatch.rs | 879 -- rpc/src/v1/helpers/dispatch/full.rs | 151 + rpc/src/v1/helpers/dispatch/light.rs | 299 + rpc/src/v1/helpers/dispatch/mod.rs | 380 + .../v1/helpers/dispatch/prospective_signer.rs | 152 + rpc/src/v1/helpers/dispatch/signing.rs | 156 + rpc/src/v1/helpers/engine_signer.rs | 48 + rpc/src/v1/helpers/errors.rs | 90 +- .../{signer.rs => external_signer/mod.rs} | 32 +- .../helpers/{ => external_signer}/oneshot.rs | 2 +- .../{ => external_signer}/signing_queue.rs | 31 +- rpc/src/v1/helpers/fake_sign.rs | 16 +- rpc/src/v1/helpers/ipfs.rs | 2 +- rpc/src/v1/helpers/light_fetch.rs | 246 +- rpc/src/v1/helpers/mod.rs | 17 +- rpc/src/v1/helpers/requests.rs | 3 +- rpc/src/v1/helpers/secretstore.rs | 3 +- rpc/src/v1/helpers/signature.rs | 18 +- rpc/src/v1/helpers/subscribers.rs | 7 +- rpc/src/v1/helpers/subscription_manager.rs | 2 +- rpc/src/v1/helpers/work.rs | 23 +- rpc/src/v1/impls/debug.rs | 11 +- rpc/src/v1/impls/eth.rs | 285 +- rpc/src/v1/impls/eth_filter.rs | 33 +- rpc/src/v1/impls/eth_pubsub.rs | 57 +- rpc/src/v1/impls/light/eth.rs | 281 +- rpc/src/v1/impls/light/net.rs | 2 +- rpc/src/v1/impls/light/parity.rs | 159 +- rpc/src/v1/impls/light/parity_set.rs | 20 +- rpc/src/v1/impls/light/trace.rs | 11 +- rpc/src/v1/impls/mod.rs | 8 + rpc/src/v1/impls/parity.rs | 109 +- rpc/src/v1/impls/parity_accounts.rs | 139 +- rpc/src/v1/impls/parity_set.rs | 87 +- rpc/src/v1/impls/personal.rs | 92 +- rpc/src/v1/impls/private.rs | 31 +- rpc/src/v1/impls/pubsub.rs | 9 +- rpc/src/v1/impls/rpc.rs | 4 +- rpc/src/v1/impls/secretstore.rs | 5 +- rpc/src/v1/impls/signer.rs | 58 +- rpc/src/v1/impls/signing.rs | 73 +- rpc/src/v1/impls/signing_unsafe.rs | 55 +- rpc/src/v1/impls/traces.rs | 31 +- rpc/src/v1/impls/web3.rs | 11 +- rpc/src/v1/informant.rs | 12 +- rpc/src/v1/mod.rs | 8 +- rpc/src/v1/tests/eth.rs | 39 +- rpc/src/v1/tests/helpers/miner_service.rs | 40 +- rpc/src/v1/tests/helpers/snapshot_service.rs | 1 + rpc/src/v1/tests/helpers/sync_provider.rs | 5 +- rpc/src/v1/tests/mocked/eth.rs | 200 +- rpc/src/v1/tests/mocked/manage_network.rs | 4 +- rpc/src/v1/tests/mocked/mod.rs | 6 + rpc/src/v1/tests/mocked/parity.rs | 50 +- rpc/src/v1/tests/mocked/parity_accounts.rs | 50 +- rpc/src/v1/tests/mocked/parity_set.rs | 63 +- rpc/src/v1/tests/mocked/personal.rs | 14 +- rpc/src/v1/tests/mocked/secretstore.rs | 5 +- rpc/src/v1/tests/mocked/signer.rs | 42 +- rpc/src/v1/tests/mocked/signing.rs | 36 +- rpc/src/v1/tests/mocked/signing_unsafe.rs | 237 + rpc/src/v1/tests/mocked/web3.rs | 6 +- rpc/src/v1/traits/debug.rs | 14 +- rpc/src/v1/traits/eth.rs | 373 +- rpc/src/v1/traits/eth_pubsub.rs | 33 +- rpc/src/v1/traits/eth_signing.rs | 50 +- rpc/src/v1/traits/mod.rs | 4 +- rpc/src/v1/traits/net.rs | 28 +- rpc/src/v1/traits/parity.rs | 428 +- rpc/src/v1/traits/parity_accounts.rs | 260 +- rpc/src/v1/traits/parity_set.rs | 197 +- rpc/src/v1/traits/parity_signing.rs | 68 +- rpc/src/v1/traits/personal.rs | 105 +- rpc/src/v1/traits/private.rs | 38 +- rpc/src/v1/traits/pubsub.rs | 35 +- rpc/src/v1/traits/rpc.rs | 28 +- rpc/src/v1/traits/secretstore.rs | 77 +- rpc/src/v1/traits/signer.rs | 72 +- rpc/src/v1/traits/traces.rs | 70 +- rpc/src/v1/traits/web3.rs | 23 +- rpc/src/v1/types/account_info.rs | 4 +- rpc/src/v1/types/block.rs | 43 +- rpc/src/v1/types/block_number.rs | 2 +- rpc/src/v1/types/call_request.rs | 5 +- rpc/src/v1/types/confirmations.rs | 16 +- rpc/src/v1/types/consensus_status.rs | 4 +- rpc/src/v1/types/derivation.rs | 5 +- rpc/src/v1/types/eip191.rs | 4 +- rpc/src/v1/types/eth_types.rs | 84 + rpc/src/v1/types/filter.rs | 16 +- rpc/src/v1/types/hash.rs | 165 - rpc/src/v1/types/histogram.rs | 2 +- rpc/src/v1/types/log.rs | 14 +- rpc/src/v1/types/mod.rs | 7 +- rpc/src/v1/types/private_receipt.rs | 11 +- rpc/src/v1/types/provenance.rs | 2 +- rpc/src/v1/types/pubsub.rs | 11 +- rpc/src/v1/types/receipt.rs | 29 +- rpc/src/v1/types/secretstore.rs | 5 +- rpc/src/v1/types/sync.rs | 10 +- rpc/src/v1/types/trace.rs | 56 +- rpc/src/v1/types/trace_filter.rs | 3 +- rpc/src/v1/types/transaction.rs | 43 +- rpc/src/v1/types/transaction_request.rs | 25 +- rpc/src/v1/types/uint.rs | 172 - rpc/src/v1/types/work.rs | 2 +- scripts/docker/debian/Dockerfile | 2 +- scripts/docker/hub/Dockerfile | 44 +- scripts/docker/hub/publish-docker.sh | 67 + scripts/gitlab/build-linux.sh | 56 + scripts/gitlab/build-windows.sh | 15 +- scripts/gitlab/publish-av-whitelists.sh | 25 + scripts/gitlab/publish-docker.sh | 22 - scripts/gitlab/publish-docs.sh | 11 +- scripts/gitlab/publish-snap.sh | 16 +- .../gitlab/{test-all.sh => rust-changes.sh} | 4 +- scripts/gitlab/test-cpp.sh | 17 + scripts/gitlab/test-linux.sh | 18 + scripts/gitlab/validate-chainspecs.sh | 19 + scripts/validate_chainspecs.sh | 14 - secret-store/Cargo.toml | 40 +- secret-store/src/key_server.rs | 37 +- .../servers_set_change_session.rs | 432 +- .../admin_sessions/share_add_session.rs | 522 +- .../client_sessions/generation_session.rs | 490 +- .../client_sessions/signing_session_ecdsa.rs | 243 +- .../signing_session_schnorr.rs | 443 +- .../src/key_server_cluster/cluster.rs | 1569 +-- .../key_server_cluster/cluster_connections.rs | 176 + .../cluster_connections_net.rs | 539 + .../cluster_message_processor.rs | 357 + .../key_server_cluster/cluster_sessions.rs | 44 +- .../key_server_cluster/connection_trigger.rs | 36 +- .../connection_trigger_with_migration.rs | 76 +- secret-store/src/key_server_cluster/mod.rs | 6 +- secret-store/src/lib.rs | 7 +- secret-store/src/listener/http_listener.rs | 2 +- secret-store/src/node_key_pair.rs | 79 +- .../key_server_cluster/cluster_connections.rs | 176 + .../cluster_connections_net.rs | 539 + .../cluster_message_processor.rs | 357 + util/EIP-152/Cargo.toml | 14 + util/EIP-152/src/lib.rs | 192 + util/blooms-db/benches/blooms.rs | 16 +- util/blooms-db/src/db.rs | 2 +- util/fetch/Cargo.toml | 2 +- util/journaldb/Cargo.toml | 4 +- util/journaldb/src/archivedb.rs | 50 +- util/journaldb/src/as_hash_db_impls.rs | 43 +- util/journaldb/src/earlymergedb.rs | 49 +- util/journaldb/src/lib.rs | 13 +- util/journaldb/src/overlaydb.rs | 14 +- util/journaldb/src/overlayrecentdb.rs | 54 +- util/journaldb/src/refcounteddb.rs | 11 +- util/journaldb/src/traits.rs | 21 +- util/keccak-hasher/Cargo.toml | 2 +- util/keccak-hasher/src/lib.rs | 4 +- util/memzero/Cargo.toml | 6 + util/network-devp2p/Cargo.toml | 2 +- util/network-devp2p/src/discovery.rs | 29 +- util/network-devp2p/src/host.rs | 21 +- util/network-devp2p/src/node_table.rs | 14 +- util/network-devp2p/src/service.rs | 10 +- util/network-devp2p/src/session.rs | 6 +- util/network-devp2p/tests/tests.rs | 2 +- util/network/Cargo.toml | 6 +- util/network/src/client_version.rs | 515 + util/network/src/error.rs | 4 + util/network/src/lib.rs | 17 +- util/panic-hook/src/lib.rs | 3 +- util/patricia-trie-ethereum/Cargo.toml | 7 +- util/patricia-trie-ethereum/src/lib.rs | 28 +- .../src/rlp_node_codec.rs | 99 +- util/rlp-compress/src/common.rs | 2 +- util/rlp-compress/src/lib.rs | 2 +- util/time-utils/Cargo.toml | 9 + util/time-utils/src/lib.rs | 66 + util/triehash-ethereum/Cargo.toml | 2 +- util/version/Cargo.toml | 3 +- whisper/Cargo.toml | 11 +- whisper/README.md | 9 +- whisper/cli/Cargo.toml | 8 +- whisper/cli/src/main.rs | 61 +- whisper/src/lib.rs | 9 +- whisper/src/message.rs | 49 +- whisper/src/net/mod.rs | 9 +- whisper/src/rpc/filter.rs | 2 +- whisper/src/rpc/mod.rs | 147 +- 488 files changed, 28328 insertions(+), 20989 deletions(-) create mode 100644 accounts/Cargo.toml create mode 100644 accounts/src/account_data.rs create mode 100644 accounts/src/error.rs rename ethcore/src/account_provider/mod.rs => accounts/src/lib.rs (92%) rename {ethcore/src/account_provider => accounts/src}/stores.rs (89%) create mode 100644 docs/CHANGELOG-2.2.md create mode 100644 docs/CHANGELOG-2.3.md create mode 100644 docs/CHANGELOG-2.4.md create mode 100644 ethash/benches/progpow.rs create mode 100644 ethash/res/progpow_testvectors.json create mode 100644 ethash/src/progpow.rs create mode 100644 ethcore/private-tx/res/keys_acl.json create mode 100644 ethcore/private-tx/src/key_server_keys.rs delete mode 100644 ethcore/res/ethereum/easthub.json create mode 100644 ethcore/res/ethereum/ewc.json create mode 100644 ethcore/res/ethereum/goerli.json create mode 100644 ethcore/res/ethereum/istanbul_test.json create mode 100644 ethcore/res/ethereum/kotti.json create mode 100644 ethcore/res/ethereum/rinkeby.json delete mode 100644 ethcore/res/ethereum/social.json delete mode 100644 ethcore/res/ethereum/tobalaba.json create mode 100644 ethcore/res/ethereum/volta.json create mode 100644 ethcore/res/ethereum/xdai.json create mode 100644 ethcore/src/engines/clique/block_state.rs create mode 100644 ethcore/src/engines/clique/mod.rs rename rpc/src/v1/helpers/accounts.rs => ethcore/src/engines/clique/params.rs (60%) create mode 100644 ethcore/src/engines/clique/step_service.rs create mode 100644 ethcore/src/engines/clique/tests.rs create mode 100644 ethcore/src/engines/clique/util.rs rename ethcore/src/{machine.rs => machine/impls.rs} (90%) create mode 100644 ethcore/src/machine/mod.rs create mode 100644 ethcore/src/machine/traits.rs create mode 100644 ethcore/sync/src/chain/sync_packet.rs delete mode 100644 json/src/misc/mod.rs create mode 100644 json/src/spec/clique.rs delete mode 100644 machine/Cargo.toml delete mode 100644 machine/src/lib.rs rename json/src/misc/account_meta.rs => miner/src/local_accounts.rs (56%) create mode 100644 miner/src/pool/replace.rs create mode 100644 parity/account_utils.rs delete mode 100644 parity/light_helpers/queue_cull.rs create mode 100644 rpc/src/v1/helpers/deprecated.rs delete mode 100644 rpc/src/v1/helpers/dispatch.rs create mode 100644 rpc/src/v1/helpers/dispatch/full.rs create mode 100644 rpc/src/v1/helpers/dispatch/light.rs create mode 100644 rpc/src/v1/helpers/dispatch/mod.rs create mode 100644 rpc/src/v1/helpers/dispatch/prospective_signer.rs create mode 100644 rpc/src/v1/helpers/dispatch/signing.rs create mode 100644 rpc/src/v1/helpers/engine_signer.rs rename rpc/src/v1/helpers/{signer.rs => external_signer/mod.rs} (70%) rename rpc/src/v1/helpers/{ => external_signer}/oneshot.rs (98%) rename rpc/src/v1/helpers/{ => external_signer}/signing_queue.rs (93%) create mode 100644 rpc/src/v1/tests/mocked/signing_unsafe.rs create mode 100644 rpc/src/v1/types/eth_types.rs delete mode 100644 rpc/src/v1/types/hash.rs delete mode 100644 rpc/src/v1/types/uint.rs create mode 100755 scripts/docker/hub/publish-docker.sh create mode 100755 scripts/gitlab/build-linux.sh create mode 100755 scripts/gitlab/publish-av-whitelists.sh delete mode 100755 scripts/gitlab/publish-docker.sh rename scripts/gitlab/{test-all.sh => rust-changes.sh} (87%) create mode 100755 scripts/gitlab/test-cpp.sh create mode 100755 scripts/gitlab/test-linux.sh create mode 100755 scripts/gitlab/validate-chainspecs.sh delete mode 100755 scripts/validate_chainspecs.sh create mode 100644 secret-store/src/key_server_cluster/cluster_connections.rs create mode 100644 secret-store/src/key_server_cluster/cluster_connections_net.rs create mode 100644 secret-store/src/key_server_cluster/cluster_message_processor.rs create mode 100644 secret_store/src/key_server_cluster/cluster_connections.rs create mode 100644 secret_store/src/key_server_cluster/cluster_connections_net.rs create mode 100644 secret_store/src/key_server_cluster/cluster_message_processor.rs create mode 100644 util/EIP-152/Cargo.toml create mode 100644 util/EIP-152/src/lib.rs create mode 100644 util/network/src/client_version.rs create mode 100644 util/time-utils/Cargo.toml create mode 100644 util/time-utils/src/lib.rs diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index b51cca8821..6d58aa9412 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -24,7 +24,42 @@ Also, try to include **steps to reproduce** the issue and expand on the **actual If you would like to contribute to Parity Ethereum, please **fork it**, fix bugs or implement features, and [propose a pull request](https://github.com/paritytech/parity-ethereum/compare). -Please, refer to the [Coding Guide](https://wiki.parity.io/Coding-guide) in our wiki for more details about hacking on Parity. +### Labels & Milestones + +We use [labels](https://github.com/paritytech/parity-ethereum/labels) to manage PRs and issues and communicate the state of a PR. Please familiarize yourself with them. Furthermore we are organizing issues in [milestones](https://github.com/paritytech/parity-ethereum/milestones). Best way to get started is to a pick a ticket from the current milestone tagged [`easy`](https://github.com/paritytech/parity-ethereum/labels/Q2-easy%20%F0%9F%92%83) and get going, or [`mentor`](https://github.com/paritytech/parity-ethereum/labels/Q1-mentor%20%F0%9F%95%BA) and get in contact with the mentor offering their support on that larger task. + +### Rules + +There are a few basic ground-rules for contributors (including the maintainer(s) of the project): + +* **No pushing directly to the master branch**. +* **All modifications** must be made in a **pull-request** to solicit feedback from other contributors. +* Pull-requests cannot be merged before CI runs green and two reviewers have given their approval. +* Contributors should adhere to the [Parity Ethereum Style Guide](https://wiki.parity.io/Parity-Ethereum-Style-Guide). + +### Recommendations + +* **Non-master branch names** *should* be prefixed with a short name moniker, followed by the associated Github Issue ID (if any), and a brief description of the task using the format `--` (e.g. `gavin-123-readme`). The name moniker helps people to inquiry about their unfinished work, and the GitHub Issue ID helps your future self and other developers (particularly those who are onboarding) find out about and understand the original scope of the task, and where it fits into Parity Ethereum [Projects](https://github.com/paritytech/parity-ethereum/projects). +* **Remove stale branches periodically** + +### Preparing Pull Requests + +* If your PR does not alter any logic (e.g. comments, dependencies, docs), then it may be tagged [`insubstantial`](https://github.com/paritytech/parity-ethereum/pulls?q=is%3Aopen+is%3Apr+label%3A%22A2-insubstantial+%F0%9F%91%B6%22). + +* Once a PR is ready for review please add the [`pleasereview`](https://github.com/paritytech/parity-ethereum/pulls?utf8=%E2%9C%93&q=is%3Aopen+is%3Apr+label%3A%22A0-pleasereview+%F0%9F%A4%93%22+) label. + +### Reviewing Pull Requests*: + +* At least two reviewers are required to review PRs (even for PRs tagged [`insubstantial`](https://github.com/paritytech/parity-ethereum/pulls?q=is%3Aopen+is%3Apr+label%3A%22A2-insubstantial+%F0%9F%91%B6%22)). + +When doing a review, make sure to look for any: + +* Buggy behavior. +* Undue maintenance burden. +* Breaking with house coding style. +* Pessimization (i.e. reduction of speed as measured in the projects benchmarks). +* Breaking changes should be carefuly reviewed and tagged as such so they end up in the [changelog](../CHANGELOG.md). +* Uselessness (i.e. it does not strictly add a feature or fix a known issue). ## License. diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 73dbf5ce07..e5bcd95960 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,19 +4,15 @@ stages: - publish - optional -image: parity/rust-parity-ethereum-build:xenial +image: parity/parity-ci-linux:latest variables: GIT_STRATEGY: fetch GIT_SUBMODULE_STRATEGY: recursive CI_SERVER_NAME: "GitLab CI" - CARGO_HOME: "${CI_PROJECT_DIR}/.cargo" + CARGO_HOME: "/ci-cache/${CI_PROJECT_NAME}/cargo/${CI_JOB_NAME}" + SCCACHE_DIR: "/ci-cache/${CI_PROJECT_NAME}/sccache" CARGO_TARGET: x86_64-unknown-linux-gnu -.no_git: &no_git - variables: - GIT_STRATEGY: none - GIT_SUBMODULE_STRATEGY: none - .releaseable_branches: # list of git refs for building GitLab artifacts (think "pre-release binaries") only: &releaseable_branches @@ -25,7 +21,6 @@ variables: - tags - schedules - .collect_artifacts: &collect_artifacts artifacts: name: "${CI_JOB_NAME}_${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}" @@ -33,143 +28,291 @@ variables: expire_in: 1 mos paths: - artifacts/ + - tools/ -test-linux: - stage: test +.docker-cache-status: &docker-cache-status variables: - RUN_TESTS: all - script: - - scripts/gitlab/test-all.sh + CARGO_HOME: "/ci-cache/parity-ethereum/cargo/${CI_JOB_NAME}" + dependencies: [] + before_script: + - rustup show + - cargo --version + - SCCACHE_ERROR_LOG=/builds/parity/parity-ethereum/sccache_debug.log + RUST_LOG=sccache=debug + sccache --start-server - sccache -s + after_script: + # sccache debug info + - if test -e sccache_debug.log; + then + echo "_____All crate-types:_____"; + grep 'parse_arguments.*--crate-type' sccache_debug.log | sed -re 's/.*"--crate-type", "([^"]+)".*/\1/' | sort | uniq -c; + echo "_____Non-cacheable reasons:_____"; + grep CannotCache sccache_debug.log | sed -re 's/.*CannotCache\((.+)\).*/\1/' | sort | uniq -c; + else + echo "_____No logs from sccache_____"; + exit 0; + fi tags: - linux-docker -test-audit: +.build-on-linux: &build-on-linux + stage: build + <<: *docker-cache-status + <<: *collect_artifacts + script: + - scripts/gitlab/build-linux.sh + - sccache -s + after_script: + - mkdir -p tools + - cp -r scripts/docker/hub/* ./tools + - cp scripts/gitlab/publish-snap.sh ./tools + - cp scripts/gitlab/publish-onchain.sh ./tools + - cp scripts/gitlab/safe-curl.sh ./tools + - echo v"$(sed -r -n '1,/^version/s/^version\s*=\s*"([^"]+)".*$/\1/p' Cargo.toml)" | + tee ./tools/VERSION + - echo "$(sed -r -n '1,/^track/s/^track\s*=\s*"([^"]+)".*$/\1/p' ./util/version/Cargo.toml)" | + tee ./tools/TRACK + + +cargo-check 0 3: + stage: test + <<: *docker-cache-status + script: + - time cargo check --target $CARGO_TARGET --locked --no-default-features --verbose --color=always + - sccache -s + +cargo-check 1 3: stage: test + <<: *docker-cache-status + script: + - time cargo check --target $CARGO_TARGET --locked --manifest-path util/io/Cargo.toml --no-default-features --verbose --color=always + - sccache -s + +cargo-check 2 3: + stage: test + <<: *docker-cache-status + script: + - time cargo check --target $CARGO_TARGET --locked --manifest-path util/io/Cargo.toml --features "mio" --verbose --color=always + - sccache -s + +cargo-audit: + stage: test + <<: *docker-cache-status script: - - set -e - - set -u - cargo audit - tags: - - linux-docker + allow_failure: true # failed cargo audit shouldn't prevent a PR from being merged -build-linux: &build-linux +validate-chainspecs: + stage: test + <<: *docker-cache-status + script: + - ./scripts/gitlab/validate-chainspecs.sh + - sccache -s + +test-cpp: + stage: build + <<: *docker-cache-status + script: + - ./scripts/gitlab/test-cpp.sh + - sccache -s + +test-linux: + stage: build + <<: *docker-cache-status + script: + - ./scripts/gitlab/test-linux.sh stable + - sccache -s + +test-linux-beta: stage: build only: *releaseable_branches + <<: *docker-cache-status script: - - scripts/gitlab/build-unix.sh + - ./scripts/gitlab/test-linux.sh beta - sccache -s - <<: *collect_artifacts - tags: - - linux-docker + +test-linux-nightly: + stage: build + only: *releaseable_branches + <<: *docker-cache-status + script: + - ./scripts/gitlab/test-linux.sh nightly + - sccache -s + allow_failure: true + +build-android: + <<: *build-on-linux + image: parity/parity-ci-android:stretch + variables: + CARGO_TARGET: armv7-linux-androideabi + +build-linux: + <<: *build-on-linux + # only: *releaseable_branches build-linux-i386: - <<: *build-linux - image: parity/rust-parity-ethereum-build:i386 + <<: *build-on-linux + only: *releaseable_branches + image: parity/parity-ci-i386:latest variables: CARGO_TARGET: i686-unknown-linux-gnu build-linux-arm64: - <<: *build-linux - image: parity/rust-parity-ethereum-build:arm64 + <<: *build-on-linux + only: *releaseable_branches + image: parity/parity-ci-arm64:latest variables: CARGO_TARGET: aarch64-unknown-linux-gnu build-linux-armhf: - <<: *build-linux - image: parity/rust-parity-ethereum-build:armhf + <<: *build-on-linux + only: *releaseable_branches + image: parity/parity-ci-armhf:latest variables: CARGO_TARGET: armv7-unknown-linux-gnueabihf build-darwin: stage: build + <<: *collect_artifacts only: *releaseable_branches variables: CARGO_TARGET: x86_64-apple-darwin + CARGO_HOME: "${CI_PROJECT_DIR}/.cargo" CC: gcc CXX: g++ script: - - scripts/gitlab/build-unix.sh + - scripts/gitlab/build-linux.sh tags: - rust-osx - <<: *collect_artifacts build-windows: stage: build + <<: *collect_artifacts only: *releaseable_branches variables: CARGO_TARGET: x86_64-pc-windows-msvc + CARGO_HOME: "C:/ci-cache/parity-ethereum/cargo/$CI_JOB_NAME" + GIT_SUBMODULE_STRATEGY: none script: - sh scripts/gitlab/build-windows.sh tags: - - rust-windows - <<: *collect_artifacts + - rust-windows publish-docker: stage: publish only: *releaseable_branches - cache: {} + except: + - nightly + when: manual dependencies: - build-linux - tags: - - shell + environment: + name: parity-build + cache: {} + image: docker:stable + services: + - docker:dind + variables: + GIT_STRATEGY: none + DOCKER_HOST: tcp://localhost:2375 + DOCKER_DRIVER: overlay2 + GIT_STRATEGY: none + # DOCKERFILE: tools/Dockerfile + # CONTAINER_IMAGE: parity/parity script: - - scripts/gitlab/publish-docker.sh parity + - ./tools/publish-docker.sh + tags: + - kubernetes-parity-build -publish-snap: &publish-snap +publish-snap-nightly: &publish-snap stage: publish - only: *releaseable_branches + only: + - nightly image: snapcore/snapcraft variables: + GIT_STRATEGY: none BUILD_ARCH: amd64 - cache: {} + cache: {} dependencies: - build-linux tags: - linux-docker script: - - scripts/gitlab/publish-snap.sh - <<: *collect_artifacts + - ./tools/publish-snap.sh + +publish-snap-manually: + <<: *publish-snap + only: *releaseable_branches + when: manual -publish-snap-i386: +publish-snap-i386-nightly: &publish-snap-i386 <<: *publish-snap variables: BUILD_ARCH: i386 + CARGO_TARGET: i686-unknown-linux-gnu dependencies: - build-linux-i386 -publish-snap-arm64: +publish-snap-i386-manually: + <<: *publish-snap-i386 + only: *releaseable_branches + when: manual + +publish-snap-arm64-nightly: &publish-snap-arm64 <<: *publish-snap variables: BUILD_ARCH: arm64 + CARGO_TARGET: aarch64-unknown-linux-gnu dependencies: - build-linux-arm64 -publish-snap-armhf: +publish-snap-arm64-manually: + <<: *publish-snap-arm64 + only: *releaseable_branches + when: manual + +publish-snap-armhf-nightly: &publish-snap-armhf <<: *publish-snap variables: BUILD_ARCH: armhf + CARGO_TARGET: armv7-unknown-linux-gnueabihf dependencies: - build-linux-armhf -publish-onchain: - stage: publish +publish-snap-armhf-manually: + <<: *publish-snap-armhf only: *releaseable_branches + when: manual + +publish-onchain-nightly: &publish-onchain + stage: publish + only: + - nightly cache: {} + variables: + GIT_STRATEGY: none dependencies: - build-linux - build-darwin - build-windows script: - - scripts/gitlab/publish-onchain.sh + - ./tools/publish-onchain.sh tags: - linux-docker -publish-awss3-release: +publish-onchain-manually: + <<: *publish-onchain + only: *releaseable_branches + when: manual + +publish-release-awss3-nightly: &publish-release-awss3 image: parity/awscli:latest stage: publish - only: *releaseable_branches - <<: *no_git + only: + - nightly + variables: + GIT_STRATEGY: none cache: {} dependencies: - build-linux @@ -178,40 +321,52 @@ publish-awss3-release: script: - echo "__________Push binaries to AWS S3____________" - case "${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}" in - (beta|stable|nightly) - export BUCKET=releases.parity.io/ethereum; - ;; - (*) - export BUCKET=builds-parity; - ;; - esac + (beta|stable|nightly) + export BUCKET=releases.parity.io/ethereum; + ;; + (*) + export BUCKET=builds-parity; + ;; + esac - aws s3 sync ./artifacts s3://${BUCKET}/${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}/ - after_script: - - aws s3 ls s3://${BUCKET}/${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}/ - --recursive --human-readable --summarize + - echo "__________Read from S3____________" + - aws s3 ls s3://${BUCKET}/${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}} --recursive --human-readable --summarize tags: - linux-docker +publish-release-awss3-manually: + <<: *publish-release-awss3 + only: *releaseable_branches + when: manual + publish-docs: - stage: publish + stage: publish + image: parity/parity-ci-docs:latest only: - tags except: - nightly - cache: {} + when: manual + cache: {} + dependencies: [] script: - scripts/gitlab/publish-docs.sh tags: - linux-docker + allow_failure: true -build-android: - stage: optional - image: parity/rust-android:gitlab-ci +publish-av-whitelist: + stage: publish variables: - CARGO_TARGET: armv7-linux-androideabi + GIT_STRATEGY: none + only: *releaseable_branches + except: + - nightly + when: manual + cache: {} + dependencies: + - build-windows script: - - scripts/gitlab/build-unix.sh + - scripts/gitlab/publish-av-whitelists.sh tags: - linux-docker - allow_failure: true - <<: *collect_artifacts diff --git a/CHANGELOG.md b/CHANGELOG.md index 71591c5fff..8ba5eb20b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,287 +1,139 @@ -## Parity-Ethereum [v2.2.5](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.5) (2018-12-14) -Parity-Ethereum 2.2.5-beta is an important release that introduces Constantinople fork at block 7080000 on Mainnet. -This release also contains a fix for chains using AuRa + EmptySteps. Read carefully if this applies to you. -If you have a chain with`empty_steps` already running, some blocks most likely contain non-strict entries (unordered or duplicated empty steps). In this release`strict_empty_steps_transition` **is enabled by default at block 0** for any chain with `empty_steps`. -If your network uses `empty_steps` you **must**: -- plan a hard fork and change `strict_empty_steps_transition` to the desire fork block -- update the clients of the whole network to 2.2.5-beta / 2.1.10-stable. -If for some reason you don't want to do this please set`strict_empty_steps_transition` to `0xfffffffff` to disable it. - -The full list of included changes: -- Backports for beta 2.2.5 ([#10047](https://github.com/paritytech/parity-ethereum/pull/10047)) - - Bump beta to 2.2.5 ([#10047](https://github.com/paritytech/parity-ethereum/pull/10047)) - - Fix empty steps ([#9939](https://github.com/paritytech/parity-ethereum/pull/9939)) - - Prevent sending empty step message twice - - Prevent sending empty step and then block in the same step - - Don't accept double empty steps - - Do basic validation of self-sealed blocks - - Strict empty steps validation ([#10041](https://github.com/paritytech/parity-ethereum/pull/10041)) - - Enables strict verification of empty steps - there can be no duplicates and empty steps should be ordered inside the seal. - - Note that authorities won't produce invalid seals after [#9939](https://github.com/paritytech/parity-ethereum/pull/9939), this PR just adds verification to the seal to prevent forging incorrect blocks and potentially causing consensus issues. - - This features is enabled by default so any AuRa + EmptySteps chain should set strict_empty_steps_transition fork block number in their spec and upgrade to v2.2.5-beta or v2.1.10-stable. - - ethcore: enable constantinople on ethereum ([#10031](https://github.com/paritytech/parity-ethereum/pull/10031)) - - ethcore: change blockreward to 2e18 for foundation after constantinople - - ethcore: delay diff bomb by 2e6 blocks for foundation after constantinople - - ethcore: enable eip-{145,1014,1052,1283} for foundation after constantinople - - Change test miner max memory to malloc reports. ([#10024](https://github.com/paritytech/parity-ethereum/pull/10024)) - - Fix: test corpus_inaccessible panic ([#10019](https://github.com/paritytech/parity-ethereum/pull/10019)) - -## Parity-Ethereum [v2.2.2](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.2) (2018-11-29) - -Parity-Ethereum 2.2.2-beta is an exciting release. Among others, it improves sync performance, peering stability, block propagation, and transaction propagation times. Also, a warp-sync no longer removes existing blocks from the database, but rather reuses locally available information to decrease sync times and reduces required bandwidth. - -Before upgrading to 2.2.2, please also verify the validity of your chain specs. Parity Ethereum now denies unknown fields in the specification. To do this, use the chainspec tool: - -``` -cargo build --release -p chainspec -./target/release/chainspec /path/to/spec.json -``` - -Last but not least, JSONRPC APIs which are not yet accepted as an EIP in the `eth`, `personal`, or `web3` namespace, are now considere experimental as their final specification might change in future. These APIs have to be manually enabled by explicitly running `--jsonrpc-experimental`. +## Parity-Ethereum [v2.5.9](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.8) + +Parity Ethereum v2.5.9-stable is a patch release that adds the block numbers for activating the Istanbul hardfork on test networks: Ropsten, Görli, Rinkeby and Kovan. + +The full list of included changes: + +* ethcore/res: activate Istanbul on Ropsten, Görli, Rinkeby, Kovan (#11068) +* [json-spec] make blake2 pricing spec more readable (#11034) + +## Parity-Ethereum [v2.5.8](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.8) + +Parity Ethereum v2.5.8-stable is a patch release that improves security, stability and performance. + +* The most noteworthy improvement in this release is incorporating all the EIPs required for the Istanbul hard fork. +* This release also fixes certain security and performance issues, one of which was suspected to be consensus-threatening but turned out to be benign. Thanks to Martin Holst Swende and Felix Lange from the Ethereum Foundation for bringing the suspicious issue to our attention. + +The full list of included changes: + +* add more tx tests (#11038) +* Fix parallel transactions race-condition (#10995) +* Add blake2_f precompile (#11017) +* [trace] introduce trace failed to Ext (#11019) +* Edit publish-onchain.sh to use https (#11016) +* Fix deadlock in network-devp2p (#11013) +* EIP 1108: Reduce alt_bn128 precompile gas costs (#11008) +* xDai chain support and nodes list update (#10989) +* EIP 2028: transaction gas lowered from 68 to 16 (#10987) +* EIP-1344 Add CHAINID op-code (#10983) +* manual publish jobs for releases, no changes for nightlies (#10977) +* [blooms-db] Fix benchmarks (#10974) +* Verify transaction against its block during import (#10954) +* Better error message for rpc gas price errors (#10931) +* tx-pool: accept local tx with higher gas price when pool full (#10901) +* Fix fork choice (#10837) +* Cleanup unused vm dependencies (#10787) +* Fix compilation on recent nightlies (#10991) +* Don't build rpc with ethcore test-helpers (#11048) +* EIP 1884 Re-pricing of trie-size dependent operations (#10992) +* Implement EIP-1283 reenable transition, EIP-1706 and EIP-2200 (#10191) + +## Parity-Ethereum [v2.5.7](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.7) + +Parity Ethereum v2.5.7-stable is a bugfix release that fixes a potential DoS attack in the trace_call RPC method. This is a critical upgrade for anyone running Parity nodes with RPC exposed to the public internet (and highly recommended for anyone else). For details see this blog post. + +## Parity-Ethereum [v2.5.6](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.6) + +Parity-Ethereum v2.5.6-stable is a bugfix release that improves stability. + +* Allow specifying hostnames for node URLs +* Fix a bug where archive nodes were losing peers + +The full list of included changes: + +* Kaspersky AV whitelisting (#10919) +* Avast whitelist script (#10900) +* Docker images renaming (#10863) +* Remove excessive warning (#10831) +* Allow --nat extip:your.host.here.org (#10830) +* When updating the client or when called from RPC, sleep should mean sleep (#10814) +* added new ropsten-bootnode and removed old one (#10794) +* ethkey no longer uses byteorder (#10786) +* Do not drop the peer with None difficulty (#10772) +* docs: Update Readme with TOC, Contributor Guideline. Update Cargo package descriptions (#10652) + +## Parity-Ethereum [v2.5.5](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.5) + +Parity-Ethereum v2.5.5-stable is a minor release that improves performance and stability. +This release stabilises the 2.5 branch. + +As of today, Parity-Ethereum 2.4 reaches end of life and everyone is +encouraged to upgrade. + +## Parity-Ethereum [v2.5.4](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.4) + +Parity Ethereum v2.5.4-beta is a security update that addresses servo/rust-smallvec#148 The full list of included changes: -- Backports For beta 2.2.2 ([#9976](https://github.com/paritytech/parity-ethereum/pull/9976)) - - Version: bump beta to 2.2.2 - - Add experimental RPCs flag ([#9928](https://github.com/paritytech/parity-ethereum/pull/9928)) - - Keep existing blocks when restoring a Snapshot ([#8643](https://github.com/paritytech/parity-ethereum/pull/8643)) - - Rename db_restore => client - - First step: make it compile! - - Second step: working implementation! - - Refactoring - - Fix tests - - Migrate ancient blocks interacting backward - - Early return in block migration if snapshot is aborted - - Remove RwLock getter (PR Grumble I) - - Remove dependency on `Client`: only used Traits - - Add test for recovering aborted snapshot recovery - - Add test for migrating old blocks - - Release RwLock earlier - - Revert Cargo.lock - - Update _update ancient block_ logic: set local in `commit` - - Update typo in ethcore/src/snapshot/service.rs - - Adjust requests costs for light client ([#9925](https://github.com/paritytech/parity-ethereum/pull/9925)) - - Pip Table Cost relative to average peers instead of max peers - - Add tracing in PIP new_cost_table - - Update stat peer_count - - Use number of leeching peers for Light serve costs - - Fix test::light_params_load_share_depends_on_max_peers (wrong type) - - Remove (now) useless test - - Remove `load_share` from LightParams.Config - - Add LEECHER_COUNT_FACTOR - - Pr Grumble: u64 to u32 for f64 casting - - Prevent u32 overflow for avg_peer_count - - Add tests for LightSync::Statistics - - Fix empty steps ([#9939](https://github.com/paritytech/parity-ethereum/pull/9939)) - - Don't send empty step twice or empty step then block. - - Perform basic validation of locally sealed blocks. - - Don't include empty step twice. - - Prevent silent errors in daemon mode, closes [#9367](https://github.com/paritytech/parity-ethereum/issues/9367) ([#9946](https://github.com/paritytech/parity-ethereum/pull/9946)) - - Fix a deadlock ([#9952](https://github.com/paritytech/parity-ethereum/pull/9952)) - - Update informant: - - Decimal in Mgas/s - - Print every 5s (not randomly between 5s and 10s) - - Fix dead-lock in `blockchain.rs` - - Update locks ordering - - Fix light client informant while syncing ([#9932](https://github.com/paritytech/parity-ethereum/pull/9932)) - - Add `is_idle` to LightSync to check importing status - - Use SyncStateWrapper to make sure is_idle gets updates - - Update is_major_import to use verified queue size as well - - Add comment for `is_idle` - - Add Debug to `SyncStateWrapper` - - `fn get` -> `fn into_inner` - - Ci: rearrange pipeline by logic ([#9970](https://github.com/paritytech/parity-ethereum/pull/9970)) - - Ci: rearrange pipeline by logic - - Ci: rename docs script - - Fix docker build ([#9971](https://github.com/paritytech/parity-ethereum/pull/9971)) - - Deny unknown fields for chainspec ([#9972](https://github.com/paritytech/parity-ethereum/pull/9972)) - - Add deny_unknown_fields to chainspec - - Add tests and fix existing one - - Remove serde_ignored dependency for chainspec - - Fix rpc test eth chain spec - - Fix starting_nonce_test spec - - Improve block and transaction propagation ([#9954](https://github.com/paritytech/parity-ethereum/pull/9954)) - - Refactor sync to add priority tasks. - - Send priority tasks notifications. - - Propagate blocks, optimize transactions. - - Implement transaction propagation. Use sync_channel. - - Tone down info. - - Prevent deadlock by not waiting forever for sync lock. - - Fix lock order. - - Don't use sync_channel to prevent deadlocks. - - Fix tests. - - Fix unstable peers and slowness in sync ([#9967](https://github.com/paritytech/parity-ethereum/pull/9967)) - - Don't sync all peers after each response - - Update formating - - Fix tests: add `continue_sync` to `Sync_step` - - Update ethcore/sync/src/chain/mod.rs - - Fix rpc middlewares - - Fix Cargo.lock - - Json: resolve merge in spec - - Rpc: fix starting_nonce_test - - Ci: allow nightl job to fail - -## Parity-Ethereum [v2.2.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.1) (2018-11-15) - -Parity-Ethereum 2.2.1-beta is the first v2.2 release, and might introduce features that break previous work flows, among others: - -- Prevent zero network ID ([#9763](https://github.com/paritytech/parity-ethereum/pull/9763)) and drop support for Olympic testnet ([#9801](https://github.com/paritytech/parity-ethereum/pull/9801)): The Olympic test net is dead for years and never used a chain ID but network ID zero. Parity Ethereum is now preventing the network ID to be zero, thus Olympic support is dropped. Make sure to chose positive non-zero network IDs in future. -- Multithreaded snapshot creation ([#9239](https://github.com/paritytech/parity-ethereum/pull/9239)): adds a CLI argument `--snapshot-threads` which specifies the number of threads. This helps improving the performance of full nodes that wish to provide warp-snapshots for the network. The gain in performance comes with a slight drawback in increased snapshot size. -- Expose config max-round-blocks-to-import ([#9439](https://github.com/paritytech/parity-ethereum/pull/9439)): Parity Ethereum imports blocks in rounds. If at the end of any round, the queue is not empty, we consider it to be _importing_ and won't notify pubsub. On large re-orgs (10+ blocks), this is possible. The default `max_round_blocks_to_import` is increased to 12 and configurable via the `--max-round-blocks-to-import` CLI flag. With unstable network conditions, it is advised to increase the number. This shouldn't have any noticeable performance impact unless the number is set to really large. -- Increase Gas-floor-target and Gas Cap ([#9564](https://github.com/paritytech/parity-ethereum/pull/9564)): the default values for gas floor target are `8_000_000` and gas cap `10_000_000`, similar to Geth 1.8.15+. -- Produce portable binaries ([#9725](https://github.com/paritytech/parity-ethereum/pull/9725)): we now produce portable binaries, but it may incur some performance degradation. For ultimate performance it's now better to compile Parity Ethereum from source with `PORTABLE=OFF` environment variable. -- RPC: `parity_allTransactionHashes` ([#9745](https://github.com/paritytech/parity-ethereum/pull/9745)): Get all pending transactions from the queue with the high performant `parity_allTransactionHashes` RPC method. -- Support `eth_chainId` RPC method ([#9783](https://github.com/paritytech/parity-ethereum/pull/9783)): implements EIP-695 to get the chainID via RPC. -- AuRa: finalize blocks ([#9692](https://github.com/paritytech/parity-ethereum/pull/9692)): The AuRa engine was updated to emit ancestry actions to finalize blocks. The full client stores block finality in the database, the engine builds finality from an ancestry of `ExtendedHeader`; `is_epoch_end` was updated to take a vec of recently finalized headers; `is_epoch_end_light` was added which maintains the previous interface and is used by the light client since the client itself doesn't track finality. +* cargo update -p smallvec ([#10822](https://github.com/paritytech/parity-ethereum/pull/10822)) + +## Parity-Ethereum [v2.5.3](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.3) + +Parity-Ethereum 2.5.3-beta is a bugfix release that improves performance and stability. + +* EthereumClassic: activate the Atlantis Hardfork +* Clique: fix time overflow +* State tests: treat empty accounts the same as non-existant accounts (EIP 1052) +* Networking: support discovery-only peers (geth bootnodes) +* Snapshotting: fix unclean shutdown while snappshotting is under way + +The full list of included changes: + +* ethcore/res: activate atlantis classic hf on block 8772000 ([#10766](https://github.com/paritytech/parity-ethereum/pull/10766)) +* fix docker tags for publishing ([#10741](https://github.com/paritytech/parity-ethereum/pull/10741)) +* fix: aura don't add `SystemTime::now()` ([#10720](https://github.com/paritytech/parity-ethereum/pull/10720)) +* Treat empty account the same as non-exist accounts in EIP-1052 ([#10775](https://github.com/paritytech/parity-ethereum/pull/10775)) +* DevP2p: Get node IP address and udp port from Socket, if not included in PING packet ([#10705](https://github.com/paritytech/parity-ethereum/pull/10705)) +* Add a way to signal shutdown to snapshotting threads ([#10744](https://github.com/paritytech/parity-ethereum/pull/10744)) + +## Parity-Ethereum [v2.5.2](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.2) + +Parity-Ethereum 2.5.2-beta is a bugfix release that improves performance and stability. + +Among others, it enables the _Atlantis_ hardfork on **Morden** and **Kotti** Classic networks. The full list of included changes: -- Backport to parity 2.2.1 beta ([#9905](https://github.com/paritytech/parity-ethereum/pull/9905)) - - Bump version to 2.2.1 - - Fix: Intermittent failing CI due to addr in use ([#9885](https://github.com/paritytech/parity-ethereum/pull/9885)) - - Fix Parity not closing on Ctrl-C ([#9886](https://github.com/paritytech/parity-ethereum/pull/9886)) - - Fix json tracer overflow ([#9873](https://github.com/paritytech/parity-ethereum/pull/9873)) - - Fix docker script ([#9854](https://github.com/paritytech/parity-ethereum/pull/9854)) - - Add hardcoded headers for light client ([#9907](https://github.com/paritytech/parity-ethereum/pull/9907)) - - Gitlab-ci: make android release build succeed ([#9743](https://github.com/paritytech/parity-ethereum/pull/9743)) - - Allow to seal work on latest block ([#9876](https://github.com/paritytech/parity-ethereum/pull/9876)) - - Remove rust-toolchain file ([#9906](https://github.com/paritytech/parity-ethereum/pull/9906)) - - Light-fetch: Differentiate between out-of-gas/manual throw and use required gas from response on failure ([#9824](https://github.com/paritytech/parity-ethereum/pull/9824)) - - Eip-712 implementation ([#9631](https://github.com/paritytech/parity-ethereum/pull/9631)) - - Eip-191 implementation ([#9701](https://github.com/paritytech/parity-ethereum/pull/9701)) - - Simplify cargo audit ([#9918](https://github.com/paritytech/parity-ethereum/pull/9918)) - - Fix performance issue importing Kovan blocks ([#9914](https://github.com/paritytech/parity-ethereum/pull/9914)) - - Ci: nuke the gitlab caches ([#9855](https://github.com/paritytech/parity-ethereum/pull/9855)) -- Backports to parity beta 2.2.0 ([#9820](https://github.com/paritytech/parity-ethereum/pull/9820)) - - Ci: remove failing tests for android, windows, and macos ([#9788](https://github.com/paritytech/parity-ethereum/pull/9788)) - - Implement NoProof for json tests and update tests reference ([#9814](https://github.com/paritytech/parity-ethereum/pull/9814)) - - Move state root verification before gas used ([#9841](https://github.com/paritytech/parity-ethereum/pull/9841)) - - Classic.json Bootnode Update ([#9828](https://github.com/paritytech/parity-ethereum/pull/9828)) -- Rpc: parity_allTransactionHashes ([#9745](https://github.com/paritytech/parity-ethereum/pull/9745)) -- Revert "prevent zero networkID ([#9763](https://github.com/paritytech/parity-ethereum/pull/9763))" ([#9815](https://github.com/paritytech/parity-ethereum/pull/9815)) -- Allow zero chain id in EIP155 signing process ([#9792](https://github.com/paritytech/parity-ethereum/pull/9792)) -- Add readiness check for docker container ([#9804](https://github.com/paritytech/parity-ethereum/pull/9804)) -- Insert dev account before unlocking ([#9813](https://github.com/paritytech/parity-ethereum/pull/9813)) -- Removed "rustup" & added new runner tag ([#9731](https://github.com/paritytech/parity-ethereum/pull/9731)) -- Expose config max-round-blocks-to-import ([#9439](https://github.com/paritytech/parity-ethereum/pull/9439)) -- Aura: finalize blocks ([#9692](https://github.com/paritytech/parity-ethereum/pull/9692)) -- Sync: retry different peer after empty subchain heads response ([#9753](https://github.com/paritytech/parity-ethereum/pull/9753)) -- Fix(light-rpc/parity) : Remove unused client ([#9802](https://github.com/paritytech/parity-ethereum/pull/9802)) -- Drops support for olympic testnet, closes [#9800](https://github.com/paritytech/parity-ethereum/issues/9800) ([#9801](https://github.com/paritytech/parity-ethereum/pull/9801)) -- Replace `tokio_core` with `tokio` (`ring` -> 0.13) ([#9657](https://github.com/paritytech/parity-ethereum/pull/9657)) -- Support eth_chainId RPC method ([#9783](https://github.com/paritytech/parity-ethereum/pull/9783)) -- Ethcore: bump ropsten forkblock checkpoint ([#9775](https://github.com/paritytech/parity-ethereum/pull/9775)) -- Docs: changelogs for 2.0.8 and 2.1.3 ([#9758](https://github.com/paritytech/parity-ethereum/pull/9758)) -- Prevent zero networkID ([#9763](https://github.com/paritytech/parity-ethereum/pull/9763)) -- Skip seal fields count check when --no-seal-check is used ([#9757](https://github.com/paritytech/parity-ethereum/pull/9757)) -- Aura: fix panic on extra_info with unsealed block ([#9755](https://github.com/paritytech/parity-ethereum/pull/9755)) -- Docs: update changelogs ([#9742](https://github.com/paritytech/parity-ethereum/pull/9742)) -- Removed extra assert in generation_session_is_removed_when_succeeded ([#9738](https://github.com/paritytech/parity-ethereum/pull/9738)) -- Make checkpoint_storage_at use plain loop instead of recursion ([#9734](https://github.com/paritytech/parity-ethereum/pull/9734)) -- Use signed 256-bit integer for sstore gas refund substate ([#9746](https://github.com/paritytech/parity-ethereum/pull/9746)) -- Heads ref not present for branches beta and stable ([#9741](https://github.com/paritytech/parity-ethereum/pull/9741)) -- Add Callisto support ([#9534](https://github.com/paritytech/parity-ethereum/pull/9534)) -- Add --force to cargo audit install script ([#9735](https://github.com/paritytech/parity-ethereum/pull/9735)) -- Remove unused expired value from Handshake ([#9732](https://github.com/paritytech/parity-ethereum/pull/9732)) -- Add hardcoded headers ([#9730](https://github.com/paritytech/parity-ethereum/pull/9730)) -- Produce portable binaries ([#9725](https://github.com/paritytech/parity-ethereum/pull/9725)) -- Gitlab ci: releasable_branches: change variables condition to schedule ([#9729](https://github.com/paritytech/parity-ethereum/pull/9729)) -- Update a few parity-common dependencies ([#9663](https://github.com/paritytech/parity-ethereum/pull/9663)) -- Hf in POA Core (2018-10-22) ([#9724](https://github.com/paritytech/parity-ethereum/pull/9724)) -- Schedule nightly builds ([#9717](https://github.com/paritytech/parity-ethereum/pull/9717)) -- Fix ancient blocks sync ([#9531](https://github.com/paritytech/parity-ethereum/pull/9531)) -- Ci: Skip docs job for nightly ([#9693](https://github.com/paritytech/parity-ethereum/pull/9693)) -- Fix (light/provider) : Make `read_only executions` read-only ([#9591](https://github.com/paritytech/parity-ethereum/pull/9591)) -- Ethcore: fix detection of major import ([#9552](https://github.com/paritytech/parity-ethereum/pull/9552)) -- Return 0 on error ([#9705](https://github.com/paritytech/parity-ethereum/pull/9705)) -- Ethcore: delay ropsten hardfork ([#9704](https://github.com/paritytech/parity-ethereum/pull/9704)) -- Make instantSeal engine backwards compatible, closes [#9696](https://github.com/paritytech/parity-ethereum/issues/9696) ([#9700](https://github.com/paritytech/parity-ethereum/pull/9700)) -- Implement CREATE2 gas changes and fix some potential overflowing ([#9694](https://github.com/paritytech/parity-ethereum/pull/9694)) -- Don't hash the init_code of CREATE. ([#9688](https://github.com/paritytech/parity-ethereum/pull/9688)) -- Ethcore: minor optimization of modexp by using LR exponentiation ([#9697](https://github.com/paritytech/parity-ethereum/pull/9697)) -- Removed redundant clone before each block import ([#9683](https://github.com/paritytech/parity-ethereum/pull/9683)) -- Add Foundation Bootnodes ([#9666](https://github.com/paritytech/parity-ethereum/pull/9666)) -- Docker: run as parity user ([#9689](https://github.com/paritytech/parity-ethereum/pull/9689)) -- Ethcore: mcip3 block reward contract ([#9605](https://github.com/paritytech/parity-ethereum/pull/9605)) -- Verify block syncing responses against requests ([#9670](https://github.com/paritytech/parity-ethereum/pull/9670)) -- Add a new RPC `parity_submitWorkDetail` similar `eth_submitWork` but return block hash ([#9404](https://github.com/paritytech/parity-ethereum/pull/9404)) -- Resumable EVM and heap-allocated callstack ([#9360](https://github.com/paritytech/parity-ethereum/pull/9360)) -- Update parity-wordlist library ([#9682](https://github.com/paritytech/parity-ethereum/pull/9682)) -- Ci: Remove unnecessary pipes ([#9681](https://github.com/paritytech/parity-ethereum/pull/9681)) -- Test.sh: use cargo --target for platforms other than linux, win or mac ([#9650](https://github.com/paritytech/parity-ethereum/pull/9650)) -- Ci: fix push script ([#9679](https://github.com/paritytech/parity-ethereum/pull/9679)) -- Hardfork the testnets ([#9562](https://github.com/paritytech/parity-ethereum/pull/9562)) -- Calculate sha3 instead of sha256 for push-release. ([#9673](https://github.com/paritytech/parity-ethereum/pull/9673)) -- Ethcore-io retries failed work steal ([#9651](https://github.com/paritytech/parity-ethereum/pull/9651)) -- Fix(light_fetch): avoid race with BlockNumber::Latest ([#9665](https://github.com/paritytech/parity-ethereum/pull/9665)) -- Test fix for windows cache name... ([#9658](https://github.com/paritytech/parity-ethereum/pull/9658)) -- Refactor(fetch) : light use only one `DNS` thread ([#9647](https://github.com/paritytech/parity-ethereum/pull/9647)) -- Ethereum libfuzzer integration small change ([#9547](https://github.com/paritytech/parity-ethereum/pull/9547)) -- Cli: remove reference to --no-ui in --unlock flag help ([#9616](https://github.com/paritytech/parity-ethereum/pull/9616)) -- Remove master from releasable branches ([#9655](https://github.com/paritytech/parity-ethereum/pull/9655)) -- Ethcore/VerificationQueue don't spawn up extra `worker-threads` when explictly specified not to ([#9620](https://github.com/paritytech/parity-ethereum/pull/9620)) -- Rpc: parity_getBlockReceipts ([#9527](https://github.com/paritytech/parity-ethereum/pull/9527)) -- Remove unused dependencies ([#9589](https://github.com/paritytech/parity-ethereum/pull/9589)) -- Ignore key_server_cluster randomly failing tests ([#9639](https://github.com/paritytech/parity-ethereum/pull/9639)) -- Ethcore: handle vm exception when estimating gas ([#9615](https://github.com/paritytech/parity-ethereum/pull/9615)) -- Fix bad-block reporting no reason ([#9638](https://github.com/paritytech/parity-ethereum/pull/9638)) -- Use static call and apparent value transfer for block reward contract code ([#9603](https://github.com/paritytech/parity-ethereum/pull/9603)) -- Hf in POA Sokol (2018-09-19) ([#9607](https://github.com/paritytech/parity-ethereum/pull/9607)) -- Bump smallvec to 0.6 in ethcore-light, ethstore and whisper ([#9588](https://github.com/paritytech/parity-ethereum/pull/9588)) -- Add constantinople conf to EvmTestClient. ([#9570](https://github.com/paritytech/parity-ethereum/pull/9570)) -- Fix(network): don't disconnect reserved peers ([#9608](https://github.com/paritytech/parity-ethereum/pull/9608)) -- Fix failing node-table tests on mac os, closes [#9632](https://github.com/paritytech/parity-ethereum/issues/9632) ([#9633](https://github.com/paritytech/parity-ethereum/pull/9633)) -- Update ropsten.json ([#9602](https://github.com/paritytech/parity-ethereum/pull/9602)) -- Simplify ethcore errors by removing BlockImportError ([#9593](https://github.com/paritytech/parity-ethereum/pull/9593)) -- Fix windows compilation, replaces [#9561](https://github.com/paritytech/parity-ethereum/issues/9561) ([#9621](https://github.com/paritytech/parity-ethereum/pull/9621)) -- Master: rpc-docs set github token ([#9610](https://github.com/paritytech/parity-ethereum/pull/9610)) -- Docs: add changelogs for 1.11.10, 1.11.11, 2.0.3, 2.0.4, 2.0.5, 2.0.6, 2.1.0, and 2.1.1 ([#9554](https://github.com/paritytech/parity-ethereum/pull/9554)) -- Docs(rpc): annotate tag with the provided message ([#9601](https://github.com/paritytech/parity-ethereum/pull/9601)) -- Ci: fix regex roll_eyes ([#9597](https://github.com/paritytech/parity-ethereum/pull/9597)) -- Remove snapcraft clean ([#9585](https://github.com/paritytech/parity-ethereum/pull/9585)) -- Add snapcraft package image (master) ([#9584](https://github.com/paritytech/parity-ethereum/pull/9584)) -- Docs(rpc): push the branch along with tags ([#9578](https://github.com/paritytech/parity-ethereum/pull/9578)) -- Fix typo for jsonrpc-threads flag ([#9574](https://github.com/paritytech/parity-ethereum/pull/9574)) -- Fix informant compile ([#9571](https://github.com/paritytech/parity-ethereum/pull/9571)) -- Added ropsten bootnodes ([#9569](https://github.com/paritytech/parity-ethereum/pull/9569)) -- Increase Gas-floor-target and Gas Cap ([#9564](https://github.com/paritytech/parity-ethereum/pull/9564)) -- While working on the platform tests make them non-breaking ([#9563](https://github.com/paritytech/parity-ethereum/pull/9563)) -- Improve P2P discovery ([#9526](https://github.com/paritytech/parity-ethereum/pull/9526)) -- Move dockerfile for android build container to scripts repo ([#9560](https://github.com/paritytech/parity-ethereum/pull/9560)) -- Simultaneous platform tests WIP ([#9557](https://github.com/paritytech/parity-ethereum/pull/9557)) -- Update ethabi-derive, serde, serde_json, serde_derive, syn && quote ([#9553](https://github.com/paritytech/parity-ethereum/pull/9553)) -- Ci: fix rpc docs generation 2 ([#9550](https://github.com/paritytech/parity-ethereum/pull/9550)) -- Ci: always run build pipelines for win, mac, linux, and android ([#9537](https://github.com/paritytech/parity-ethereum/pull/9537)) -- Multithreaded snapshot creation ([#9239](https://github.com/paritytech/parity-ethereum/pull/9239)) -- New ethabi ([#9511](https://github.com/paritytech/parity-ethereum/pull/9511)) -- Remove initial token for WS. ([#9545](https://github.com/paritytech/parity-ethereum/pull/9545)) -- Net_version caches network_id to avoid redundant aquire of sync readlock ([#9544](https://github.com/paritytech/parity-ethereum/pull/9544)) -- Correct before_script for nightly build versions ([#9543](https://github.com/paritytech/parity-ethereum/pull/9543)) -- Deps: bump kvdb-rocksdb to 0.1.4 ([#9539](https://github.com/paritytech/parity-ethereum/pull/9539)) -- State: test when contract creation fails, old storage values should re-appear ([#9532](https://github.com/paritytech/parity-ethereum/pull/9532)) -- Allow dropping light client RPC query with no results ([#9318](https://github.com/paritytech/parity-ethereum/pull/9318)) -- Bump master to 2.2.0 ([#9517](https://github.com/paritytech/parity-ethereum/pull/9517)) -- Enable all Constantinople hard fork changes in constantinople_test.json ([#9505](https://github.com/paritytech/parity-ethereum/pull/9505)) -- [Light] Validate `account balance` before importing transactions ([#9417](https://github.com/paritytech/parity-ethereum/pull/9417)) -- In create memory calculation is the same for create2 because the additional parameter was popped before. ([#9522](https://github.com/paritytech/parity-ethereum/pull/9522)) -- Update patricia trie to 0.2.2 ([#9525](https://github.com/paritytech/parity-ethereum/pull/9525)) -- Replace hardcoded JSON with serde json! macro ([#9489](https://github.com/paritytech/parity-ethereum/pull/9489)) -- Fix typo in version string ([#9516](https://github.com/paritytech/parity-ethereum/pull/9516)) - -## Previous releases - -- [CHANGELOG-2.1](docs/CHANGELOG-2.1.md) (_stable_) -- [CHANGELOG-2.0](docs/CHANGELOG-2.0.md) (EOL: 2018-11-15) -- [CHANGELOG-1.11](docs/CHANGELOG-1.11.md) (EOL: 2018-09-19) -- [CHANGELOG-1.10](docs/CHANGELOG-1.10.md) (EOL: 2018-07-18) -- [CHANGELOG-1.9](docs/CHANGELOG-1.9.md) (EOL: 2018-05-09) -- [CHANGELOG-1.8](docs/CHANGELOG-1.8.md) (EOL: 2018-03-22) -- [CHANGELOG-1.7](docs/CHANGELOG-1.7.md) (EOL: 2018-01-25) -- [CHANGELOG-1.6](docs/CHANGELOG-1.6.md) (EOL: 2017-10-15) -- [CHANGELOG-1.5](docs/CHANGELOG-1.5.md) (EOL: 2017-07-28) -- [CHANGELOG-1.4](docs/CHANGELOG-1.4.md) (EOL: 2017-03-13) -- [CHANGELOG-1.3](docs/CHANGELOG-1.3.md) (EOL: 2017-01-19) -- [CHANGELOG-1.2](docs/CHANGELOG-1.2.md) (EOL: 2016-11-07) -- [CHANGELOG-1.1](docs/CHANGELOG-1.1.md) (EOL: 2016-08-12) -- [CHANGELOG-1.0](docs/CHANGELOG-1.0.md) (EOL: 2016-06-24) -- [CHANGELOG-0.9](docs/CHANGELOG-0.9.md) (EOL: 2016-05-02) +* [CI] allow cargo audit to fail ([#10676](https://github.com/paritytech/parity-ethereum/pull/10676)) +* Reset blockchain properly ([#10669](https://github.com/paritytech/parity-ethereum/pull/10669)) +* new image ([#10673](https://github.com/paritytech/parity-ethereum/pull/10673)) +* Update publishing ([#10644](https://github.com/paritytech/parity-ethereum/pull/10644)) +* enable lto for release builds ([#10717](https://github.com/paritytech/parity-ethereum/pull/10717)) +* Use RUSTFLAGS to set the optimization level ([#10719](https://github.com/paritytech/parity-ethereum/pull/10719)) +* ethcore: enable ECIP-1054 for classic ([#10731](https://github.com/paritytech/parity-ethereum/pull/10731)) + +## Parity-Ethereum [v2.5.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.1) + +Parity-Ethereum 2.5.1-beta is a bugfix release that improves performance and stability. + +Among others, it enables the Petersburg hardfork on **Rinkeby** and **POA-Core** Network, as well as the **Kovan** Network community hardfork. + +The full list of included changes: + +* ci: publish docs debug ([#10638](https://github.com/paritytech/parity-ethereum/pull/10638)) + +## Parity-Ethereum [v2.5.0](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.0) + +Parity-Ethereum 2.5.0-beta is a minor release that improves performance and stabilizes the 2.5 branch by marking it as beta release. + +- This release adds support for the Clique consensus engine ([#9981](https://github.com/paritytech/parity-ethereum/pull/9981)) + - This enables Parity-Ethereum users to use the Görli, the Kotti Classic, and the legacy Rinkeby testnet. To get started try `parity --chain goerli`; note that light client support is currently not yet fully functional. +- This release removes the dead chain configs for Easthub and Ethereum Social ([#10531](https://github.com/paritytech/parity-ethereum/pull/10531)) + +As of today, Parity-Ethereum 2.3 reaches end of life and everyone is encouraged to upgrade. + +The full list of included changes: + +* fix(light cull): poll light cull instead of timer ([#10559](https://github.com/paritytech/parity-ethereum/pull/10559)) + diff --git a/Cargo.lock b/Cargo.lock index a57f60d763..c95da51e9e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,19 +1,60 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aes" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aes-ctr" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aes-soft" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aesni" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "aho-corasick" version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aho-corasick" -version = "0.7.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -60,7 +101,7 @@ name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -81,7 +122,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "arrayvec" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -89,7 +130,7 @@ dependencies = [ [[package]] name = "ascii" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -99,44 +140,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "atty" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.2" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.15" +version = "0.3.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.28" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "base-x" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -144,8 +182,8 @@ name = "base64" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -153,7 +191,7 @@ name = "base64" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -161,7 +199,7 @@ name = "bincode" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -191,7 +229,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "1.0.4" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -210,8 +248,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-cipher-trait" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-modes" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -226,31 +281,34 @@ dependencies = [ name = "blooms-db" version = "0.1.0" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethbloom 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bn" version = "0.4.4" -source = "git+https://github.com/paritytech/bn#67df95d06683b99d4308af20f9adc31497afcece" +source = "git+https://github.com/paritytech/bn#6079255e65793038b9a6e5292203eab482737cc2" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bstr" -version = "0.1.2" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -265,7 +323,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -273,7 +331,8 @@ name = "bytes" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -284,7 +343,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.36" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -294,7 +353,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.7" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -307,20 +366,21 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.6" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cid" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "integer-encoding 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "integer-encoding 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "multihash 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -331,11 +391,11 @@ version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -343,7 +403,8 @@ dependencies = [ name = "cli-signer" version = "1.4.0" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "parity-rpc 1.12.0", "parity-rpc-client 1.4.0", "rpassword 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -354,15 +415,15 @@ name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cmake" -version = "0.1.39" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -370,10 +431,10 @@ name = "combine" version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ascii 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ascii 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -387,7 +448,6 @@ dependencies = [ "heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-machine 0.1.0", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp_derive 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -399,7 +459,7 @@ name = "config" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rust-ini 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", @@ -409,6 +469,11 @@ dependencies = [ "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "constant_time_eq" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cookie-factory" version = "0.2.4" @@ -419,25 +484,25 @@ name = "criterion" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "criterion-plot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -445,59 +510,18 @@ name = "criterion-plot" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-channel" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-deque" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-deque" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-deque" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -505,61 +529,21 @@ name = "crossbeam-deque" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -567,29 +551,16 @@ name = "crossbeam-queue" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-utils" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-utils" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "crossbeam-utils" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -602,40 +573,59 @@ name = "crunchy" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crypto-mac" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crypto-mac" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "csv" -version = "1.0.7" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "csv-core" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ct-logs" -version = "0.4.0" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ctr" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "sct 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -644,16 +634,19 @@ version = "1.1.1" source = "git+https://github.com/paritytech/rust-ctrlc.git#b523017108bb2d571a7a69bd97bc406e63bc7a9d" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "daemonize" -version = "0.3.0" +name = "derive_more" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -671,10 +664,10 @@ dependencies = [ [[package]] name = "digest" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -692,8 +685,8 @@ name = "docopt" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -703,6 +696,13 @@ name = "edit-distance" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "eip-152" +version = "0.1.0" +dependencies = [ + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "eip-712" version = "0.1.0" @@ -710,15 +710,15 @@ dependencies = [ "ethabi 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lunarity-lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "toolshed 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "validator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -727,7 +727,7 @@ dependencies = [ [[package]] name = "either" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -745,39 +745,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "enclose" -version = "1.1.6" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "enum_primitive" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "env_logger" version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "env_logger" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "error-chain" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -785,9 +794,9 @@ name = "eth-secp256k1" version = "0.5.7" source = "git+https://github.com/paritytech/rust-secp256k1#ccc06e7480148b723eb44ac56cf4d20eec380b6f" dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -796,13 +805,13 @@ name = "ethabi" version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -818,8 +827,8 @@ dependencies = [ "ethabi 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -828,13 +837,15 @@ version = "1.12.0" dependencies = [ "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -847,7 +858,7 @@ dependencies = [ "ethereum-types-serialize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "fixed-hash 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -857,16 +868,18 @@ dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "blooms-db 0.1.0", "bn 0.4.4 (git+https://github.com/paritytech/bn)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "common-types 0.1.0", "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "eip-152 0.1.0", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 6.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethash 1.12.0", + "ethcore-accounts 0.1.0", "ethcore-blockchain 0.1.0", "ethcore-bloom-journal 0.1.0", "ethcore-call-contract 0.1.0", @@ -877,46 +890,46 @@ dependencies = [ "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", "ethkey 0.3.0", - "ethstore 0.2.1", "evm 0.1.0", - "fake-hardware-wallet 0.0.1", - "hardware-wallet 1.12.0", - "hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fetch 0.1.0", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "journaldb 0.2.0", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hasher 0.1.1", "kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb-memorydb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb-rocksdb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-memorydb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-rocksdb 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "len-caching-lock 0.1.1", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "macros 0.1.0", "memory-cache 0.1.0", - "memorydb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-machine 0.1.0", + "parity-crypto 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-runtime 0.1.0", "parity-snappy 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "patricia-trie 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "patricia-trie-ethereum 0.1.0", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp_compress 0.1.0", "rlp_derive 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "stats 0.1.0", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "time-utils 0.1.0", "trace-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "trie-standardmap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "triehash-ethereum 0.2.0", "unexpected 0.1.0", @@ -925,11 +938,29 @@ dependencies = [ "wasm 0.1.0", ] +[[package]] +name = "ethcore-accounts" +version = "0.1.0" +dependencies = [ + "common-types 0.1.0", + "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", + "ethstore 0.2.1", + "fake-hardware-wallet 0.0.1", + "hardware-wallet 1.12.0", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ethcore-blockchain" version = "0.1.0" dependencies = [ - "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "blooms-db 0.1.0", "common-types 0.1.0", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -940,16 +971,18 @@ dependencies = [ "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb-memorydb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-memorydb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp_compress 0.1.0", "rlp_derive 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "triehash-ethereum 0.2.0", ] [[package]] @@ -987,15 +1020,15 @@ version = "1.12.0" dependencies = [ "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "timer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1004,38 +1037,39 @@ version = "1.12.0" dependencies = [ "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "common-types 0.1.0", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethcore-blockchain 0.1.0", "ethcore-db 0.1.0", "ethcore-io 1.12.0", "ethcore-network 1.12.0", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "failsafe 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failsafe 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "fastmap 0.1.0", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "journaldb 0.2.0", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hasher 0.1.1", "kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb-memorydb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-memorydb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "memory-cache 0.1.0", - "memorydb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "patricia-trie 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "patricia-trie-ethereum 0.1.0", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp_derive 0.1.0", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "stats 0.1.0", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "triehash-ethereum 0.2.0", "vm 0.1.0", ] @@ -1045,13 +1079,13 @@ name = "ethcore-logger" version = "1.12.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1062,7 +1096,7 @@ dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "common-types 0.1.0", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 6.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1071,19 +1105,19 @@ dependencies = [ "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "fetch 0.1.0", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)", - "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-runtime 0.1.0", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "price-info 1.12.0", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "trace-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "transaction-pool 1.13.3 (registry+https://github.com/rust-lang/crates.io-index)", + "transaction-pool 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1092,15 +1126,19 @@ name = "ethcore-network" version = "1.12.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-io 1.12.0", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "ipnetwork 0.12.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-crypto 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-snappy 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1111,7 +1149,7 @@ dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-io 1.12.0", "ethcore-network 1.12.0", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1119,13 +1157,13 @@ dependencies = [ "igd 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.12.8 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-path 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-crypto 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-path 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "parity-snappy 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1133,11 +1171,11 @@ dependencies = [ "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1145,8 +1183,8 @@ name = "ethcore-private-tx" version = "1.0.0" dependencies = [ "common-types 0.1.0", + "derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 6.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1158,24 +1196,24 @@ dependencies = [ "ethjson 0.1.0", "ethkey 0.3.0", "fetch 0.1.0", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-crypto 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "patricia-trie 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "patricia-trie-ethereum 0.1.0", "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp_derive 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "transaction-pool 1.13.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "transaction-pool 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1183,35 +1221,36 @@ dependencies = [ name = "ethcore-secretstore" version = "1.0.0" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "common-types 0.1.0", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 6.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", + "ethcore-accounts 0.1.0", "ethcore-call-contract 0.1.0", "ethcore-sync 1.12.0", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb-rocksdb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-rocksdb 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-crypto 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-runtime 0.1.0", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1222,7 +1261,7 @@ name = "ethcore-service" version = "0.1.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethcore-blockchain 0.1.0", "ethcore-db 0.1.0", @@ -1231,8 +1270,8 @@ dependencies = [ "ethcore-sync 1.12.0", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb-rocksdb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-rocksdb 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "trace-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1243,13 +1282,12 @@ version = "1.12.0" dependencies = [ "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-macros 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-tcp-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", + "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-tcp-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1258,6 +1296,7 @@ name = "ethcore-sync" version = "1.12.0" dependencies = [ "common-types 0.1.0", + "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethcore-io 1.12.0", @@ -1269,13 +1308,13 @@ dependencies = [ "ethkey 0.3.0", "ethstore 0.2.1", "fastmap 0.1.0", - "hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hasher 0.1.1", "kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb-memorydb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-memorydb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "macros 0.1.0", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1314,7 +1353,7 @@ dependencies = [ "ethereum-types 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)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1322,21 +1361,20 @@ dependencies = [ name = "ethkey" version = "0.3.0" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "edit-distance 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "memzero 0.1.0", - "parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wordlist 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-crypto 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wordlist 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1347,10 +1385,10 @@ dependencies = [ "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "panic_hook 0.1.0", - "parity-wordlist 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wordlist 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1362,21 +1400,22 @@ dependencies = [ "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wordlist 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-crypto 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wordlist 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1387,12 +1426,12 @@ dependencies = [ "docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "ethstore 0.2.1", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "panic_hook 0.1.0", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1404,10 +1443,12 @@ dependencies = [ "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "memory-cache 0.1.0", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1430,7 +1471,7 @@ dependencies = [ "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "vm 0.1.0", @@ -1438,10 +1479,10 @@ dependencies = [ [[package]] name = "failsafe" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1451,7 +1492,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1461,9 +1502,9 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1471,8 +1512,8 @@ name = "fake-fetch" version = "0.0.1" dependencies = [ "fetch 0.1.0", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1501,7 +1542,7 @@ name = "fdlimit" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1509,12 +1550,12 @@ name = "fetch" version = "0.1.0" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1524,7 +1565,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1544,10 +1585,10 @@ name = "fs-swap" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1565,7 +1606,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1576,7 +1617,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures" -version = "0.1.26" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1592,7 +1633,7 @@ name = "futures-core" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1600,8 +1641,8 @@ name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1612,8 +1653,8 @@ dependencies = [ "futures-channel 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures-util 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1630,8 +1671,8 @@ name = "futures-retry" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1639,7 +1680,7 @@ name = "futures-sink" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures-channel 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1649,7 +1690,7 @@ name = "futures-util" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures-channel 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures-io 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1661,7 +1702,7 @@ name = "fxhash" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1674,51 +1715,51 @@ name = "generic-array" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "generic-array" -version = "0.12.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "getopts" -version = "0.2.19" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "globset" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "h2" -version = "0.1.18" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1732,15 +1773,15 @@ name = "handlebars" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1751,17 +1792,17 @@ dependencies = [ "ethkey 0.3.0", "hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)", "libusb 0.3.0 (git+https://github.com/paritytech/libusb-rs)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 1.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 1.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "trezor-sys 1.0.0 (git+https://github.com/paritytech/trezor-sys)", ] [[package]] -name = "hashdb" -version = "0.3.0" +name = "hash-db" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1770,7 +1811,7 @@ version = "0.4.2" source = "git+https://github.com/cheme/heapsize.git?branch=ec-macfix#c07ffe843acb9da570682e290a48540741afdce1" dependencies = [ "jemallocator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1778,7 +1819,7 @@ name = "heck" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1791,22 +1832,48 @@ name = "hex" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "hex-literal" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hex-literal-impl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hex-literal-impl" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hidapi" version = "0.3.1" source = "git+https://github.com/paritytech/hidapi-rs#d4d323767d6f27cf5a3d73fbae0b0f2134d579bf" dependencies = [ - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hmac" -version = "0.7.0" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1815,12 +1882,21 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "home" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "http" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1828,14 +1904,25 @@ dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "http-body" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "httparse" -version = "1.3.3" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "humantime" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1848,13 +1935,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1862,53 +1949,53 @@ dependencies = [ "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hyper" -version = "0.12.28" +version = "0.12.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hyper-rustls" -version = "0.14.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ct-logs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "ct-logs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1931,7 +2018,7 @@ name = "igd" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1944,12 +2031,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.0.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "integer-encoding" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1962,7 +2049,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1976,7 +2063,7 @@ name = "itertools" version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1984,7 +2071,7 @@ name = "itertools" version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1992,7 +2079,7 @@ name = "itertools" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2005,9 +2092,9 @@ name = "jemalloc-sys" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2016,20 +2103,20 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jni" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2044,14 +2131,14 @@ dependencies = [ "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "fastmap 0.1.0", - "hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hasher 0.1.1", "kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb-memorydb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memorydb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-memorydb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2059,102 +2146,103 @@ dependencies = [ [[package]] name = "jsonrpc-core" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2#84360bf1d03821b8fd669a6a95fcdf847aaf6cca" +version = "10.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "jsonrpc-derive" +version = "10.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "jsonrpc-http-server" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2#84360bf1d03821b8fd669a6a95fcdf847aaf6cca" +version = "10.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-server-utils 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-server-utils 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-ipc-server" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2#84360bf1d03821b8fd669a6a95fcdf847aaf6cca" +version = "10.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-server-utils 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-server-utils 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-tokio-ipc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "jsonrpc-macros" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2#84360bf1d03821b8fd669a6a95fcdf847aaf6cca" -dependencies = [ - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "jsonrpc-pubsub" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2#84360bf1d03821b8fd669a6a95fcdf847aaf6cca" +version = "10.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-server-utils" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2#84360bf1d03821b8fd669a6a95fcdf847aaf6cca" +version = "10.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-tcp-server" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2#84360bf1d03821b8fd669a6a95fcdf847aaf6cca" +version = "10.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-server-utils 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-server-utils 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-ws-server" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2#84360bf1d03821b8fd669a6a95fcdf847aaf6cca" +version = "10.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-server-utils 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-server-utils 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-ws 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ws 0.7.9 (git+https://github.com/tomusdrw/ws-rs)", ] [[package]] @@ -2163,7 +2251,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2171,9 +2259,9 @@ name = "keccak-hasher" version = "0.1.1" dependencies = [ "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "plain_hasher 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2196,27 +2284,27 @@ dependencies = [ [[package]] name = "kvdb-memorydb" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "kvdb-rocksdb" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "fs-swap 0.2.4 (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 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-rocksdb 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2232,7 +2320,7 @@ dependencies = [ "amq-protocol 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "cookie-factory 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sasl 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2245,7 +2333,7 @@ dependencies = [ "amq-protocol 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "cookie-factory 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2259,13 +2347,13 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "cookie-factory 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lapin-async 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2277,15 +2365,15 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "cookie-factory 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lapin-async 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2295,7 +2383,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2312,16 +2400,16 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.54" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libloading" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2330,7 +2418,7 @@ version = "0.3.0" source = "git+https://github.com/paritytech/libusb-rs#442708954a720bc89a9cf41e7be021a778bdbc27" dependencies = [ "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "libusb-sys 0.2.5 (git+https://github.com/paritytech/libusb-sys)", ] @@ -2339,8 +2427,8 @@ name = "libusb-sys" version = "0.2.5" source = "git+https://github.com/paritytech/libusb-sys#79e570b00379e1550fb728f2fbd2a083dc99bda6" dependencies = [ - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2377,19 +2465,19 @@ dependencies = [ ] [[package]] -name = "log" -version = "0.3.9" +name = "lock_api" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "log" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2414,7 +2502,7 @@ version = "0.1.0" [[package]] name = "maplit" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2424,10 +2512,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2435,14 +2523,17 @@ name = "memmap" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memoffset" -version = "0.2.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "memory-cache" @@ -2453,20 +2544,18 @@ dependencies = [ ] [[package]] -name = "memory_units" -version = "0.3.0" +name = "memory-db" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)", +] [[package]] -name = "memorydb" +name = "memory_units" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)", - "plain_hasher 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "memzero" @@ -2477,43 +2566,37 @@ name = "migration-rocksdb" version = "0.1.0" dependencies = [ "kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb-rocksdb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-rocksdb 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "macros 0.1.0", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mime" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "mime_guess" -version = "2.0.0-alpha.6" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mio" -version = "0.6.16" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2526,8 +2609,8 @@ version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2536,10 +2619,10 @@ name = "mio-named-pipes" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2548,8 +2631,8 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2568,8 +2651,8 @@ name = "miow" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2577,7 +2660,7 @@ name = "multibase" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base-x 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "base-x 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2587,7 +2670,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "sha1 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2600,9 +2683,9 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2617,8 +2700,8 @@ dependencies = [ "ethcore-network 1.12.0", "ethcore-network-devp2p 1.12.0", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb-memorydb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-memorydb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2634,7 +2717,7 @@ name = "nom" version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2644,9 +2727,9 @@ version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2654,27 +2737,39 @@ name = "num-bigint" version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-bigint" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-integer" -version = "0.1.39" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-iter" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2682,20 +2777,23 @@ name = "num-traits" version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "num_cpus" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2703,14 +2801,9 @@ name = "number_prefix" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "numtoa" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "ole32-sys" version = "0.2.0" @@ -2722,7 +2815,7 @@ dependencies = [ [[package]] name = "opaque-debug" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2756,7 +2849,7 @@ dependencies = [ name = "panic_hook" version = "0.1.0" dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2768,40 +2861,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "parity-clib" version = "1.12.0" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "jni 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "jni 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "panic_hook 0.1.0", - "parity-ethereum 2.3.5", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-ethereum 2.5.9", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-crypto" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-modes 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scrypt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-daemonize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-ethereum" -version = "2.3.5" +version = "2.5.9" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "blooms-db 0.1.0", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "cli-signer 1.4.0", "common-types 0.1.0", "ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)", - "daemonize 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "dir 0.1.2", "docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", + "ethcore-accounts 0.1.0", "ethcore-blockchain 0.1.0", "ethcore-call-contract 0.1.0", "ethcore-db 0.1.0", @@ -2819,33 +2930,35 @@ dependencies = [ "ethstore 0.2.1", "fake-fetch 0.0.1", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.12.8 (registry+https://github.com/rust-lang/crates.io-index)", "journaldb 0.2.0", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", + "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb-rocksdb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-rocksdb 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "migration-rocksdb 0.1.0", "node-filter 1.12.0", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "panic_hook 0.1.0", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-daemonize 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-hash-fetch 1.12.0", "parity-ipfs-api 1.12.0", "parity-local-store 0.1.0", - "parity-path 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-path 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "parity-rabbitmq 0.1.0", "parity-rpc 1.12.0", "parity-runtime 0.1.0", "parity-updater 1.12.0", - "parity-version 2.3.5", + "parity-version 2.5.9", "parity-whisper 0.1.0", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "registrar 0.0.1", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rpassword 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2853,13 +2966,13 @@ dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2872,11 +2985,11 @@ dependencies = [ "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "fake-fetch 0.0.1", "fetch 0.1.0", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-runtime 0.1.0", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2889,15 +3002,15 @@ dependencies = [ name = "parity-ipfs-api" version = "1.12.0" dependencies = [ - "cid 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-http-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", + "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-http-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "multihash 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2908,25 +3021,21 @@ dependencies = [ "ethcore-io 1.12.0", "ethkey 0.3.0", "kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb-memorydb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-memorydb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parity-machine" -version = "0.1.0" -dependencies = [ - "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parity-path" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "home 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "parity-rabbitmq" @@ -2938,20 +3047,20 @@ dependencies = [ "ethcore-miner 1.12.0", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "futures-executor 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lapin-futures 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "macros 0.1.0", "parity-runtime 0.1.0", "rabbitmq_adaptor 0.3.3 (registry+https://dl.cloudsmith.io/ItqwH3F8rYFNB5vv/chronicled/platform-v2/cargo/index.git)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2959,7 +3068,7 @@ name = "parity-rocksdb" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "local-encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-rocksdb-sys 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2969,8 +3078,8 @@ name = "parity-rocksdb-sys" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cmake 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "local-encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-snappy-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2980,11 +3089,12 @@ name = "parity-rpc" version = "1.12.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cid 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "common-types 0.1.0", "eip-712 0.1.0", "ethash 1.12.0", "ethcore 1.12.0", + "ethcore-accounts 0.1.0", "ethcore-io 1.12.0", "ethcore-light 1.12.0", "ethcore-logger 1.12.0", @@ -2997,44 +3107,40 @@ dependencies = [ "ethkey 0.3.0", "ethstore 0.2.1", "fake-fetch 0.0.1", - "fake-hardware-wallet 0.0.1", "fastmap 0.1.0", "fetch 0.1.0", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "hardware-wallet 1.12.0", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-http-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-ipc-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-macros 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-ws-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", + "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-derive 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-http-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-ipc-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-ws-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb-memorydb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "macros 0.1.0", "multihash 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-crypto 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-runtime 0.1.0", "parity-updater 1.12.0", - "parity-version 2.3.5", + "parity-version 2.5.9", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "patricia-trie 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "stats 0.1.0", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "transaction-pool 1.13.3 (registry+https://github.com/rust-lang/crates.io-index)", + "transaction-pool 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "transient-hashmap 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "vm 0.1.0", ] @@ -3043,11 +3149,12 @@ dependencies = [ name = "parity-rpc-client" version = "1.4.0" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-ws-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", + "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-ws-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-rpc 1.12.0", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3060,8 +3167,8 @@ dependencies = [ name = "parity-runtime" version = "0.1.0" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3069,7 +3176,7 @@ name = "parity-snappy" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "parity-snappy-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3078,8 +3185,8 @@ name = "parity-snappy-sys" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cmake 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3088,15 +3195,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-named-pipes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3111,13 +3218,13 @@ dependencies = [ "ethcore-sync 1.12.0", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-hash-fetch 1.12.0", - "parity-path 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-version 2.3.5", + "parity-path 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-version 2.5.9", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3127,7 +3234,7 @@ dependencies = [ [[package]] name = "parity-version" -version = "2.3.5" +version = "2.5.9" dependencies = [ "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3142,7 +3249,7 @@ name = "parity-wasm" version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3150,37 +3257,54 @@ name = "parity-whisper" version = "0.1.0" dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-network 1.12.0", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-macros 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-derive 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "memzero 0.1.0", "ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-crypto 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "time-utils 0.1.0", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-wordlist" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-ws" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3201,16 +3325,26 @@ dependencies = [ "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3218,26 +3352,28 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "patricia-trie" -version = "0.3.0" +name = "parking_lot_core" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3246,13 +3382,24 @@ version = "0.1.0" dependencies = [ "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "journaldb 0.2.0", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hasher 0.1.1", - "memorydb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "patricia-trie 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pbkdf2" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3260,7 +3407,7 @@ name = "pbkdf2" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3271,10 +3418,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pest" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3282,29 +3429,29 @@ name = "pest_derive" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "pest_generator" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_meta 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "pest_meta" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3317,41 +3464,6 @@ dependencies = [ "ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "phf" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "phf_codegen" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "phf_generator" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "phf_shared" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "plain_hasher" version = "0.2.0" @@ -3374,8 +3486,8 @@ version = "1.12.0" dependencies = [ "fake-fetch 0.0.1", "fetch 0.1.0", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-runtime 0.1.0", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3404,7 +3516,7 @@ name = "primal-check" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3420,7 +3532,17 @@ dependencies = [ "hamming 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "primal-bit 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "primal-estimate 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3431,9 +3553,17 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "protobuf" -version = "1.7.4" +version = "1.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3441,7 +3571,7 @@ name = "pulldown-cmark" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3454,7 +3584,7 @@ dependencies = [ "ethjson 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "vm 0.1.0", "wasm 0.1.0", @@ -3465,8 +3595,8 @@ name = "pwasm-utils" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3477,12 +3607,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.6.12" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rabbitmq_adaptor" version = "0.3.3" @@ -3490,17 +3628,17 @@ source = "registry+https://dl.cloudsmith.io/ItqwH3F8rYFNB5vv/chronicled/platform dependencies = [ "amq-protocol 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "config 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "enclose 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "enclose 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "futures-retry 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures-util 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lapin-futures 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3509,7 +3647,7 @@ name = "rand" version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3519,10 +3657,10 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3532,9 +3670,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3542,17 +3680,17 @@ name = "rand" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3560,7 +3698,7 @@ name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3569,12 +3707,12 @@ name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3598,9 +3736,9 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3610,10 +3748,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3621,8 +3759,8 @@ name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3638,29 +3776,30 @@ name = "rand_xoshiro" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon" -version = "1.0.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon-core" -version = "1.4.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3673,16 +3812,8 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "redox_termios" -version = "0.1.1" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "regex" @@ -3690,40 +3821,44 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.1.6" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "regex-syntax" -version = "0.5.6" +name = "regex-automata" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.6" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "regex-syntax" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "registrar" version = "0.0.1" @@ -3731,7 +3866,7 @@ dependencies = [ "ethabi 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 6.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3740,26 +3875,38 @@ name = "relay" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "remove_dir_all" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ring" -version = "0.13.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ripemd160" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3767,7 +3914,7 @@ name = "rlp" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3778,7 +3925,7 @@ name = "rlp" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3788,7 +3935,7 @@ name = "rlp_compress" version = "0.1.0" dependencies = [ "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3797,9 +3944,9 @@ name = "rlp_derive" version = "0.1.0" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3808,7 +3955,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rprompt 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3824,7 +3971,7 @@ version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3837,7 +3984,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-demangle" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3865,22 +4012,17 @@ dependencies = [ [[package]] name = "rustls" -version = "0.13.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sct 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ryu" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "ryu" version = "1.0.0" @@ -3888,12 +4030,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "safemem" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "same-file" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3905,7 +4047,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3922,12 +4064,29 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scopeguard" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "scrypt" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sct" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3937,6 +4096,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3954,7 +4114,7 @@ name = "serde" version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3965,18 +4125,18 @@ dependencies = [ "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.91" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4003,9 +4163,9 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4035,9 +4195,9 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4054,11 +4214,6 @@ name = "siphasher" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "siphasher" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "skeptic" version = "0.4.0" @@ -4085,20 +4240,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "socket2" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "stable_deref_trait" version = "1.1.1" @@ -4108,13 +4268,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "stats" version = "0.1.0" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stream-cipher" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "string" -version = "0.1.3" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "strsim" @@ -4133,22 +4304,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.34" +version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "synstructure" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4163,7 +4344,7 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4172,27 +4353,16 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "termcolor" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "termion" -version = "1.5.2" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4200,7 +4370,7 @@ name = "textwrap" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4208,7 +4378,7 @@ name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4216,9 +4386,9 @@ name = "thread-id" version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4226,7 +4396,7 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4234,7 +4404,7 @@ name = "threadpool" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4242,30 +4412,34 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "time-utils" +version = "0.1.0" + [[package]] name = "timer" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tiny-keccak" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tinytemplate" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4274,35 +4448,44 @@ dependencies = [ [[package]] name = "tokio" -version = "0.1.19" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-buf" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-codec" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4312,16 +4495,16 @@ version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4329,17 +4512,17 @@ name = "tokio-current-thread" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4347,9 +4530,9 @@ name = "tokio-fs" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4358,8 +4541,8 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4368,28 +4551,28 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-reactor" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4397,7 +4580,7 @@ name = "tokio-retry" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4405,12 +4588,13 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.7.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4418,16 +4602,16 @@ name = "tokio-service" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-sync" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4436,27 +4620,27 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4464,41 +4648,33 @@ name = "tokio-timer" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-trace-core" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-udp" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4507,15 +4683,15 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4539,17 +4715,16 @@ name = "trace-time" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "transaction-pool" -version = "1.13.3" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "trace-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4563,7 +4738,18 @@ name = "trezor-sys" version = "1.0.0" source = "git+https://github.com/paritytech/trezor-sys#8a401705e58c83db6c29c199d9577b78fde40709" dependencies = [ - "protobuf 1.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 1.7.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "trie-db" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4579,10 +4765,10 @@ dependencies = [ [[package]] name = "triehash" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4592,7 +4778,7 @@ version = "0.2.0" dependencies = [ "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hasher 0.1.1", - "triehash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "triehash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4607,17 +4793,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "typenum" -version = "1.10.0" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ucd-trie" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ucd-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -4625,7 +4811,7 @@ name = "uint" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4637,15 +4823,7 @@ version = "0.1.0" [[package]] name = "unicase" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicase" -version = "2.4.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4664,17 +4842,17 @@ name = "unicode-normalization" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-segmentation" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-width" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -4682,6 +4860,11 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unreachable" version = "1.0.0" @@ -4711,7 +4894,7 @@ version = "0.1.0" [[package]] name = "utf8-ranges" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -4728,10 +4911,10 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4742,11 +4925,11 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", "validator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4773,13 +4956,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "vm" version = "0.1.0" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "patricia-trie 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "patricia-trie-ethereum 0.1.0", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4791,11 +4971,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "walkdir" -version = "2.2.7" +version = "2.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4804,18 +4984,18 @@ name = "want" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "try-lock 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "want" -version = "0.0.6" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4823,11 +5003,11 @@ dependencies = [ name = "wasm" version = "0.1.0" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", "pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "vm 0.1.0", @@ -4839,7 +5019,7 @@ name = "wasmi" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "nan-preserving-float 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4847,20 +5027,20 @@ dependencies = [ [[package]] name = "webpki" -version = "0.18.1" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "webpki-roots" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4871,14 +5051,16 @@ dependencies = [ "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-network 1.12.0", "ethcore-network-devp2p 1.12.0", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-http-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", + "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-http-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "panic_hook 0.1.0", "parity-whisper 0.1.0", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4888,7 +5070,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4910,7 +5092,7 @@ name = "winapi-util" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4920,30 +5102,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wincolor" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ws" -version = "0.7.9" -source = "git+https://github.com/tomusdrw/ws-rs#4baef2dc1abc8e216559af51cfc120bbcc777e21" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -4963,7 +5128,7 @@ name = "xml-rs" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4983,8 +5148,12 @@ dependencies = [ ] [metadata] +"checksum aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "54eb1d8fe354e5fc611daf4f2ea97dd45a765f4f1e4512306ec183ae2e8f20c9" +"checksum aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2e5b0458ea3beae0d1d8c0f3946564f8e10f90646cf78c06b4351052058d1ee" +"checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" +"checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" "checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" -"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" +"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum amq-protocol 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d687fc53c2d85f31d22d91d8b62a7a6f8fc2b0e8dfd2c23d52a0433db4d01f2b" "checksum amq-protocol-codegen 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b367f31f4feba2ca7959f476f81076db213734a053d2b0ab78bcffab0acbfae6" "checksum amq-protocol-types 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6857d51c6c9e9b45eacd355917c0e792cd3ceeaeab76a75d6475ea8980009fea" @@ -4992,14 +5161,14 @@ dependencies = [ "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum app_dirs 1.2.1 (git+https://github.com/paritytech/app-dirs-rs)" = "" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" -"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" -"checksum ascii 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5fc969a8ce2c9c0c4b0429bb8431544f6658283c8326ba5ff8c762b75369335" +"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" +"checksum ascii 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" "checksum assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5" -"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637" -"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" -"checksum base-x 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d55aa264e822dbafa12db4d54767aff17c6ba55ea2d8559b3e17392c7d000e5d" +"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" +"checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5" +"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" +"checksum base-x 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "76f4eae81729e69bb1819a26c6caac956cc429238388091f98cb6cd858f16443" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e103c8b299b28a9c6990458b7013dc4a8356a9b854c51b9883241f5866fac36e" @@ -5007,64 +5176,61 @@ dependencies = [ "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" "checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" +"checksum block-modes 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "31aa8410095e39fdb732909fb5730a48d5bd7c2e3cd76bd1b07b3dbea130c529" "checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" "checksum bn 0.4.4 (git+https://github.com/paritytech/bn)" = "" -"checksum bstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c8203ca06c502958719dae5f653a79e0cc6ba808ed02beffbf27d09610f2143" +"checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c56216487bb80eec9c4516337b2588a4f2a2290d72a1416d930e4dcdb0c90d" +"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" "checksum cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" -"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" -"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" -"checksum cid 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0e37fba0087d9f3f4e269827a55dc511abf3e440cc097a0c154ff4e6584f988" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" +"checksum cid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6908948032561f2550467a477f659cdc358320a805237b9b5035c0350c441def" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum cmake 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "d9fc5523427cb1451da064f7db483d18bf8957e471baabf140ff683c37a86536" +"checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" "checksum combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" "checksum config 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9107d78ed62b3fa5a86e7d18e647abed48cfd8f8fab6c72f4cdb982d196f7e6" +"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" "checksum cookie-factory 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98a479f8099cc5ac64915a3dd76c87be27f929ba406ad705aacb13f19b791207" "checksum criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0363053954f3e679645fc443321ca128b7b950a6fe288cf5f9335cc22ee58394" "checksum criterion-plot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76f9212ddf2f4a9eb2d401635190600656a1f88a932ef53d06e7fa4c7e02fb8e" -"checksum crossbeam 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7408247b1b87f480890f28b670c5f8d9a8a4274833433fe74dc0dfd46d33650" -"checksum crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b85741761b7f160bc5e7e0c14986ef685b7f8bf9b7ad081c60c604bb4649827" -"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" -"checksum crossbeam-deque 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7792c4a9b5a4222f654e3728a3dd945aacc24d2c3a1a096ed265d80e4929cb9a" "checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" -"checksum crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30fecfcac6abfef8771151f8be4abc9e4edc112c2bcb233314cafde2680536e9" -"checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8" -"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" +"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" -"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" +"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +"checksum crypto-mac 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7afa06d05a046c7a47c3a849907ec303504608c927f4e85f7bfff22b7180d971" "checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" -"checksum csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9044e25afb0924b5a5fc5511689b0918629e85d68ea591e5e87fbf1e85ea1b3b" -"checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" -"checksum ct-logs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "95a4bf5107667e12bf6ce31a3a5066d67acc88942b6742117a41198734aaccaa" +"checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" +"checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" +"checksum ct-logs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b4660f8b07a560a88c02d76286edb9f0d5d64e495d2b0f233186155aa51be1f" +"checksum ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "022cd691704491df67d25d006fe8eca083098253c4d43516c2206479c58c6736" "checksum ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)" = "" -"checksum daemonize 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4093d27eb267d617f03c2ee25d4c3ca525b89a76154001954a11984508ffbde5" +"checksum derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6d944ac6003ed268757ef1ee686753b57efc5fcf0ebe7b64c9fc81e7e32ff839" "checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" -"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969" "checksum edit-distance 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bbbaaaf38131deb9ca518a274a45bfdb8771f139517b073b16c2d3d32ae5037b" -"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" +"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "073be79b6538296faf81c631872676600616073817dd9a440c477ad09b408983" "checksum enclose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5e432442c28955a3bc9d0ad23ffe730f29274edf1d1db1b3eb9c461eb01d38fd" -"checksum enclose 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3b762b80547dcf67e427c99ab25dd421fe7d95938c1b10763824555b73b09c7c" +"checksum enclose 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1056f553da426e9c025a662efa48b52e62e0a3a7648aa2d15aeaaf7f0d329357" +"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" -"checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" -"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" +"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" +"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)" = "" "checksum ethabi 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8eb362fde43ed0b50b258bb0c72b72b3dccfd29f8de9506295eaf9251c49ca31" "checksum ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "795e25fd868e12a59ca235dbe1f6cc8f1eba8f67d6a39438b29535e0126e0c27" @@ -5072,7 +5238,7 @@ dependencies = [ "checksum ethbloom 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6294da962646baa738414e8e718d1a1f0360a51d92de89ccbf91870418f5360" "checksum ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e742184dc63a01c8ea0637369f8faa27c40f537949908a237f95c05e68d2c96" "checksum ethereum-types-serialize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1873d77b32bc1891a79dad925f2acbc318ee942b38b9110f9dbc5fbeffcea350" -"checksum failsafe 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad3bf1642583ea2f1fa38a1e8546613a7488816941b33e5f0fccceac61879118" +"checksum failsafe 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf04c6ffd217a68c73fdf40eb3331c484fd7a9fa4fd1028fcf74456ef889ca12" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" @@ -5085,7 +5251,7 @@ dependencies = [ "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "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.26 (registry+https://github.com/rust-lang/crates.io-index)" = "62941eff9507c8177d448bd83a44d9b9760856e184081d8cd79ba9f03dd24981" +"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" "checksum futures-channel 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bbb37ec6418c577b25f5b129c0f4456ad7ce8714ec43c59712aa7e4cd2cb6b85" "checksum futures-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7455c91eb2eae38f33b013f77ebe766c75761af333efd9d550e154045c63e225" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" @@ -5096,32 +5262,37 @@ dependencies = [ "checksum futures-util 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cf12a3fc1ccaf1bc2901ec6e0ed6ed407a4f16eaa20dd838f40cabf5f7b31f1" "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" -"checksum getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "72327b15c228bfe31f1390f93dd5e9279587f0463836393c9df719ce62a3e450" -"checksum globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4feaabe24a0a658fd9cf4a9acf6ed284f045c77df0f49020ba3245cfb7b454" -"checksum h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "85ab6286db06040ddefb71641b50017c06874614001a134b423783e2db2920bd" +"checksum getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +"checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" +"checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" "checksum hamming 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1" "checksum handlebars 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d82e5750d8027a97b9640e3fefa66bbaf852a35228e1c90790efd13c4b09c166" -"checksum hashdb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d91261ee336dd046ac7df28306cb297b7a7228bd1ae25e9a57f4ed5e0ab628c7" +"checksum hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b03501f6e1a2a97f1618879aba3156f14ca2847faa530c4e28859638bd11483" "checksum heapsize 0.4.2 (git+https://github.com/cheme/heapsize.git?branch=ec-macfix)" = "" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +"checksum hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "961de220ec9a91af2e1e5bd80d02109155695e516771762381ef8581317066e0" +"checksum hex-literal-impl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d4c5c844e2fee0bf673d54c2c177f1713b3d2af2ff6e666b49cb7572e6cf42d" "checksum hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)" = "" -"checksum hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f127a908633569f208325f86f71255d3363c79721d7f9fe31cd5569908819771" +"checksum hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "733e1b3ac906631ca01ebb577e9bb0f5e37a454032b9036b5eaea4013ed6f99a" +"checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" "checksum home 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "29302b90cfa76231a757a887d1e3153331a63c7f80b6c75f86366334cbe70708" -"checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" -"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" -"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" +"checksum home 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c315e106bd6f83f026a20ddaeef2706782e490db1dcdd37caad38a0e895b3" +"checksum http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "372bcb56f939e449117fb0869c2e8fd8753a8223d92a172c6e808cf123a5b6e4" +"checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" +"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" +"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" "checksum hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)" = "34a590ca09d341e94cddf8e5af0bbccde205d5fbc2fa3c09dd67c7f85cea59d7" -"checksum hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)" = "e8e4606fed1c162e3a63d408c07584429f49a4f34c7176cb6cbee60e78f2372c" -"checksum hyper-rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68f2aa6b1681795bf4da8063f718cd23145aa0c9a5143d9787b345aa60d38ee4" +"checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" +"checksum hyper-rustls 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "15b66d1bd4864ef036adf2363409caa3acd63ebb4725957b66e621c8a36631a3" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4bac95d9aa0624e7b78187d6fb8ab012b41d9f6f54b1bcb61e61c4845f8357ec" "checksum igd 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c8aef7814a769f156ef3a86169a8b04c066e3aebc324f522c159978466e32a1c" -"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" -"checksum integer-encoding 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "26746cbc2e680af687e88d717f20ff90079bd10fc984ad57d277cd0e37309fa5" +"checksum indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a61202fbe46c4a951e9404a720a0180bcf3212c750d735cb5c4ba4dc551299f3" +"checksum integer-encoding 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1aec89c15e2cfa0f0eae8ca60e03cb10b30d25ea2c0ad7d6be60a95e32729994" "checksum interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "141340095b15ed7491bd3d4ced9d20cebfb826174b6bb03386381f62b01e3d77" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum ipnetwork 0.12.8 (registry+https://github.com/rust-lang/crates.io-index)" = "70783119ac90828aaba91eae39db32c6c1b8838deea3637e5238efa0130801ab" @@ -5131,51 +5302,51 @@ dependencies = [ "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc62c8e50e381768ce8ee0428ee53741929f7ebd73e4d83f669bcf7693e00ae" "checksum jemallocator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9f0cd42ac65f758063fea55126b0148b1ce0a6354ff78e07a4d6806bc65c4ab3" -"checksum jni 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1ecfa3b81afc64d9a6539c4eece96ac9a93c551c713a313800dade8e33d7b5c1" +"checksum jni 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "294eca097d1dc0bf59de5ab9f7eafa5f77129e9f6464c957ed3ddeb705fb4292" "checksum jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" -"checksum jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)" = "" -"checksum jsonrpc-http-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)" = "" -"checksum jsonrpc-ipc-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)" = "" -"checksum jsonrpc-macros 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)" = "" -"checksum jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)" = "" -"checksum jsonrpc-server-utils 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)" = "" -"checksum jsonrpc-tcp-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)" = "" -"checksum jsonrpc-ws-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-2.2)" = "" +"checksum jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc15eef5f8b6bef5ac5f7440a957ff95d036e2f98706947741bfc93d1976db4c" +"checksum jsonrpc-derive 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dae61ca8a3b047fb11309b00661bc56837085bd07e46f907b9c562c0b03e68" +"checksum jsonrpc-http-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11d2a00824306155b8ef57fe957f31b8cd8ad24262f15cf911d84dcf9a3f206d" +"checksum jsonrpc-ipc-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3da135d38d35137f9af49fde7bac99e3fe028352bfb96fe0140ae23a189ea027" +"checksum jsonrpc-pubsub 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37fce55133ee264d0ab42bd862efcd45ae1d062cda599f4cc12ccc4be3195f2a" +"checksum jsonrpc-server-utils 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c9527f01ef25f251d64082cbefc0c6d6f367349afe6848ef908a674e06b2bdd3" +"checksum jsonrpc-tcp-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7a04458f5fcba7bb0f109a4d42f47fab4c068cdeb40bdf9b984327e9aaea24" +"checksum jsonrpc-ws-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3889012aa638a2f18eb1a879f46fc8b34e7e1423cbff3247cd1531de0d51084b" "checksum keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "253bbe643c32c816bf58fa5a88248fafedeebb139705ad17a62add3517854a86" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "72ae89206cea31c32014b39d5a454b96135894221610dbfd19cf4d2d044fa546" -"checksum kvdb-memorydb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45bcdf5eb083602cff61a6f8438dce2a7900d714e893fc48781c39fb119d37aa" -"checksum kvdb-rocksdb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "06cf755dc587839ba34d3cbe3f12b6ad55850fbcdfe67336157a021a1a5c43ae" +"checksum kvdb-memorydb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "296c12309ed36cb74d59206406adbf1971c3baa56d5410efdb508d8f1c60a351" +"checksum kvdb-rocksdb 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96eb0e0112bb66fe5401294ca0f43c9cb771456af9270443545026e55fd00912" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lapin-async 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a78f5e949ded314f74be719426213f3dd872e02b1dff9ca8a2d98745962d073" "checksum lapin-async 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e1ad739d56453c51f7af0b74a4df4f60c83367f9042ccbb83d64b3796ea4095" "checksum lapin-futures 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83bc85315fb99af5a9cd0fdf13bf2530003046b0b83ee02249217064ad705a20" "checksum lapin-futures 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0de570ca372f3c6c317ffb382c45ed48ea7da013bfd20380cd53f37354095b4" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" -"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6" -"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" +"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" "checksum libusb 0.3.0 (git+https://github.com/paritytech/libusb-rs)" = "" "checksum libusb-sys 0.2.5 (git+https://github.com/paritytech/libusb-sys)" = "" "checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum local-encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1ceb20f39ff7ae42f3ff9795f3986b1daad821caaa1e1732a0944103a5a1a66" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" "checksum lunarity-lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a1670671f305792567116d4660e6e5bd785d6fa973e817c3445c0a7a54cecb6" -"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" +"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" +"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" -"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" +"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" +"checksum memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94da53143d45f6bad3753f532e56ad57a6a26c0ca6881794583310c7cb4c885f" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" -"checksum memorydb 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e143fbad9f90d2158bca3c4b09015276a6de6f085a77088943901cb26828780f" -"checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" -"checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" -"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" +"checksum mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "dd1d63acd1b78403cc0c325605908475dd9b9a3acbf65ed8bcab97e27014afcf" +"checksum mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" +"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" @@ -5189,45 +5360,45 @@ dependencies = [ "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" "checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" -"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" -"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" +"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" +"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" +"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum number_prefix 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dbf9993e59c894e3c08aa1c2712914e9e6bf1fcbfc6bef283e2183df345a4fee" -"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" -"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" +"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "efa535d5117d3661134dbf1719b6f0ffe06f2375843b13935db186cd094105eb" "checksum ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7eb5259643245d3f292c7a146b2df53bba24d7eab159410e648eb73dc164669d" "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5168b4cf41f3835e4bc6ffb32f51bc9365dc50cb351904595b3931d917fd0c" -"checksum parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8adf489acb31f1922db0ce43803b6f48a425241a8473611be3cc625a8e4a4c47" -"checksum parity-path 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5962540f99d3895d9addf535f37ab1397886bc2c68e59efd040ef458e5f8c3f7" +"checksum parity-crypto 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1b9c063d87e1507cb3807493c8d21859ef23b5414b39f81c53f0ba267d64c1" +"checksum parity-daemonize 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "69b1910b2793ff52713fca0a4ee92544ebec59ccd218ea74560be6f947b4ca77" +"checksum parity-path 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7b027aab22527061b7005cecf7805e8f42eed94ce89e76bac3a6035394b56627" "checksum parity-rocksdb 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d17caf6640e24b70242f3f48615e3f0764f98871e8c7aea25584e29833eb5a8" "checksum parity-rocksdb-sys 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9581e6b8c63f3808500638372ee56faaaffb57c4d349974bff591606b94d5f57" "checksum parity-snappy 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2c5f9d149b13134b8b354d93a92830efcbee6fe5b73a2e6e540fe70d4dd8a63" "checksum parity-snappy-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1a413d51e5e1927320c9de992998e4a279dffb8c8a7363570198bd8383e66f1b" "checksum parity-tokio-ipc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eb002c2d3539ccd3b82bd915ec060028d4ab350ad203dbffa20028c1e483af5b" "checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc" -"checksum parity-wordlist 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf13102febd98f4ad416a526b42deb82daf482626ba6ab10d0ebf8f45327514c" +"checksum parity-wordlist 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "573d08f0d3bc8a6ffcdac1de2725b5daeed8db26345a9c12d91648e2d6457f3e" +"checksum parity-ws 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2fec5048fba72a2e01baeb0d08089db79aead4b57e2443df172fb1840075a233" "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -"checksum patricia-trie 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "10438ba40c2f6e9ceca55277d8e7f6a5dafd58cabd802e6d97e16f02aab83a03" +"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +"checksum pbkdf2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0c09cddfbfc98de7f76931acf44460972edb4023eb14d0c6d4018800e552d8e0" "checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "933085deae3f32071f135d799d75667b63c8dc1f4537159756e3d4ceab41868c" +"checksum pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e4fb201c5c22a55d8b24fef95f78be52738e5e1361129be1b5e862ecdb6894a" "checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" -"checksum pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646" -"checksum pest_meta 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f249ea6de7c7b7aba92b4ff4376a994c6dbd98fd2166c89d5c4947397ecb574d" +"checksum pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9fcf299b5712d06ee128a556c94709aaa04512c4dffb8ead07c5c998447fc0" +"checksum pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df43fd99896fd72c485fe47542c7b500e4ac1e8700bf995544d1317a60ded547" "checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" -"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" -"checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" -"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" -"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" "checksum plain_hasher 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "95fa6386b1d34aaf0adb9b7dd2885dbe7c34190e6263785e5a7ec2b19044a90f" "checksum pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2412f3332a07c7a2a50168988dcc184f32180a9758ad470390e5f55e089f6b6e" "checksum primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0e31b86efadeaeb1235452171a66689682783149a6249ff334a2c5d8218d00a4" @@ -5235,12 +5406,15 @@ dependencies = [ "checksum primal-check 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e65f96c0a171f887198c274392c99a116ef65aa7f53f3b6d4902f493965c2d1" "checksum primal-estimate 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56ea4531dde757b56906493c8604641da14607bf9cdaa80fb9c9cabd2429f8d5" "checksum primal-sieve 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "da2d6ed369bb4b0273aeeb43f07c105c0117717cbae827b20719438eb2eb798c" +"checksum proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "114cdf1f426eb7f550f01af5f53a33c0946156f6814aec939b3bd77e844f9a9d" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum protobuf 1.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "52fbc45bf6709565e44ef31847eb7407b3c3c80af811ee884a04da071dcca12b" +"checksum proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afdc77cc74ec70ed262262942ebb7dac3d479e9e5cfa2da1841c0806f6cdabcc" +"checksum protobuf 1.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e14ccd6b79ec748412d4f2dfde1a80fa363a67def4062969f8aed3d790a30f28" "checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07" "checksum pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "efb0dcbddbb600f47a7098d33762a00552c671992171637f5bb310b37fe1f0e4" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rabbitmq_adaptor 0.3.3 (registry+https://dl.cloudsmith.io/ItqwH3F8rYFNB5vv/chronicled/platform-v2/cargo/index.git)" = "5d85c7caa1a0e1f555e8880cdd1f02dfe80fa16f5b92efe6793ab23773dbb239" "checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" @@ -5248,7 +5422,7 @@ dependencies = [ "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" @@ -5256,44 +5430,46 @@ dependencies = [ "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03b418169fb9c46533f326efd6eed2576699c44ca92d3052a066214a8d828929" -"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" -"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" +"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" +"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" -"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" "checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" -"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" +"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" +"checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" -"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" +"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a" -"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" +"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" +"checksum ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a" "checksum rlp 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "524c5ad554859785dfc8469df3ed5e0b5784d4d335877ed47c8d90fc0eb238fe" "checksum rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16d1effe9845d54f90e7be8420ee49e5c94623140b97ee4bc6fb5bfddb745720" "checksum rpassword 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b273c91bd242ca03ad6d71c143b6f17a48790e61f21a6c78568fa2b6774a24a4" "checksum rprompt 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1601f32bc5858aae3cbfa1c645c96c4d820cc5c16be0194f089560c00b6eb625" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rust-ini 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2" -"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" +"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "942b71057b31981152970d57399c25f72e27a6ee0d207a669d8304cabf44705b" -"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" +"checksum rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f271e3552cd835fa28c541c34a7e8fdd8cdff09d77fe4eb8f6c42e87a11b096e" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" -"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" -"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" +"checksum safemem 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b08423011dae9a5ca23f07cf57dac3857f5c885d352b76f6d95f4aea9434d0" +"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" "checksum sasl 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e457758c85b736bbad56dc099406cd2a9c19554cf81880dba7a51d092929e600" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum sct 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb8f61f9e6eadd062a71c380043d28036304a4706b3c4dd001ff3387ed00745a" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum scrypt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8570c5e2fa69cb29d492fd4e9974b6b5facb5a888e1c6da630d4a3cd7ebfef4a" +"checksum sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f5adf8fbd58e1b1b52699dc8bed2630faecb6d8c7bee77d009d6bbe4af569b9" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" "checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" "checksum serde-hjson 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0b833c5ad67d52ced5f5938b2980f32a9c1c5ef047f0b4fb3127e7a423c76153" -"checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f" +"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum serde_test 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" @@ -5303,25 +5479,26 @@ dependencies = [ "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum shell32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee04b46101f57121c9da2b151988283b6beb79b34f5bb29a58ee48cb695122c" "checksum siphasher 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "833011ca526bd88f16778d32c699d325a9ad302fa06381cd66f7be63351d3f6d" -"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum skeptic 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24ebf8a06f5f8bae61ae5bbc7af7aac4ef6907ae975130faba1199e5fe82256a" "checksum slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dbdd334bd28d328dad1c41b0ea662517883d8880d8533895ef96c8003dec9c4" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" -"checksum socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "4e626972d3593207547f14bf5fc9efa4d0e7283deb73fef1dff313dae9ab8878" +"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" +"checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" +"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" +"checksum stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8131256a5896cabcf5eb04f4d6dacbe1aefda854b0d9896e09cb58829ec5638c" +"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "032c03039aae92b350aad2e3779c352e104d919cb192ba2fabbd7b831ce4f0f6" "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" -"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" -"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" +"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" +"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327" -"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" -"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" +"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" "checksum thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1" @@ -5329,53 +5506,54 @@ dependencies = [ "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum timer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "31d42176308937165701f50638db1c31586f183f1aab416268216577aec7306b" -"checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f" -"checksum tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7655088894274afb52b807bd3c87072daa1fedd155068b8705cabfd628956115" -"checksum tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "cec6c34409089be085de9403ba2010b80e36938c9ca992c4f67f407bb13db0b1" +"checksum tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" +"checksum tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4574b75faccaacddb9b284faecdf0b544b80b6b294f3d062d325c5726a209c20" +"checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +"checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" -"checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e" +"checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" "checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" "checksum tokio-named-pipes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d282d483052288b2308ba5ee795f5673b159c9bdf63c385a05609da782a5eae" -"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" +"checksum tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c56391be9805bc80163151c0b9e5164ee64f4b0200962c346fea12773158f22d" "checksum tokio-retry 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f05746ae87dca83a2016b4f5dba5b237b897dd12fd324f60afe282112f16969a" -"checksum tokio-rustls 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "208d62fa3e015426e3c64039d9d20adf054a3c9b4d9445560f1c41c75bef3eab" +"checksum tokio-rustls 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "95a199832a67452c60bed18ed951d28d5755ff57b02b3d2d535d9f13a81ea6c9" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" -"checksum tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2f843ffdf8d6e1f90bddd48da43f99ab071660cd92b7ec560ef3cdfd7a409a" +"checksum tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2162248ff317e2bc713b261f242b69dbb838b85248ed20bb21df56d60ea4cae7" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72558af20be886ea124595ea0f806dd5703b8958e4705429dd58b3d8231f72f2" +"checksum tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd2c6a3885302581f4401c82af70d792bb9df1700e7437b0aeb4ada94d5388c" "checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc" -"checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" -"checksum tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "350c9edade9830dc185ae48ba45667a445ab59f6167ef6d0254ec9d2430d9dd3" -"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" +"checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" +"checksum tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" "checksum toolshed 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "450441e131c7663af72e63a33c02a6a1fbaaa8601dc652ed6757813bb55aeec7" "checksum trace-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe82f2f0bf1991e163e757baf044282823155dd326e70f44ce2186c3c320cc9" -"checksum transaction-pool 1.13.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e5866e5126b14358f1d7af4bf51a0be677a363799b90e655edcec8254edef1d2" +"checksum transaction-pool 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "454adc482e32785c3beab9415dd0f3c689f29cc2d16717eb62f6a784d53544b4" "checksum transient-hashmap 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aeb4b191d033a35edfce392a38cdcf9790b6cebcb30fa690c312c29da4dc433e" "checksum trezor-sys 1.0.0 (git+https://github.com/paritytech/trezor-sys)" = "" +"checksum trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7319e28ca295f27359d944a682f7f65b419158bf1590c92cadc0000258d788" "checksum trie-standardmap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e26f52976a57a0859616d6fcec87092ac35d08eabbd78dc3dabee93b480ea5f" -"checksum triehash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9cb3a626dd9a19a1b5f84087143b19409db793d902c5ddee4b6212020713f1" +"checksum triehash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d26efb4ddf87870fc08dc9a6580dc3061be350d7b9d0eb30aef1c8b4227aa46" "checksum try-lock 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2aa4715743892880f70885373966c83d73ef1b0838a664ef0c76fffd35e7c2" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" -"checksum ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77" -"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +"checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" +"checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" "checksum uint 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "754ba11732b9161b94c41798e5197e5e75388d012f760c42adb5000353e98646" -"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" +"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" -"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" -"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" +"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" +"checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" "checksum validator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "236a5eda3df2c877872e98dbc55d497d943792e6405d8fc65bd4f8a5e3b53c99" "checksum validator_derive 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d360d6f5754972c0c1da14fb3d5580daa31aee566e1e45e2f8d3bf5950ecd3e9" @@ -5383,20 +5561,19 @@ dependencies = [ "checksum vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c3365f36c57e5df714a34be40902b27a992eeddb9996eca52d0584611cf885d" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" +"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum want 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a05d9d966753fa4b5c8db73fcab5eed4549cfe0e1e4e66911e5564a0085c35d1" -"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" +"checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" "checksum wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b4a6d379e9332b1b1f52c5a87f2481c85c7c931d8ec411963dfb8f26b1ec1e3" -"checksum webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "17d7967316d8411ca3b01821ee6c332bde138ba4363becdb492f12e514daa17f" -"checksum webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85d1f408918fd590908a70d36b7ac388db2edc221470333e4d6e5b598e44cabf" +"checksum webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4f7e1cd7900a3a6b65a3e8780c51a3e6b59c0e2c55c6dc69578c288d69f7d082" +"checksum webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c10fa4212003ba19a564f25cd8ab572c6791f99a03cc219c13ed35ccab00de0e" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" -"checksum ws 0.7.9 (git+https://github.com/tomusdrw/ws-rs)" = "" +"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" "checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2" diff --git a/Cargo.toml b/Cargo.toml index 99bb4a45b2..8a9cbb2d0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ description = "Parity Ethereum client" name = "parity-ethereum" # NOTE Make sure to update util/version/Cargo.toml as well -version = "2.3.5" +version = "2.5.9" license = "GPL-3.0" authors = ["Parity Technologies "] @@ -29,10 +29,11 @@ serde_derive = "1.0" futures = "0.1" fdlimit = "0.1" ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" } -jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } -ethcore = { path = "ethcore", features = ["parity"] } +jsonrpc-core = "10.0.1" parity-bytes = "0.1" common-types = { path = "ethcore/types" } +ethcore = { path = "ethcore", features = ["parity"] } +ethcore-accounts = { path = "accounts", optional = true } ethcore-blockchain = { path = "ethcore/blockchain" } ethcore-call-contract = { path = "ethcore/call-contract"} ethcore-db = { path = "ethcore/db" } @@ -44,12 +45,13 @@ ethcore-network = { path = "util/network" } ethcore-private-tx = { path = "ethcore/private-tx" } ethcore-service = { path = "ethcore/service" } ethcore-sync = { path = "ethcore/sync" } -ethstore = { path = "accounts/ethstore" } ethereum-types = "0.4" -node-filter = { path = "ethcore/node-filter" } ethkey = { path = "accounts/ethkey" } +ethstore = { path = "accounts/ethstore" } +node-filter = { path = "ethcore/node-filter" } rlp = { version = "0.3.0", features = ["ethereum"] } cli-signer= { path = "cli-signer" } +parity-daemonize = "0.3" parity-hash-fetch = { path = "updater/hash-fetch" } parity-ipfs-api = { path = "ipfs" } parity-local-store = { path = "miner/local-store" } @@ -80,22 +82,22 @@ pretty_assertions = "0.1" ipnetwork = "0.12.6" tempdir = "0.3" fake-fetch = { path = "util/fake-fetch" } - -[target.'cfg(not(windows))'.dependencies] -daemonize = "0.3" +lazy_static = "1.2.0" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3.4", features = ["winsock2", "winuser", "shellapi"] } [features] +default = ["accounts"] +accounts = ["ethcore-accounts", "parity-rpc/accounts"] miner-debug = ["ethcore/miner-debug"] json-tests = ["ethcore/json-tests"] -ci-skip-issue = ["ethcore/ci-skip-issue"] +ci-skip-tests = ["ethcore/ci-skip-tests"] test-heavy = ["ethcore/test-heavy"] evm-debug = ["ethcore/evm-debug"] evm-debug-tests = ["ethcore/evm-debug-tests"] slow-blocks = ["ethcore/slow-blocks"] -secretstore = ["ethcore-secretstore"] +secretstore = ["ethcore-secretstore", "ethcore-secretstore/accounts"] final = ["parity-version/final"] deadlock_detection = ["parking_lot/deadlock_detection"] # to create a memory profile (requires nightly rust), use e.g. @@ -117,10 +119,13 @@ path = "parity/lib.rs" path = "parity/main.rs" name = "parity" -[profile.dev] +[profile.test] +lto = false +opt-level = 3 # makes tests slower to compile, but faster to run [profile.release] debug = false +lto = true [workspace] # This should only list projects that are not @@ -137,7 +142,8 @@ members = [ "util/triehash-ethereum", "util/keccak-hasher", "util/patricia-trie-ethereum", - "util/fastmap" + "util/fastmap", + "util/time-utils" ] [patch.crates-io] diff --git a/README.md b/README.md index efb2d28518..b244256725 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,24 @@

+## Table of Contents + +1. [Description](#chapter-001) +2. [Technical Overview](#chapter-002) +3. [Building](#chapter-003)
+ 3.1 [Building Dependencies](#chapter-0031)
+ 3.2 [Building from Source Code](#chapter-0032)
+ 3.3 [Simple One-Line Installer for Mac and Linux](#chapter-0033)
+ 3.4 [Starting Parity Ethereum](#chapter-0034) +4. [Documentation](#chapter-004) +5. [Toolchain](#chapter-005) +6. [Community](#chapter-006) +7. [Contributing](#chapter-007) +8. [License](#chapter-008) + + +## 1. Description + **Built for mission-critical use**: Miners, service providers, and exchanges need fast synchronisation and maximum uptime. Parity Ethereum provides the core infrastructure essential for speedy and reliable services. - Clean, modular codebase for easy customisation @@ -15,7 +33,7 @@ - Synchronise in hours, not days with Warp Sync - Modular for light integration into your service or product -## Technical Overview +## 2. Technical Overview Parity Ethereum's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity Ethereum using the sophisticated and cutting-edge **Rust programming language**. Parity Ethereum is licensed under the GPLv3 and can be used for all your Ethereum needs. @@ -25,7 +43,9 @@ If you run into problems while using Parity Ethereum, check out the [wiki for do Parity Ethereum's current beta-release is 2.1. You can download it at [the releases page](https://github.com/paritytech/parity-ethereum/releases) or follow the instructions below to build from source. Please, mind the [CHANGELOG.md](CHANGELOG.md) for a list of all changes between different versions. -## Build Dependencies +## 3. Building + +### 3.1 Build Dependencies Parity Ethereum requires **latest stable Rust version** to build. @@ -58,7 +78,7 @@ Once you have `rustup` installed, then you need to install: Make sure that these binaries are in your `PATH`. After that, you should be able to build Parity Ethereum from source. -## Build from Source Code +### 3.2 Build from Source Code ```bash # download Parity Ethereum code @@ -95,7 +115,7 @@ or $ git checkout beta ``` -## Simple One-Line Installer for Mac and Linux +### 3.3 Simple One-Line Installer for Mac and Linux ```bash bash <(curl https://get.parity.io -L) @@ -107,9 +127,9 @@ The one-line installer always defaults to the latest beta release. To install a bash <(curl https://get.parity.io -L) -r stable ``` -## Start Parity Ethereum +### 3.4 Starting Parity Ethereum -### Manually +#### Manually To start Parity Ethereum manually, just run @@ -119,25 +139,212 @@ $ ./target/release/parity so Parity Ethereum begins syncing the Ethereum blockchain. -### Using `systemd` service file +#### Using `systemd` service file To start Parity Ethereum as a regular user using `systemd` init: 1. Copy `./scripts/parity.service` to your `systemd` user directory (usually `~/.config/systemd/user`). -2. To configure Parity Ethereum, write a `/etc/parity/config.toml` config file, see [Configuring Parity Ethereum](https://paritytech.github.io/wiki/Configuring-Parity) for details. +2. Copy release to bin folder, write `sudo install ./target/release/parity /usr/bin/parity` +3. To configure Parity Ethereum, write a `/etc/parity/config.toml` config file, see [Configuring Parity Ethereum](https://paritytech.github.io/wiki/Configuring-Parity) for details. + +## 4. Documentation + +Official website: https://parity.io + +Be sure to [check out our wiki](https://wiki.parity.io) for more information. + +### Viewing documentation for Parity Ethereum packages + +You can generate documentation for Parity Ethereum Rust packages that automatically opens in your web browser using [rustdoc with Cargo](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html#using-rustdoc-with-cargo) (of the The Rustdoc Book), by running the the following commands: + +* **All** packages + ``` + cargo doc --open + ``` + +* Specific package + ``` + cargo doc --package --open + ``` + +Replacing `` with one of the following from the details section below (i.e. `cargo doc --package parity-ethereum --open`): + +

+ +* Parity Ethereum (EthCore) Client Application + ```bash + parity-ethereum + ``` +* Parity Ethereum Account Management, Key Management Tool, and Keys Generator + ```bash + ethcore-accounts, ethkey-cli, ethstore, ethstore-cli + ``` +* Parity Chain Specification + ```bash + chainspec + ``` +* Parity CLI Signer Tool & RPC Client + ```bash + cli-signer parity-rpc-client + ``` +* Parity Ethereum Ethash & ProgPoW Implementations + ```bash + ethash + ``` +* Parity (EthCore) Library + ```bash + ethcore + ``` + * Parity Ethereum Blockchain Database, Test Generator, Configuration, +Caching, Importing Blocks, and Block Information + ```bash + ethcore-blockchain + ``` + * Parity Ethereum (EthCore) Contract Calls and Blockchain Service & Registry Information + ```bash + ethcore-call-contract + ``` + * Parity Ethereum (EthCore) Database Access & Utilities, Database Cache Manager + ```bash + ethcore-db + ``` + * Parity Ethereum Virtual Machine (EVM) Rust Implementation + ```bash + evm + ``` + * Parity Ethereum (EthCore) Light Client Implementation + ```bash + ethcore-light + ``` + * Parity Smart Contract based Node Filter, Manage Permissions of Network Connections + ```bash + node-filter + ``` + * Parity Private Transactions + ```bash + ethcore-private-tx + ``` + * Parity Ethereum (EthCore) Client & Network Service Creation & Registration with the I/O Subsystem + ```bash + ethcore-service + ``` + * Parity Ethereum (EthCore) Blockchain Synchronization + ```bash + ethcore-sync + ``` + * Parity Ethereum Common Types + ```bash + common-types + ``` + * Parity Ethereum Virtual Machines (VM) Support Library + ```bash + vm + ``` + * Parity Ethereum WASM Interpreter + ```bash + wasm + ``` + * Parity Ethereum WASM Test Runner + ```bash + pwasm-run-test + ``` + * Parity EVM Implementation + ```bash + evmbin + ``` + * Parity Ethereum IPFS-compatible API + ```bash + parity-ipfs-api + ``` + * Parity Ethereum JSON Deserialization + ```bash + ethjson + ``` + * Parity Ethereum State Machine Generalization for Consensus Engines + ```bash + parity-machine + ``` +* Parity Ethereum (EthCore) Miner Interface + ```bash + ethcore-miner parity-local-store price-info ethcore-stratum using_queue + ``` +* Parity Ethereum (EthCore) Logger Implementation + ```bash + ethcore-logger + ``` +* C bindings library for the Parity Ethereum client + ```bash + parity-clib + ``` +* Parity Ethereum JSON-RPC Servers + ```bash + parity-rpc + ``` +* Parity Ethereum (EthCore) Secret Store + ```bash + ethcore-secretstore + ``` +* Parity Updater Service + ```bash + parity-updater parity-hash-fetch + ``` +* Parity Core Libraries (Parity Util) + ```bash + ethcore-bloom-journal blooms-db dir eip-712 fake-fetch fastmap fetch ethcore-io + journaldb keccak-hasher len-caching-lock macros memory-cache memzero + migration-rocksdb ethcore-network ethcore-network-devp2p panic_hook + patricia-trie-ethereum registrar rlp_compress rlp_derive parity-runtime stats + time-utils triehash-ethereum unexpected parity-version + ``` +* Parity Whisper Protocol Implementation + ```bash + parity-whisper whisper-cli + ``` + +

+ +### Contributing to documentation for Parity Ethereum packages + +[Document source code](https://doc.rust-lang.org/1.9.0/book/documentation.html) for Parity Ethereum packages by annotating the source code with documentation comments. + +Example (generic documentation comment): +```markdown +/// Summary +/// +/// Description +/// +/// # Panics +/// +/// # Errors +/// +/// # Safety +/// +/// # Examples +/// +/// Summary of Example 1 +/// +/// ```rust +/// // insert example 1 code here for use with documentation as tests +/// ``` +/// +``` -## Parity Ethereum toolchain +## 5. Toolchain In addition to the Parity Ethereum client, there are additional tools in this repository available: -- [evmbin](https://github.com/paritytech/parity-ethereum/blob/master/evmbin/) - EVM implementation for Parity Ethereum. -- [ethabi](https://github.com/paritytech/ethabi) - Parity Ethereum function calls encoding. -- [ethstore](https://github.com/paritytech/parity-ethereum/blob/master/accounts/ethstore) - Parity Ethereum key management. -- [ethkey](https://github.com/paritytech/parity-ethereum/blob/master/accounts/ethkey) - Parity Ethereum keys generator. -- [whisper](https://github.com/paritytech/parity-ethereum/blob/master/whisper/) - Implementation of Whisper-v2 PoC. +- [evmbin](./evmbin) - Parity Ethereum EVM Implementation. +- [ethstore](./accounts/ethstore) - Parity Ethereum Key Management. +- [ethkey](./accounts/ethkey) - Parity Ethereum Keys Generator. +- [whisper](./whisper) - Parity Ethereum Whisper-v2 PoC Implementation. -## Join the chat! +The following tool is available in a separate repository: +- [ethabi](https://github.com/paritytech/ethabi) - Parity Ethereum Encoding of Function Calls. [Docs here](https://crates.io/crates/ethabi) + +## 6. Community + +### Join the chat! Questions? Get in touch with us on Gitter: [![Gitter: Parity](https://img.shields.io/badge/gitter-parity-4AB495.svg)](https://gitter.im/paritytech/parity) @@ -148,8 +355,14 @@ Questions? Get in touch with us on Gitter: Alternatively, join our community on Matrix: [![Riot: +Parity](https://img.shields.io/badge/riot-%2Bparity%3Amatrix.parity.io-orange.svg)](https://riot.im/app/#/group/+parity:matrix.parity.io) -## Documentation +## 7. Contributing -Official website: https://parity.io +An introduction has been provided in the ["So You Want to be a Core Developer" presentation slides by Hernando Castano](http://tiny.cc/contrib-to-parity-eth). Additional guidelines are provided in [CONTRIBUTING](./.github/CONTRIBUTING.md). -Be sure to [check out our wiki](https://wiki.parity.io) for more information. +### Contributor Code of Conduct + +[CODE_OF_CONDUCT](./.github/CODE_OF_CONDUCT.md) + +## 8. License + +[LICENSE](./LICENSE) diff --git a/accounts/Cargo.toml b/accounts/Cargo.toml new file mode 100644 index 0000000000..12100df6ed --- /dev/null +++ b/accounts/Cargo.toml @@ -0,0 +1,28 @@ +[package] +description = "Parity Ethereum Account Management" +homepage = "http://parity.io" +license = "GPL-3.0" +name = "ethcore-accounts" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +common-types = { path = "../ethcore/types" } +ethkey = { path = "ethkey" } +ethstore = { path = "ethstore" } +log = "0.4" +parking_lot = "0.7" +serde = "1.0" +serde_derive = "1.0" +serde_json = "1.0" + +[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))'.dependencies] +hardware-wallet = { path = "hw" } + +[target.'cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))'.dependencies] +fake-hardware-wallet = { path = "fake-hardware-wallet" } + +[dev-dependencies] +ethereum-types = "0.4" +tempdir = "0.3" diff --git a/accounts/ethkey/Cargo.toml b/accounts/ethkey/Cargo.toml index 3dddcc1ce1..c10949622c 100644 --- a/accounts/ethkey/Cargo.toml +++ b/accounts/ethkey/Cargo.toml @@ -1,18 +1,18 @@ [package] +description = "Parity Ethereum Keys Generator" name = "ethkey" version = "0.3.0" authors = ["Parity Technologies "] [dependencies] -byteorder = "1.0" edit-distance = "2.0" -parity-crypto = "0.2" +parity-crypto = "0.3.0" eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" } ethereum-types = "0.4" lazy_static = "1.0" log = "0.4" memzero = { path = "../../util/memzero" } -parity-wordlist = "1.2" +parity-wordlist = "1.3" quick-error = "1.2.2" rand = "0.4" rustc-hex = "1.0" diff --git a/accounts/ethkey/README.md b/accounts/ethkey/README.md index 896d38e83f..23c57fa4ca 100644 --- a/accounts/ethkey/README.md +++ b/accounts/ethkey/README.md @@ -5,8 +5,8 @@ Parity Ethereum keys generator. ### Usage ``` -Parity Ethereum keys generator. - Copyright 2015-2018 Parity Technologies (UK) Ltd. +Parity Ethereum Keys Generator. + Copyright 2015-2019 Parity Technologies (UK) Ltd. Usage: ethkey info [options] diff --git a/accounts/ethkey/cli/Cargo.toml b/accounts/ethkey/cli/Cargo.toml index d43aa2c5c0..c1d44897cc 100644 --- a/accounts/ethkey/cli/Cargo.toml +++ b/accounts/ethkey/cli/Cargo.toml @@ -1,4 +1,5 @@ [package] +description = "Parity Ethereum Keys Generator CLI" name = "ethkey-cli" version = "0.1.0" authors = ["Parity Technologies "] @@ -8,7 +9,7 @@ docopt = "1.0" env_logger = "0.5" ethkey = { path = "../" } panic_hook = { path = "../../../util/panic-hook" } -parity-wordlist="1.2" +parity-wordlist="1.3" rustc-hex = "1.0" serde = "1.0" serde_derive = "1.0" diff --git a/accounts/ethkey/cli/src/main.rs b/accounts/ethkey/cli/src/main.rs index ecb612e069..759f5f484c 100644 --- a/accounts/ethkey/cli/src/main.rs +++ b/accounts/ethkey/cli/src/main.rs @@ -35,7 +35,7 @@ use rustc_hex::{FromHex, FromHexError}; const USAGE: &'static str = r#" Parity Ethereum keys generator. - Copyright 2015-2018 Parity Technologies (UK) Ltd. + Copyright 2015-2019 Parity Technologies (UK) Ltd. Usage: ethkey info [options] diff --git a/accounts/ethkey/src/extended.rs b/accounts/ethkey/src/extended.rs index 7d02271ebb..401d98f2f6 100644 --- a/accounts/ethkey/src/extended.rs +++ b/accounts/ethkey/src/extended.rs @@ -35,9 +35,8 @@ impl Label for u32 { fn len() -> usize { 4 } fn store(&self, target: &mut [u8]) { - use byteorder::{BigEndian, ByteOrder}; - - BigEndian::write_u32(&mut target[0..4], *self); + let bytes = self.to_be_bytes(); + target[0..4].copy_from_slice(&bytes); } } diff --git a/accounts/ethkey/src/lib.rs b/accounts/ethkey/src/lib.rs index 5c58333c71..2a1968bbea 100644 --- a/accounts/ethkey/src/lib.rs +++ b/accounts/ethkey/src/lib.rs @@ -16,7 +16,6 @@ // #![warn(missing_docs)] -extern crate byteorder; extern crate edit_distance; extern crate parity_crypto; extern crate ethereum_types; diff --git a/accounts/ethstore/Cargo.toml b/accounts/ethstore/Cargo.toml index 96d24d8c31..af497bcff3 100644 --- a/accounts/ethstore/Cargo.toml +++ b/accounts/ethstore/Cargo.toml @@ -1,4 +1,5 @@ [package] +description = "Parity Ethereum Key Management" name = "ethstore" version = "0.2.1" authors = ["Parity Technologies "] @@ -16,12 +17,13 @@ tiny-keccak = "1.4" time = "0.1.34" itertools = "0.5" parking_lot = "0.7" -parity-crypto = "0.2" +parity-crypto = "0.3.0" ethereum-types = "0.4" dir = { path = "../../util/dir" } smallvec = "0.6" -parity-wordlist = "1.0" +parity-wordlist = "1.3" tempdir = "0.3" +lazy_static = "1.2.0" [dev-dependencies] matches = "0.1" diff --git a/accounts/ethstore/README.md b/accounts/ethstore/README.md index fc988c2d31..77c37bd246 100644 --- a/accounts/ethstore/README.md +++ b/accounts/ethstore/README.md @@ -6,7 +6,7 @@ Parity Ethereum key management. ``` Parity Ethereum key management tool. - Copyright 2015-2018 Parity Technologies (UK) Ltd. + Copyright 2015-2019 Parity Technologies (UK) Ltd. Usage: ethstore insert [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] diff --git a/accounts/ethstore/cli/Cargo.toml b/accounts/ethstore/cli/Cargo.toml index 82858eaa76..9578a75377 100644 --- a/accounts/ethstore/cli/Cargo.toml +++ b/accounts/ethstore/cli/Cargo.toml @@ -1,4 +1,5 @@ [package] +description = "Parity Ethereum Key Management CLI" name = "ethstore-cli" version = "0.1.1" authors = ["Parity Technologies "] diff --git a/accounts/ethstore/cli/src/main.rs b/accounts/ethstore/cli/src/main.rs index 6ee1914a00..0f56440639 100644 --- a/accounts/ethstore/cli/src/main.rs +++ b/accounts/ethstore/cli/src/main.rs @@ -41,7 +41,7 @@ mod crack; pub const USAGE: &'static str = r#" Parity Ethereum key management tool. - Copyright 2015-2018 Parity Technologies (UK) Ltd. + Copyright 2015-2019 Parity Technologies (UK) Ltd. Usage: ethstore insert [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] diff --git a/accounts/ethstore/src/account/crypto.rs b/accounts/ethstore/src/account/crypto.rs index e2cc5dc515..a3f6f9e9a3 100644 --- a/accounts/ethstore/src/account/crypto.rs +++ b/accounts/ethstore/src/account/crypto.rs @@ -15,6 +15,7 @@ // along with Parity Ethereum. If not, see . use std::str; +use std::num::NonZeroU32; use ethkey::{Password, Secret}; use {json, Error, crypto}; use crypto::Keccak256; @@ -73,12 +74,12 @@ impl From for String { impl Crypto { /// Encrypt account secret - pub fn with_secret(secret: &Secret, password: &Password, iterations: u32) -> Result { + pub fn with_secret(secret: &Secret, password: &Password, iterations: NonZeroU32) -> Result { Crypto::with_plain(&*secret, password, iterations) } /// Encrypt custom plain data - pub fn with_plain(plain: &[u8], password: &Password, iterations: u32) -> Result { + pub fn with_plain(plain: &[u8], password: &Password, iterations: NonZeroU32) -> Result { let salt: [u8; 32] = Random::random(); let iv: [u8; 16] = Random::random(); @@ -159,13 +160,17 @@ impl Crypto { #[cfg(test)] mod tests { use ethkey::{Generator, Random}; - use super::{Crypto, Error}; + use super::{Crypto, Error, NonZeroU32}; + + lazy_static! { + static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed"); + } #[test] fn crypto_with_secret_create() { let keypair = Random.generate().unwrap(); let passwd = "this is sparta".into(); - let crypto = Crypto::with_secret(keypair.secret(), &passwd, 10240).unwrap(); + let crypto = Crypto::with_secret(keypair.secret(), &passwd, *ITERATIONS).unwrap(); let secret = crypto.secret(&passwd).unwrap(); assert_eq!(keypair.secret(), &secret); } @@ -173,7 +178,7 @@ mod tests { #[test] fn crypto_with_secret_invalid_password() { let keypair = Random.generate().unwrap(); - let crypto = Crypto::with_secret(keypair.secret(), &"this is sparta".into(), 10240).unwrap(); + let crypto = Crypto::with_secret(keypair.secret(), &"this is sparta".into(), *ITERATIONS).unwrap(); assert_matches!(crypto.secret(&"this is sparta!".into()), Err(Error::InvalidPassword)) } @@ -181,7 +186,7 @@ mod tests { fn crypto_with_null_plain_data() { let original_data = b""; let passwd = "this is sparta".into(); - let crypto = Crypto::with_plain(&original_data[..], &passwd, 10240).unwrap(); + let crypto = Crypto::with_plain(&original_data[..], &passwd, *ITERATIONS).unwrap(); let decrypted_data = crypto.decrypt(&passwd).unwrap(); assert_eq!(original_data[..], *decrypted_data); } @@ -190,7 +195,7 @@ mod tests { fn crypto_with_tiny_plain_data() { let original_data = b"{}"; let passwd = "this is sparta".into(); - let crypto = Crypto::with_plain(&original_data[..], &passwd, 10240).unwrap(); + let crypto = Crypto::with_plain(&original_data[..], &passwd, *ITERATIONS).unwrap(); let decrypted_data = crypto.decrypt(&passwd).unwrap(); assert_eq!(original_data[..], *decrypted_data); } @@ -199,7 +204,7 @@ mod tests { fn crypto_with_huge_plain_data() { let original_data: Vec<_> = (1..65536).map(|i| (i % 256) as u8).collect(); let passwd = "this is sparta".into(); - let crypto = Crypto::with_plain(&original_data, &passwd, 10240).unwrap(); + let crypto = Crypto::with_plain(&original_data, &passwd, *ITERATIONS).unwrap(); let decrypted_data = crypto.decrypt(&passwd).unwrap(); assert_eq!(&original_data, &decrypted_data); } diff --git a/accounts/ethstore/src/account/kdf.rs b/accounts/ethstore/src/account/kdf.rs index dfa1dea496..06b361cdca 100644 --- a/accounts/ethstore/src/account/kdf.rs +++ b/accounts/ethstore/src/account/kdf.rs @@ -15,6 +15,7 @@ // along with Parity Ethereum. If not, see . use json; +use std::num::NonZeroU32; #[derive(Debug, PartialEq, Clone)] pub enum Prf { @@ -23,7 +24,7 @@ pub enum Prf { #[derive(Debug, PartialEq, Clone)] pub struct Pbkdf2 { - pub c: u32, + pub c: NonZeroU32, pub dklen: u32, pub prf: Prf, pub salt: Vec, diff --git a/accounts/ethstore/src/account/safe_account.rs b/accounts/ethstore/src/account/safe_account.rs index 7a38e79fa2..63971ef6a2 100644 --- a/accounts/ethstore/src/account/safe_account.rs +++ b/accounts/ethstore/src/account/safe_account.rs @@ -20,6 +20,7 @@ use {json, Error}; use account::Version; use crypto; use super::crypto::Crypto; +use std::num::NonZeroU32; /// Account representation. #[derive(Debug, PartialEq, Clone)] @@ -59,7 +60,7 @@ impl SafeAccount { keypair: &KeyPair, id: [u8; 16], password: &Password, - iterations: u32, + iterations: NonZeroU32, name: String, meta: String ) -> Result { @@ -135,7 +136,7 @@ impl SafeAccount { } /// Create a new `VaultKeyFile` from the given `self` - pub fn into_vault_file(self, iterations: u32, password: &Password) -> Result { + pub fn into_vault_file(self, iterations: NonZeroU32, password: &Password) -> Result { let meta_plain = json::VaultKeyMeta { address: self.address.into(), name: Some(self.name), @@ -177,7 +178,7 @@ impl SafeAccount { } /// Change account's password. - pub fn change_password(&self, old_password: &Password, new_password: &Password, iterations: u32) -> Result { + pub fn change_password(&self, old_password: &Password, new_password: &Password, iterations: NonZeroU32) -> Result { let secret = self.crypto.secret(old_password)?; let result = SafeAccount { id: self.id.clone(), @@ -200,14 +201,19 @@ impl SafeAccount { #[cfg(test)] mod tests { use ethkey::{Generator, Random, verify_public, Message}; - use super::SafeAccount; + use super::{SafeAccount, NonZeroU32}; + + lazy_static! { + static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed"); + } + #[test] fn sign_and_verify_public() { let keypair = Random.generate().unwrap(); let password = "hello world".into(); let message = Message::default(); - let account = SafeAccount::create(&keypair, [0u8; 16], &password, 10240, "Test".to_owned(), "{}".to_owned()); + let account = SafeAccount::create(&keypair, [0u8; 16], &password, *ITERATIONS, "Test".to_owned(), "{}".to_owned()); let signature = account.unwrap().sign(&password, &message).unwrap(); assert!(verify_public(keypair.public(), &signature, &message).unwrap()); } @@ -217,10 +223,9 @@ mod tests { let keypair = Random.generate().unwrap(); let first_password = "hello world".into(); let sec_password = "this is sparta".into(); - let i = 10240; let message = Message::default(); - let account = SafeAccount::create(&keypair, [0u8; 16], &first_password, i, "Test".to_owned(), "{}".to_owned()).unwrap(); - let new_account = account.change_password(&first_password, &sec_password, i).unwrap(); + let account = SafeAccount::create(&keypair, [0u8; 16], &first_password, *ITERATIONS, "Test".to_owned(), "{}".to_owned()).unwrap(); + let new_account = account.change_password(&first_password, &sec_password, *ITERATIONS).unwrap(); assert!(account.sign(&first_password, &message).is_ok()); assert!(account.sign(&sec_password, &message).is_err()); assert!(new_account.sign(&first_password, &message).is_err()); diff --git a/accounts/ethstore/src/accounts_dir/disk.rs b/accounts/ethstore/src/accounts_dir/disk.rs index 2bbb766773..00c59b254d 100644 --- a/accounts/ethstore/src/accounts_dir/disk.rs +++ b/accounts/ethstore/src/accounts_dir/disk.rs @@ -356,11 +356,16 @@ mod test { extern crate tempdir; use std::{env, fs}; + use std::num::NonZeroU32; use super::{KeyDirectory, RootDiskDirectory, VaultKey}; use account::SafeAccount; use ethkey::{Random, Generator}; use self::tempdir::TempDir; + lazy_static! { + static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(1024).expect("1024 > 0; qed"); + } + #[test] fn should_create_new_account() { // given @@ -371,7 +376,7 @@ mod test { let directory = RootDiskDirectory::create(dir.clone()).unwrap(); // when - let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned()); + let account = SafeAccount::create(&keypair, [0u8; 16], &password, *ITERATIONS, "Test".to_owned(), "{}".to_owned()); let res = directory.insert(account.unwrap()); // then @@ -392,7 +397,7 @@ mod test { let directory = RootDiskDirectory::create(dir.clone()).unwrap(); // when - let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned()).unwrap(); + let account = SafeAccount::create(&keypair, [0u8; 16], &password, *ITERATIONS, "Test".to_owned(), "{}".to_owned()).unwrap(); let filename = "test".to_string(); let dedup = true; @@ -428,7 +433,7 @@ mod test { // and when let before_root_items_count = fs::read_dir(&dir).unwrap().count(); - let vault = directory.as_vault_provider().unwrap().create(vault_name, VaultKey::new(&password, 1024)); + let vault = directory.as_vault_provider().unwrap().create(vault_name, VaultKey::new(&password, *ITERATIONS)); // then assert!(vault.is_ok()); @@ -436,7 +441,7 @@ mod test { assert!(after_root_items_count > before_root_items_count); // and when - let vault = directory.as_vault_provider().unwrap().open(vault_name, VaultKey::new(&password, 1024)); + let vault = directory.as_vault_provider().unwrap().open(vault_name, VaultKey::new(&password, *ITERATIONS)); // then assert!(vault.is_ok()); @@ -453,8 +458,9 @@ mod test { let temp_path = TempDir::new("").unwrap(); let directory = RootDiskDirectory::create(&temp_path).unwrap(); let vault_provider = directory.as_vault_provider().unwrap(); - vault_provider.create("vault1", VaultKey::new(&"password1".into(), 1)).unwrap(); - vault_provider.create("vault2", VaultKey::new(&"password2".into(), 1)).unwrap(); + let iter = NonZeroU32::new(1).expect("1 > 0; qed"); + vault_provider.create("vault1", VaultKey::new(&"password1".into(), iter)).unwrap(); + vault_provider.create("vault2", VaultKey::new(&"password2".into(), iter)).unwrap(); // then let vaults = vault_provider.list_vaults().unwrap(); @@ -476,7 +482,7 @@ mod test { let keypair = Random.generate().unwrap(); let password = "test pass".into(); - let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned()); + let account = SafeAccount::create(&keypair, [0u8; 16], &password, *ITERATIONS, "Test".to_owned(), "{}".to_owned()); directory.insert(account.unwrap()).expect("Account should be inserted ok"); let new_hash = directory.files_hash().expect("New files hash should be calculated ok"); diff --git a/accounts/ethstore/src/accounts_dir/mod.rs b/accounts/ethstore/src/accounts_dir/mod.rs index 300c395222..9b1328e115 100644 --- a/accounts/ethstore/src/accounts_dir/mod.rs +++ b/accounts/ethstore/src/accounts_dir/mod.rs @@ -17,6 +17,7 @@ //! Accounts Directory use ethkey::Password; +use std::num::NonZeroU32; use std::path::{PathBuf}; use {SafeAccount, Error}; @@ -41,7 +42,7 @@ pub struct VaultKey { /// Vault password pub password: Password, /// Number of iterations to produce a derived key from password - pub iterations: u32, + pub iterations: NonZeroU32, } /// Keys directory @@ -96,7 +97,7 @@ pub use self::vault::VaultDiskDirectory; impl VaultKey { /// Create new vault key - pub fn new(password: &Password, iterations: u32) -> Self { + pub fn new(password: &Password, iterations: NonZeroU32) -> Self { VaultKey { password: password.clone(), iterations: iterations, diff --git a/accounts/ethstore/src/accounts_dir/vault.rs b/accounts/ethstore/src/accounts_dir/vault.rs index 1aea7e104c..c54de7c12c 100644 --- a/accounts/ethstore/src/accounts_dir/vault.rs +++ b/accounts/ethstore/src/accounts_dir/vault.rs @@ -282,11 +282,17 @@ mod test { use std::fs; use std::io::Write; + use std::num::NonZeroU32; use std::path::PathBuf; use super::VaultKey; use super::{VAULT_FILE_NAME, check_vault_name, make_vault_dir_path, create_vault_file, read_vault_file, VaultDiskDirectory}; use self::tempdir::TempDir; + + lazy_static! { + static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(1024).expect("1024 > 0; qed"); + } + #[test] fn check_vault_name_succeeds() { assert!(check_vault_name("vault")); @@ -325,7 +331,7 @@ mod test { fn create_vault_file_succeeds() { // given let temp_path = TempDir::new("").unwrap(); - let key = VaultKey::new(&"password".into(), 1024); + let key = VaultKey::new(&"password".into(), *ITERATIONS); let mut vault_dir: PathBuf = temp_path.path().into(); vault_dir.push("vault"); fs::create_dir_all(&vault_dir).unwrap(); @@ -344,7 +350,7 @@ mod test { fn read_vault_file_succeeds() { // given let temp_path = TempDir::new("").unwrap(); - let key = VaultKey::new(&"password".into(), 1024); + let key = VaultKey::new(&"password".into(), *ITERATIONS); let vault_file_contents = r#"{"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"758696c8dc6378ab9b25bb42790da2f5"},"ciphertext":"54eb50683717d41caaeb12ea969f2c159daada5907383f26f327606a37dc7168","kdf":"pbkdf2","kdfparams":{"c":1024,"dklen":32,"prf":"hmac-sha256","salt":"3c320fa566a1a7963ac8df68a19548d27c8f40bf92ef87c84594dcd5bbc402b6"},"mac":"9e5c2314c2a0781962db85611417c614bd6756666b6b1e93840f5b6ed895f003"}}"#; let dir: PathBuf = temp_path.path().into(); let mut vault_file_path: PathBuf = dir.clone(); @@ -365,7 +371,7 @@ mod test { fn read_vault_file_fails() { // given let temp_path = TempDir::new("").unwrap(); - let key = VaultKey::new(&"password1".into(), 1024); + let key = VaultKey::new(&"password1".into(), *ITERATIONS); let dir: PathBuf = temp_path.path().into(); let mut vault_file_path: PathBuf = dir.clone(); vault_file_path.push(VAULT_FILE_NAME); @@ -394,7 +400,7 @@ mod test { fn vault_directory_can_be_created() { // given let temp_path = TempDir::new("").unwrap(); - let key = VaultKey::new(&"password".into(), 1024); + let key = VaultKey::new(&"password".into(), *ITERATIONS); let dir: PathBuf = temp_path.path().into(); // when @@ -414,7 +420,7 @@ mod test { fn vault_directory_cannot_be_created_if_already_exists() { // given let temp_path = TempDir::new("").unwrap(); - let key = VaultKey::new(&"password".into(), 1024); + let key = VaultKey::new(&"password".into(), *ITERATIONS); let dir: PathBuf = temp_path.path().into(); let mut vault_dir = dir.clone(); vault_dir.push("vault"); @@ -431,7 +437,7 @@ mod test { fn vault_directory_cannot_be_opened_if_not_exists() { // given let temp_path = TempDir::new("").unwrap(); - let key = VaultKey::new(&"password".into(), 1024); + let key = VaultKey::new(&"password".into(), *ITERATIONS); let dir: PathBuf = temp_path.path().into(); // when diff --git a/accounts/ethstore/src/ethstore.rs b/accounts/ethstore/src/ethstore.rs index 7207db7260..92eb949673 100644 --- a/accounts/ethstore/src/ethstore.rs +++ b/accounts/ethstore/src/ethstore.rs @@ -15,12 +15,12 @@ // along with Parity Ethereum. If not, see . use std::collections::{BTreeMap, HashMap}; +use std::num::NonZeroU32; use std::mem; use std::path::PathBuf; use parking_lot::{Mutex, RwLock}; use std::time::{Instant, Duration}; -use crypto::KEY_ITERATIONS; use random::Random; use ethkey::{self, Signature, Password, Address, Message, Secret, Public, KeyPair, ExtendedKeyPair}; use accounts_dir::{KeyDirectory, VaultKeyDirectory, VaultKey, SetKeyError}; @@ -29,6 +29,12 @@ use presale::PresaleWallet; use json::{self, Uuid, OpaqueKeyFile}; use {import, Error, SimpleSecretStore, SecretStore, SecretVaultRef, StoreAccountRef, Derivation, OpaqueSecret}; + +lazy_static! { + static ref KEY_ITERATIONS: NonZeroU32 = + NonZeroU32::new(crypto::KEY_ITERATIONS as u32).expect("KEY_ITERATIONS > 0; qed"); +} + /// Accounts store. pub struct EthStore { store: EthMultiStore, @@ -37,11 +43,11 @@ pub struct EthStore { impl EthStore { /// Open a new accounts store with given key directory backend. pub fn open(directory: Box) -> Result { - Self::open_with_iterations(directory, KEY_ITERATIONS as u32) + Self::open_with_iterations(directory, *KEY_ITERATIONS) } /// Open a new account store with given key directory backend and custom number of iterations. - pub fn open_with_iterations(directory: Box, iterations: u32) -> Result { + pub fn open_with_iterations(directory: Box, iterations: NonZeroU32) -> Result { Ok(EthStore { store: EthMultiStore::open_with_iterations(directory, iterations)?, }) @@ -257,7 +263,7 @@ impl SecretStore for EthStore { /// Similar to `EthStore` but may store many accounts (with different passwords) for the same `Address` pub struct EthMultiStore { dir: Box, - iterations: u32, + iterations: NonZeroU32, // order lock: cache, then vaults cache: RwLock>>, vaults: Mutex>>, @@ -273,11 +279,11 @@ struct Timestamp { impl EthMultiStore { /// Open new multi-accounts store with given key directory backend. pub fn open(directory: Box) -> Result { - Self::open_with_iterations(directory, KEY_ITERATIONS as u32) + Self::open_with_iterations(directory, *KEY_ITERATIONS) } /// Open new multi-accounts store with given key directory backend and custom number of iterations for new keys. - pub fn open_with_iterations(directory: Box, iterations: u32) -> Result { + pub fn open_with_iterations(directory: Box, iterations: NonZeroU32) -> Result { let store = EthMultiStore { dir: directory, vaults: Mutex::new(HashMap::new()), diff --git a/accounts/ethstore/src/json/kdf.rs b/accounts/ethstore/src/json/kdf.rs index 0ea1d9f31c..a8bb8b261c 100644 --- a/accounts/ethstore/src/json/kdf.rs +++ b/accounts/ethstore/src/json/kdf.rs @@ -15,6 +15,7 @@ // along with Parity Ethereum. If not, see . use std::fmt; +use std::num::NonZeroU32; use serde::{Serialize, Serializer, Deserialize, Deserializer}; use serde::de::{Visitor, Error as SerdeError}; use super::{Error, Bytes}; @@ -108,7 +109,7 @@ impl<'a> Visitor<'a> for PrfVisitor { #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct Pbkdf2 { - pub c: u32, + pub c: NonZeroU32, pub dklen: u32, pub prf: Prf, pub salt: Bytes, diff --git a/accounts/ethstore/src/json/vault_file.rs b/accounts/ethstore/src/json/vault_file.rs index 52e98cd250..0da870931d 100644 --- a/accounts/ethstore/src/json/vault_file.rs +++ b/accounts/ethstore/src/json/vault_file.rs @@ -41,6 +41,11 @@ impl VaultFile { mod test { use serde_json; use json::{VaultFile, Crypto, Cipher, Aes128Ctr, Kdf, Pbkdf2, Prf}; + use std::num::NonZeroU32; + + lazy_static! { + static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(1024).expect("1024 > 0; qed"); + } #[test] fn to_and_from_json() { @@ -51,7 +56,7 @@ mod test { }), ciphertext: "4d6938a1f49b7782".into(), kdf: Kdf::Pbkdf2(Pbkdf2 { - c: 1024, + c: *ITERATIONS, dklen: 32, prf: Prf::HmacSha256, salt: "b6a9338a7ccd39288a86dba73bfecd9101b4f3db9c9830e7c76afdbd4f6872e5".into(), @@ -76,7 +81,7 @@ mod test { }), ciphertext: "4d6938a1f49b7782".into(), kdf: Kdf::Pbkdf2(Pbkdf2 { - c: 1024, + c: *ITERATIONS, dklen: 32, prf: Prf::HmacSha256, salt: "b6a9338a7ccd39288a86dba73bfecd9101b4f3db9c9830e7c76afdbd4f6872e5".into(), diff --git a/accounts/ethstore/src/json/vault_key_file.rs b/accounts/ethstore/src/json/vault_key_file.rs index a29d5fe7f6..dd4ba49798 100644 --- a/accounts/ethstore/src/json/vault_key_file.rs +++ b/accounts/ethstore/src/json/vault_key_file.rs @@ -106,6 +106,11 @@ mod test { use serde_json; use json::{VaultKeyFile, Version, Crypto, Cipher, Aes128Ctr, Kdf, Pbkdf2, Prf, insert_vault_name_to_json_meta, remove_vault_name_from_json_meta}; + use std::num::NonZeroU32; + + lazy_static! { + static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed"); + } #[test] fn to_and_from_json() { @@ -118,7 +123,7 @@ mod test { }), ciphertext: "4befe0a66d9a4b6fec8e39eb5c90ac5dafdeaab005fff1af665fd1f9af925c91".into(), kdf: Kdf::Pbkdf2(Pbkdf2 { - c: 10240, + c: *ITERATIONS, dklen: 32, prf: Prf::HmacSha256, salt: "f17731e84ecac390546692dbd4ccf6a3a2720dc9652984978381e61c28a471b2".into(), @@ -131,7 +136,7 @@ mod test { }), ciphertext: "fef0d113d7576c1702daf380ad6f4c5408389e57991cae2a174facd74bd549338e1014850bddbab7eb486ff5f5c9c5532800c6a6d4db2be2212cd5cd3769244ab230e1f369e8382a9e6d7c0a".into(), kdf: Kdf::Pbkdf2(Pbkdf2 { - c: 10240, + c: *ITERATIONS, dklen: 32, prf: Prf::HmacSha256, salt: "aca82865174a82249a198814b263f43a631f272cbf7ed329d0f0839d259c652a".into(), diff --git a/accounts/ethstore/src/lib.rs b/accounts/ethstore/src/lib.rs index aa2bb86a47..c0955caeb0 100644 --- a/accounts/ethstore/src/lib.rs +++ b/accounts/ethstore/src/lib.rs @@ -36,6 +36,8 @@ extern crate ethereum_types; extern crate ethkey as _ethkey; extern crate parity_wordlist; +#[macro_use] +extern crate lazy_static; #[macro_use] extern crate log; #[macro_use] diff --git a/accounts/ethstore/src/presale.rs b/accounts/ethstore/src/presale.rs index c1be05f0f0..8ca5d0b98b 100644 --- a/accounts/ethstore/src/presale.rs +++ b/accounts/ethstore/src/presale.rs @@ -15,6 +15,7 @@ // along with Parity Ethereum. If not, see . use std::fs; +use std::num::NonZeroU32; use std::path::Path; use json; use ethkey::{Address, Secret, KeyPair, Password}; @@ -58,7 +59,8 @@ impl PresaleWallet { let mut derived_key = [0u8; 32]; let salt = pbkdf2::Salt(password.as_bytes()); let sec = pbkdf2::Secret(password.as_bytes()); - pbkdf2::sha256(2000, salt, sec, &mut derived_key); + let iter = NonZeroU32::new(2000).expect("2000 > 0; qed"); + pbkdf2::sha256(iter, salt, sec, &mut derived_key); let mut key = vec![0; self.ciphertext.len()]; let len = crypto::aes::decrypt_128_cbc(&derived_key[0..16], &self.iv, &self.ciphertext, &mut key) diff --git a/accounts/src/account_data.rs b/accounts/src/account_data.rs new file mode 100644 index 0000000000..a36d38740e --- /dev/null +++ b/accounts/src/account_data.rs @@ -0,0 +1,73 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +//! Account Metadata + +use std::{ + collections::HashMap, + time::Instant, +}; + +use ethkey::{Address, Password}; +use serde_derive::{Serialize, Deserialize}; +use serde_json; + +/// Type of unlock. +#[derive(Clone, PartialEq)] +pub enum Unlock { + /// If account is unlocked temporarily, it should be locked after first usage. + OneTime, + /// Account unlocked permanently can always sign message. + /// Use with caution. + Perm, + /// Account unlocked with a timeout + Timed(Instant), +} + +/// Data associated with account. +#[derive(Clone)] +pub struct AccountData { + pub unlock: Unlock, + pub password: Password, +} + +/// Collected account metadata +#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct AccountMeta { + /// The name of the account. + pub name: String, + /// The rest of the metadata of the account. + pub meta: String, + /// The 128-bit Uuid of the account, if it has one (brain-wallets don't). + pub uuid: Option, +} + +impl AccountMeta { + /// Read a hash map of Address -> AccountMeta + pub fn read(reader: R) -> Result, serde_json::Error> where + R: ::std::io::Read, + { + serde_json::from_reader(reader) + } + + /// Write a hash map of Address -> AccountMeta + pub fn write(m: &HashMap, writer: &mut W) -> Result<(), serde_json::Error> where + W: ::std::io::Write, + { + serde_json::to_writer(writer, m) + } +} + diff --git a/accounts/src/error.rs b/accounts/src/error.rs new file mode 100644 index 0000000000..2aa3564efd --- /dev/null +++ b/accounts/src/error.rs @@ -0,0 +1,56 @@ +// 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::fmt; + +use ethstore::{Error as SSError}; +use hardware_wallet::{Error as HardwareError}; + +/// Signing error +#[derive(Debug)] +pub enum SignError { + /// Account is not unlocked + NotUnlocked, + /// Account does not exist. + NotFound, + /// Low-level hardware device error. + Hardware(HardwareError), + /// Low-level error from store + SStore(SSError), +} + +impl fmt::Display for SignError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + SignError::NotUnlocked => write!(f, "Account is locked"), + SignError::NotFound => write!(f, "Account does not exist"), + SignError::Hardware(ref e) => write!(f, "{}", e), + SignError::SStore(ref e) => write!(f, "{}", e), + } + } +} + +impl From for SignError { + fn from(e: HardwareError) -> Self { + SignError::Hardware(e) + } +} + +impl From for SignError { + fn from(e: SSError) -> Self { + SignError::SStore(e) + } +} diff --git a/ethcore/src/account_provider/mod.rs b/accounts/src/lib.rs similarity index 92% rename from ethcore/src/account_provider/mod.rs rename to accounts/src/lib.rs index 0414c42468..0107eadad0 100644 --- a/ethcore/src/account_provider/mod.rs +++ b/accounts/src/lib.rs @@ -14,94 +14,55 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +#![warn(missing_docs)] + //! Account management. +mod account_data; +mod error; mod stores; +#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))] +extern crate fake_hardware_wallet as hardware_wallet; + +use self::account_data::{Unlock, AccountData}; use self::stores::AddressBook; use std::collections::HashMap; -use std::fmt; use std::time::{Instant, Duration}; +use common_types::transaction::{Action, Transaction}; +use ethkey::{Address, Message, Public, Secret, Password, Random, Generator}; use ethstore::accounts_dir::MemoryDirectory; -use ethstore::ethkey::{Address, Message, Public, Secret, Password, Random, Generator}; -use ethjson::misc::AccountMeta; use ethstore::{ - SimpleSecretStore, SecretStore, Error as SSError, EthStore, EthMultiStore, + SimpleSecretStore, SecretStore, EthStore, EthMultiStore, random_string, SecretVaultRef, StoreAccountRef, OpaqueSecret, }; +use log::{warn, debug}; use parking_lot::RwLock; -use types::transaction::{Action, Transaction}; -pub use ethstore::ethkey::Signature; -pub use ethstore::{Derivation, IndexDerivation, KeyFile}; +pub use ethkey::Signature; +pub use ethstore::{Derivation, IndexDerivation, KeyFile, Error}; pub use hardware_wallet::{Error as HardwareError, HardwareWalletManager, KeyPath, TransactionInfo}; -/// Type of unlock. -#[derive(Clone, PartialEq)] -enum Unlock { - /// If account is unlocked temporarily, it should be locked after first usage. - OneTime, - /// Account unlocked permanently can always sign message. - /// Use with caution. - Perm, - /// Account unlocked with a timeout - Timed(Instant), -} - -/// Data associated with account. -#[derive(Clone)] -struct AccountData { - unlock: Unlock, - password: Password, -} - -/// Signing error -#[derive(Debug)] -pub enum SignError { - /// Account is not unlocked - NotUnlocked, - /// Account does not exist. - NotFound, - /// Low-level hardware device error. - Hardware(HardwareError), - /// Low-level error from store - SStore(SSError), -} +pub use self::account_data::AccountMeta; +pub use self::error::SignError; -impl fmt::Display for SignError { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - SignError::NotUnlocked => write!(f, "Account is locked"), - SignError::NotFound => write!(f, "Account does not exist"), - SignError::Hardware(ref e) => write!(f, "{}", e), - SignError::SStore(ref e) => write!(f, "{}", e), - } - } -} - -impl From for SignError { - fn from(e: HardwareError) -> Self { - SignError::Hardware(e) - } -} - -impl From for SignError { - fn from(e: SSError) -> Self { - SignError::SStore(e) - } -} - -/// `AccountProvider` errors. -pub type Error = SSError; +type AccountToken = Password; -fn transient_sstore() -> EthMultiStore { - EthMultiStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed") +/// Account management settings. +#[derive(Debug, Default)] +pub struct AccountProviderSettings { + /// Enable hardware wallet support. + pub enable_hardware_wallets: bool, + /// Use the classic chain key on the hardware wallet. + pub hardware_wallet_classic_key: bool, + /// Store raw account secret when unlocking the account permanently. + pub unlock_keep_secret: bool, + /// Disallowed accounts. + pub blacklisted_accounts: Vec
, } -type AccountToken = Password; - /// Account management. /// Responsible for unlocking accounts. pub struct AccountProvider { @@ -124,27 +85,8 @@ pub struct AccountProvider { blacklisted_accounts: Vec
, } -/// Account management settings. -pub struct AccountProviderSettings { - /// Enable hardware wallet support. - pub enable_hardware_wallets: bool, - /// Use the classic chain key on the hardware wallet. - pub hardware_wallet_classic_key: bool, - /// Store raw account secret when unlocking the account permanently. - pub unlock_keep_secret: bool, - /// Disallowed accounts. - pub blacklisted_accounts: Vec
, -} - -impl Default for AccountProviderSettings { - fn default() -> Self { - AccountProviderSettings { - enable_hardware_wallets: false, - hardware_wallet_classic_key: false, - unlock_keep_secret: false, - blacklisted_accounts: vec![], - } - } +fn transient_sstore() -> EthMultiStore { + EthMultiStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed") } impl AccountProvider { @@ -221,7 +163,7 @@ impl AccountProvider { let account = self.sstore.insert_account(SecretVaultRef::Root, secret, password)?; if self.blacklisted_accounts.contains(&account.address) { self.sstore.remove_account(&account, password)?; - return Err(SSError::InvalidAccount.into()); + return Err(Error::InvalidAccount.into()); } Ok(account.address) } @@ -251,7 +193,7 @@ impl AccountProvider { let account = self.sstore.import_wallet(SecretVaultRef::Root, json, password, gen_id)?; if self.blacklisted_accounts.contains(&account.address) { self.sstore.remove_account(&account, password)?; - return Err(SSError::InvalidAccount.into()); + return Err(Error::InvalidAccount.into()); } Ok(Address::from(account.address).into()) } @@ -284,7 +226,7 @@ impl AccountProvider { return Ok(accounts.into_iter().map(|a| a.address).collect()); } } - Err(SSError::Custom("No hardware wallet accounts were found".into())) + Err(Error::Custom("No hardware wallet accounts were found".into())) } /// Get a list of paths to locked hardware wallets @@ -669,7 +611,7 @@ impl AccountProvider { mod tests { use super::{AccountProvider, Unlock}; use std::time::{Duration, Instant}; - use ethstore::ethkey::{Generator, Random, Address}; + use ethkey::{Generator, Random, Address}; use ethstore::{StoreAccountRef, Derivation}; use ethereum_types::H256; diff --git a/ethcore/src/account_provider/stores.rs b/accounts/src/stores.rs similarity index 89% rename from ethcore/src/account_provider/stores.rs rename to accounts/src/stores.rs index 10d7ffde88..baa26cc48b 100644 --- a/ethcore/src/account_provider/stores.rs +++ b/accounts/src/stores.rs @@ -20,8 +20,10 @@ use std::{fs, fmt, hash, ops}; use std::collections::HashMap; use std::path::{Path, PathBuf}; -use ethstore::ethkey::Address; -use ethjson::misc::AccountMeta; +use ethkey::Address; +use log::{trace, warn}; + +use crate::AccountMeta; /// Disk-backed map from Address to String. Uses JSON. pub struct AddressBook { @@ -153,8 +155,8 @@ impl DiskMap { mod tests { use super::AddressBook; use std::collections::HashMap; - use ethjson::misc::AccountMeta; use tempdir::TempDir; + use crate::account_data::AccountMeta; #[test] fn should_save_and_reload_address_book() { @@ -163,7 +165,9 @@ mod tests { b.set_name(1.into(), "One".to_owned()); b.set_meta(1.into(), "{1:1}".to_owned()); let b = AddressBook::new(tempdir.path()); - assert_eq!(b.get(), hash_map![1.into() => AccountMeta{name: "One".to_owned(), meta: "{1:1}".to_owned(), uuid: None}]); + assert_eq!(b.get(), vec![ + (1, AccountMeta {name: "One".to_owned(), meta: "{1:1}".to_owned(), uuid: None}) + ].into_iter().map(|(a, b)| (a.into(), b)).collect::>()); } #[test] @@ -177,9 +181,9 @@ mod tests { b.remove(2.into()); let b = AddressBook::new(tempdir.path()); - assert_eq!(b.get(), hash_map![ - 1.into() => AccountMeta{name: "One".to_owned(), meta: "{}".to_owned(), uuid: None}, - 3.into() => AccountMeta{name: "Three".to_owned(), meta: "{}".to_owned(), uuid: None} - ]); + assert_eq!(b.get(), vec![ + (1, AccountMeta{name: "One".to_owned(), meta: "{}".to_owned(), uuid: None}), + (3, AccountMeta{name: "Three".to_owned(), meta: "{}".to_owned(), uuid: None}), + ].into_iter().map(|(a, b)| (a.into(), b)).collect::>()); } } diff --git a/chainspec/Cargo.toml b/chainspec/Cargo.toml index 8739ca7dcb..c0308edd32 100644 --- a/chainspec/Cargo.toml +++ b/chainspec/Cargo.toml @@ -1,4 +1,5 @@ [package] +description = "Parity Ethereum Chain Specification" name = "chainspec" version = "0.1.0" authors = ["Marek Kotewicz "] diff --git a/cli-signer/Cargo.toml b/cli-signer/Cargo.toml index f4fa86d945..aa56da6f85 100644 --- a/cli-signer/Cargo.toml +++ b/cli-signer/Cargo.toml @@ -1,12 +1,13 @@ [package] -authors = ["Parity "] -description = "Parity Cli Tool" +description = "Parity Ethereum CLI Signer Tool" homepage = "http://parity.io" license = "GPL-3.0" name = "cli-signer" version = "1.4.0" +authors = ["Parity "] [dependencies] +ethereum-types = "0.4" futures = "0.1" rpassword = "1.0" parity-rpc = { path = "../rpc" } diff --git a/cli-signer/rpc-client/Cargo.toml b/cli-signer/rpc-client/Cargo.toml index 0ffdae770a..50565c0b34 100644 --- a/cli-signer/rpc-client/Cargo.toml +++ b/cli-signer/rpc-client/Cargo.toml @@ -1,12 +1,13 @@ [package] -authors = ["Parity "] -description = "Parity Rpc Client" +description = "Parity Ethereum RPC Client" homepage = "http://parity.io" license = "GPL-3.0" name = "parity-rpc-client" version = "1.4.0" +authors = ["Parity "] [dependencies] +ethereum-types = "0.4" futures = "0.1" log = "0.4" serde = "1.0" @@ -14,7 +15,7 @@ serde_json = "1.0" url = "1.2.0" matches = "0.1" parking_lot = "0.7" -jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } -jsonrpc-ws-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } +jsonrpc-core = "10.0.1" +jsonrpc-ws-server = "10.0.1" parity-rpc = { path = "../../rpc" } keccak-hash = "0.1" diff --git a/cli-signer/rpc-client/src/lib.rs b/cli-signer/rpc-client/src/lib.rs index df7936eaee..d0e087e59d 100644 --- a/cli-signer/rpc-client/src/lib.rs +++ b/cli-signer/rpc-client/src/lib.rs @@ -17,6 +17,7 @@ pub mod client; pub mod signer_client; +extern crate ethereum_types; extern crate futures; extern crate jsonrpc_core; extern crate jsonrpc_ws_server as ws; diff --git a/cli-signer/rpc-client/src/signer_client.rs b/cli-signer/rpc-client/src/signer_client.rs index 339f43b6e3..997841936d 100644 --- a/cli-signer/rpc-client/src/signer_client.rs +++ b/cli-signer/rpc-client/src/signer_client.rs @@ -15,7 +15,8 @@ // along with Parity Ethereum. If not, see . use client::{Rpc, RpcError}; -use rpc::signer::{ConfirmationRequest, TransactionModification, U256, TransactionCondition}; +use ethereum_types::U256; +use rpc::signer::{ConfirmationRequest, TransactionModification, TransactionCondition}; use serde; use serde_json::{Value as JsonValue, to_value}; use std::path::PathBuf; diff --git a/cli-signer/src/lib.rs b/cli-signer/src/lib.rs index f09d4403aa..3ef6e70549 100644 --- a/cli-signer/src/lib.rs +++ b/cli-signer/src/lib.rs @@ -14,13 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +extern crate ethereum_types; extern crate futures; extern crate rpassword; extern crate parity_rpc as rpc; extern crate parity_rpc_client as client; -use rpc::signer::{U256, ConfirmationRequest}; +use ethereum_types::U256; +use rpc::signer::ConfirmationRequest; use client::signer_client::SignerRpc; use std::io::{Write, BufRead, BufReader, stdout, stdin}; use std::path::PathBuf; diff --git a/docs/CHANGELOG-2.0.md b/docs/CHANGELOG-2.0.md index e0e6b0c380..ef57dc2fbb 100644 --- a/docs/CHANGELOG-2.0.md +++ b/docs/CHANGELOG-2.0.md @@ -1,4 +1,4 @@ -Note: Parity 2.0 reached End-of-Life on 2018-11-15 (EOL). +Note: Parity Ethereum 2.0 reached End-of-Life on 2018-11-15 (EOL). ## Parity-Ethereum [v2.0.9](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.9) (2018-10-29) diff --git a/docs/CHANGELOG-2.1.md b/docs/CHANGELOG-2.1.md index 3f3b229809..212370a270 100644 --- a/docs/CHANGELOG-2.1.md +++ b/docs/CHANGELOG-2.1.md @@ -1,13 +1,31 @@ +Note: Parity Ethereum 2.1 reached End-of-Life on 2019-01-16 (EOL). + +## Parity-Ethereum [v2.1.11](https://github.com/paritytech/parity-ethereum/releases/tag/v2.1.11) (2019-01-09) + +Parity-Ethereum 2.1.11-stable is a bugfix release that improves performance and stability. + +The full list of included changes: + +- Stable backports v2.1.11 ([#10112](https://github.com/paritytech/parity-ethereum/pull/10112)) + - Version: bump stable to v2.1.11 + - HF in POA Sokol (2019-01-04) ([#10077](https://github.com/paritytech/parity-ethereum/pull/10077)) + - Add --locked when running cargo ([#10107](https://github.com/paritytech/parity-ethereum/pull/10107)) + - Ethcore: update hardcoded headers ([#10123](https://github.com/paritytech/parity-ethereum/pull/10123)) + - Identity fix ([#10128](https://github.com/paritytech/parity-ethereum/pull/10128)) + - Update pwasm-utils to 0.6.1 ([#10134](https://github.com/paritytech/parity-ethereum/pull/10134)) + - Version: mark upgrade critical on kovan + ## Parity-Ethereum [v2.1.10](https://github.com/paritytech/parity-ethereum/releases/tag/v2.1.10) (2018-12-14) -Parity-Ethereum 2.1.10-stable is an important release that introduces Constantinople fork at block 7080000 on Mainnet. -This release also contains a fix for chains using AuRa + EmptySteps. Read carefully if this applies to you. + +Parity-Ethereum 2.1.10-stable is an important release that introduces Constantinople fork at block 7080000 on Mainnet. +This release also contains a fix for chains using AuRa + EmptySteps. Read carefully if this applies to you. If you have a chain with`empty_steps` already running, some blocks most likely contain non-strict entries (unordered or duplicated empty steps). In this release`strict_empty_steps_transition` **is enabled by default at block 0** for any chain with `empty_steps`. If your network uses `empty_steps` you **must**: - plan a hard fork and change `strict_empty_steps_transition` to the desire fork block - update the clients of the whole network to 2.2.5-beta / 2.1.10-stable. If for some reason you don't want to do this please set`strict_empty_steps_transition` to `0xfffffffff` to disable it. -The full list of included changes: +The full list of included changes: - Backports for stable 2.1.10 ([#10046](https://github.com/paritytech/parity-ethereum/pull/10046)) - Bump stable to 2.1.10 ([#10046](https://github.com/paritytech/parity-ethereum/pull/10046)) diff --git a/docs/CHANGELOG-2.2.md b/docs/CHANGELOG-2.2.md new file mode 100644 index 0000000000..69d6a0dcb7 --- /dev/null +++ b/docs/CHANGELOG-2.2.md @@ -0,0 +1,392 @@ +Note: Parity Ethereum 2.2 reached End-of-Life on 2019-02-25 (EOL). + +## Parity-Ethereum [v2.2.11](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.11) (2019-02-21) + +Parity-Ethereum 2.2.11-stable is a maintenance release that fixes snap and docker installations. + +The full list of included changes: + +- Stable: snap: release untagged versions from branches to the candidate ([#10357](https://github.com/paritytech/parity-ethereum/pull/10357)) ([#10372](https://github.com/paritytech/parity-ethereum/pull/10372)) + - Snap: release untagged versions from branches to the candidate snap channel ([#10357](https://github.com/paritytech/parity-ethereum/pull/10357)) + - Snap: add the removable-media plug ([#10377](https://github.com/paritytech/parity-ethereum/pull/10377)) + - Exchanged old(azure) bootnodes with new(ovh) ones ([#10309](https://github.com/paritytech/parity-ethereum/pull/10309)) +- Stable Backports ([#10353](https://github.com/paritytech/parity-ethereum/pull/10353)) + - Version: bump stable to 2.2.11 + - Snap: prefix version and populate candidate channel ([#10343](https://github.com/paritytech/parity-ethereum/pull/10343)) + - Snap: populate candidate releases with beta snaps to avoid stale channel + - Snap: prefix version with v* + - No volumes are needed, just run -v volume:/path/in/the/container ([#10345](https://github.com/paritytech/parity-ethereum/pull/10345)) + +## Parity-Ethereum [v2.2.10](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.10) (2019-02-13) + +Parity-Ethereum 2.2.10-stable is a security-relevant release. A bug in the JSONRPC-deserialization module can cause crashes of all versions of Parity Ethereum nodes if an attacker is able to submit a specially-crafted RPC to certain publicly available endpoints. + +- https://www.parity.io/new-parity-ethereum-update-fixes-several-rpc-vulnerabilities/ + +The full list of included changes: + +- Additional error for invalid gas ([#10327](https://github.com/paritytech/parity-ethereum/pull/10327)) ([#10329](https://github.com/paritytech/parity-ethereum/pull/10329)) +- Backports for Stable 2.2.10 ([#10332](https://github.com/paritytech/parity-ethereum/pull/10332)) + - fix(docker-aarch64) : cross-compile config ([#9798](https://github.com/paritytech/parity-ethereum/pull/9798)) + - import rpc transactions sequentially ([#10051](https://github.com/paritytech/parity-ethereum/pull/10051)) + - fix(docker): fix not receives SIGINT ([#10059](https://github.com/paritytech/parity-ethereum/pull/10059)) + - snap: official image / test ([#10168](https://github.com/paritytech/parity-ethereum/pull/10168)) + - perform stripping during build ([#10208](https://github.com/paritytech/parity-ethereum/pull/10208)) + - Additional tests for uint/hash/bytes deserialization. ([#10279](https://github.com/paritytech/parity-ethereum/pull/10279)) + - Don't run the CPP example on CI ([#10285](https://github.com/paritytech/parity-ethereum/pull/10285)) + - CI optimizations ([#10297](https://github.com/paritytech/parity-ethereum/pull/10297)) + - fix publish job ([#10317](https://github.com/paritytech/parity-ethereum/pull/10317)) + - Add Statetest support for Constantinople Fix ([#10323](https://github.com/paritytech/parity-ethereum/pull/10323)) + - Add helper for Timestamp overflows ([#10330](https://github.com/paritytech/parity-ethereum/pull/10330)) + - Don't add discovery initiators to the node table ([#10305](https://github.com/paritytech/parity-ethereum/pull/10305)) + - change docker image based on debian instead of ubuntu due to the chan ([#10336](https://github.com/paritytech/parity-ethereum/pull/10336)) + - role back docker build image and docker deploy image to ubuntu:xenial based ([#10338](https://github.com/paritytech/parity-ethereum/pull/10338)) + +## Parity-Ethereum [v2.2.9](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.9) (2019-02-03) + +Parity-Ethereum 2.2.9-stable is a security-relevant release. A bug in the JSONRPC-deserialization module can cause crashes of all versions of Parity Ethereum nodes if an attacker is able to submit a specially-crafted RPC to certain publicly available endpoints. + +- https://www.parity.io/security-alert-parity-ethereum-03-02/ + +The full list of included changes: + +- Additional tests for uint deserialization. ([#10279](https://github.com/paritytech/parity-ethereum/pull/10279)) ([#10281](https://github.com/paritytech/parity-ethereum/pull/10281)) +- Version: bump stable to 2.2.9 ([#10282](https://github.com/paritytech/parity-ethereum/pull/10282)) + +## Parity-Ethereum [v2.2.8](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.8) (2019-02-01) + +Parity-Ethereum 2.2.8-stable is a consensus-relevant release that enables _St. Petersfork_ on: + +- Ethereum Block `7280000` (along with Constantinople) +- Kovan Block `10255201` +- Ropsten Block `4939394` +- POA Sokol Block `7026400` + +In addition to this, Constantinople is cancelled for the POA Core network. Upgrading is mandatory for clients on any of these chains. + +The full list of included changes: + +- Backports for stable 2.2.8 ([#10224](https://github.com/paritytech/parity-ethereum/pull/10224)) + - Update for Android cross-compilation. ([#10180](https://github.com/paritytech/parity-ethereum/pull/10180)) + - Cancel Constantinople HF on POA Core ([#10198](https://github.com/paritytech/parity-ethereum/pull/10198)) + - Add EIP-1283 disable transition ([#10214](https://github.com/paritytech/parity-ethereum/pull/10214)) + - Enable St-Peters-Fork ("Constantinople Fix") ([#10223](https://github.com/paritytech/parity-ethereum/pull/10223)) +- Stable: Macos heapsize force jemalloc ([#10234](https://github.com/paritytech/parity-ethereum/pull/10234)) ([#10258](https://github.com/paritytech/parity-ethereum/pull/10258)) + +## Parity-Ethereum [v2.2.7](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.7) (2019-01-15) + +Parity-Ethereum 2.2.7-stable is a consensus-relevant security release that reverts Constantinople on the Ethereum network. Upgrading is mandatory for Ethereum, and strongly recommended for other networks. + +- **Consensus** - Ethereum Network: Pull Constantinople protocol upgrade on Ethereum ([#10189](https://github.com/paritytech/parity-ethereum/pull/10189)) + - Read more: [Security Alert: Ethereum Constantinople Postponement](https://blog.ethereum.org/2019/01/15/security-alert-ethereum-constantinople-postponement/) +- **Networking** - All networks: Ping nodes from discovery ([#10167](https://github.com/paritytech/parity-ethereum/pull/10167)) +- **Wasm** - Kovan Network: Update pwasm-utils to 0.6.1 ([#10134](https://github.com/paritytech/parity-ethereum/pull/10134)) + +_Note:_ This release marks Parity 2.2 as _stable_. All versions of Parity 2.1 now reached _end of life_. + +The full list of included changes: + +- Backports for stable 2.2.7 ([#10163](https://github.com/paritytech/parity-ethereum/pull/10163)) + - Version: bump stable to 2.2.7 + - Version: mark 2.2 track stable + - Version: mark update critical on all networks + - Handle the case for contract creation on an empty but exist account with storage items ([#10065](https://github.com/paritytech/parity-ethereum/pull/10065)) + - Fix _cannot recursively call into `Core`_ issue ([#10144](https://github.com/paritytech/parity-ethereum/pull/10144)) + - Snap: fix path in script ([#10157](https://github.com/paritytech/parity-ethereum/pull/10157)) + - Ping nodes from discovery ([#10167](https://github.com/paritytech/parity-ethereum/pull/10167)) + - Version: bump fork blocks for kovan and foundation, mark releases non critical + - Pull constantinople on ethereum network ([#10189](https://github.com/paritytech/parity-ethereum/pull/10189)) + +## Parity-Ethereum [v2.2.6](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.6) (2019-01-10) + +Parity-Ethereum 2.2.6-beta is a bugfix release that improves performance and stability. + +The full list of included changes: + +- Beta backports v2.2.6 ([#10113](https://github.com/paritytech/parity-ethereum/pull/10113)) + - Version: bump beta to v2.2.6 + - Fill transaction hash on ethGetLog of light client. ([#9938](https://github.com/paritytech/parity-ethereum/pull/9938)) + - Fix pubsub new_blocks notifications to include all blocks ([#9987](https://github.com/paritytech/parity-ethereum/pull/9987)) + - Finality: dont require chain head to be in the chain ([#10054](https://github.com/paritytech/parity-ethereum/pull/10054)) + - Handle the case for contract creation on an empty but exist account with storage items ([#10065](https://github.com/paritytech/parity-ethereum/pull/10065)) + - Autogen docs for the "Configuring Parity Ethereum" wiki page. ([#10067](https://github.com/paritytech/parity-ethereum/pull/10067)) + - HF in POA Sokol (2019-01-04) ([#10077](https://github.com/paritytech/parity-ethereum/pull/10077)) + - Add --locked when running cargo ([#10107](https://github.com/paritytech/parity-ethereum/pull/10107)) + - Ethcore: update hardcoded headers ([#10123](https://github.com/paritytech/parity-ethereum/pull/10123)) + - Identity fix ([#10128](https://github.com/paritytech/parity-ethereum/pull/10128)) + - Update pwasm-utils to 0.6.1 ([#10134](https://github.com/paritytech/parity-ethereum/pull/10134)) + - Make sure parent block is not in importing queue when importing ancient blocks ([#10138](https://github.com/paritytech/parity-ethereum/pull/10138)) + - CI: re-enable snap publishing ([#10142](https://github.com/paritytech/parity-ethereum/pull/10142)) + - HF in POA Core (2019-01-18) - Constantinople ([#10155](https://github.com/paritytech/parity-ethereum/pull/10155)) + - Version: mark upgrade critical on kovan + +## Parity-Ethereum [v2.2.5](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.5) (2018-12-14) + +Parity-Ethereum 2.2.5-beta is an important release that introduces Constantinople fork at block 7080000 on Mainnet. +This release also contains a fix for chains using AuRa + EmptySteps. Read carefully if this applies to you. +If you have a chain with`empty_steps` already running, some blocks most likely contain non-strict entries (unordered or duplicated empty steps). In this release`strict_empty_steps_transition` **is enabled by default at block 0** for any chain with `empty_steps`. +If your network uses `empty_steps` you **must**: +- plan a hard fork and change `strict_empty_steps_transition` to the desire fork block +- update the clients of the whole network to 2.2.5-beta / 2.1.10-stable. +If for some reason you don't want to do this please set`strict_empty_steps_transition` to `0xfffffffff` to disable it. + +The full list of included changes: +- Backports for beta 2.2.5 ([#10047](https://github.com/paritytech/parity-ethereum/pull/10047)) + - Bump beta to 2.2.5 ([#10047](https://github.com/paritytech/parity-ethereum/pull/10047)) + - Fix empty steps ([#9939](https://github.com/paritytech/parity-ethereum/pull/9939)) + - Prevent sending empty step message twice + - Prevent sending empty step and then block in the same step + - Don't accept double empty steps + - Do basic validation of self-sealed blocks + - Strict empty steps validation ([#10041](https://github.com/paritytech/parity-ethereum/pull/10041)) + - Enables strict verification of empty steps - there can be no duplicates and empty steps should be ordered inside the seal. + - Note that authorities won't produce invalid seals after [#9939](https://github.com/paritytech/parity-ethereum/pull/9939), this PR just adds verification to the seal to prevent forging incorrect blocks and potentially causing consensus issues. + - This features is enabled by default so any AuRa + EmptySteps chain should set strict_empty_steps_transition fork block number in their spec and upgrade to v2.2.5-beta or v2.1.10-stable. + - ethcore: enable constantinople on ethereum ([#10031](https://github.com/paritytech/parity-ethereum/pull/10031)) + - ethcore: change blockreward to 2e18 for foundation after constantinople + - ethcore: delay diff bomb by 2e6 blocks for foundation after constantinople + - ethcore: enable eip-{145,1014,1052,1283} for foundation after constantinople + - Change test miner max memory to malloc reports. ([#10024](https://github.com/paritytech/parity-ethereum/pull/10024)) + - Fix: test corpus_inaccessible panic ([#10019](https://github.com/paritytech/parity-ethereum/pull/10019)) + +## Parity-Ethereum [v2.2.2](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.2) (2018-11-29) + +Parity-Ethereum 2.2.2-beta is an exciting release. Among others, it improves sync performance, peering stability, block propagation, and transaction propagation times. Also, a warp-sync no longer removes existing blocks from the database, but rather reuses locally available information to decrease sync times and reduces required bandwidth. + +Before upgrading to 2.2.2, please also verify the validity of your chain specs. Parity Ethereum now denies unknown fields in the specification. To do this, use the chainspec tool: + +``` +cargo build --release -p chainspec +./target/release/chainspec /path/to/spec.json +``` + +Last but not least, JSONRPC APIs which are not yet accepted as an EIP in the `eth`, `personal`, or `web3` namespace, are now considere experimental as their final specification might change in future. These APIs have to be manually enabled by explicitly running `--jsonrpc-experimental`. + +The full list of included changes: + +- Backports For beta 2.2.2 ([#9976](https://github.com/paritytech/parity-ethereum/pull/9976)) + - Version: bump beta to 2.2.2 + - Add experimental RPCs flag ([#9928](https://github.com/paritytech/parity-ethereum/pull/9928)) + - Keep existing blocks when restoring a Snapshot ([#8643](https://github.com/paritytech/parity-ethereum/pull/8643)) + - Rename db_restore => client + - First step: make it compile! + - Second step: working implementation! + - Refactoring + - Fix tests + - Migrate ancient blocks interacting backward + - Early return in block migration if snapshot is aborted + - Remove RwLock getter (PR Grumble I) + - Remove dependency on `Client`: only used Traits + - Add test for recovering aborted snapshot recovery + - Add test for migrating old blocks + - Release RwLock earlier + - Revert Cargo.lock + - Update _update ancient block_ logic: set local in `commit` + - Update typo in ethcore/src/snapshot/service.rs + - Adjust requests costs for light client ([#9925](https://github.com/paritytech/parity-ethereum/pull/9925)) + - Pip Table Cost relative to average peers instead of max peers + - Add tracing in PIP new_cost_table + - Update stat peer_count + - Use number of leeching peers for Light serve costs + - Fix test::light_params_load_share_depends_on_max_peers (wrong type) + - Remove (now) useless test + - Remove `load_share` from LightParams.Config + - Add LEECHER_COUNT_FACTOR + - Pr Grumble: u64 to u32 for f64 casting + - Prevent u32 overflow for avg_peer_count + - Add tests for LightSync::Statistics + - Fix empty steps ([#9939](https://github.com/paritytech/parity-ethereum/pull/9939)) + - Don't send empty step twice or empty step then block. + - Perform basic validation of locally sealed blocks. + - Don't include empty step twice. + - Prevent silent errors in daemon mode, closes [#9367](https://github.com/paritytech/parity-ethereum/issues/9367) ([#9946](https://github.com/paritytech/parity-ethereum/pull/9946)) + - Fix a deadlock ([#9952](https://github.com/paritytech/parity-ethereum/pull/9952)) + - Update informant: + - Decimal in Mgas/s + - Print every 5s (not randomly between 5s and 10s) + - Fix dead-lock in `blockchain.rs` + - Update locks ordering + - Fix light client informant while syncing ([#9932](https://github.com/paritytech/parity-ethereum/pull/9932)) + - Add `is_idle` to LightSync to check importing status + - Use SyncStateWrapper to make sure is_idle gets updates + - Update is_major_import to use verified queue size as well + - Add comment for `is_idle` + - Add Debug to `SyncStateWrapper` + - `fn get` -> `fn into_inner` + - Ci: rearrange pipeline by logic ([#9970](https://github.com/paritytech/parity-ethereum/pull/9970)) + - Ci: rearrange pipeline by logic + - Ci: rename docs script + - Fix docker build ([#9971](https://github.com/paritytech/parity-ethereum/pull/9971)) + - Deny unknown fields for chainspec ([#9972](https://github.com/paritytech/parity-ethereum/pull/9972)) + - Add deny_unknown_fields to chainspec + - Add tests and fix existing one + - Remove serde_ignored dependency for chainspec + - Fix rpc test eth chain spec + - Fix starting_nonce_test spec + - Improve block and transaction propagation ([#9954](https://github.com/paritytech/parity-ethereum/pull/9954)) + - Refactor sync to add priority tasks. + - Send priority tasks notifications. + - Propagate blocks, optimize transactions. + - Implement transaction propagation. Use sync_channel. + - Tone down info. + - Prevent deadlock by not waiting forever for sync lock. + - Fix lock order. + - Don't use sync_channel to prevent deadlocks. + - Fix tests. + - Fix unstable peers and slowness in sync ([#9967](https://github.com/paritytech/parity-ethereum/pull/9967)) + - Don't sync all peers after each response + - Update formating + - Fix tests: add `continue_sync` to `Sync_step` + - Update ethcore/sync/src/chain/mod.rs + - Fix rpc middlewares + - Fix Cargo.lock + - Json: resolve merge in spec + - Rpc: fix starting_nonce_test + - Ci: allow nightl job to fail + +## Parity-Ethereum [v2.2.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.1) (2018-11-15) + +Parity-Ethereum 2.2.1-beta is the first v2.2 release, and might introduce features that break previous work flows, among others: + +- Prevent zero network ID ([#9763](https://github.com/paritytech/parity-ethereum/pull/9763)) and drop support for Olympic testnet ([#9801](https://github.com/paritytech/parity-ethereum/pull/9801)): The Olympic test net is dead for years and never used a chain ID but network ID zero. Parity Ethereum is now preventing the network ID to be zero, thus Olympic support is dropped. Make sure to chose positive non-zero network IDs in future. +- Multithreaded snapshot creation ([#9239](https://github.com/paritytech/parity-ethereum/pull/9239)): adds a CLI argument `--snapshot-threads` which specifies the number of threads. This helps improving the performance of full nodes that wish to provide warp-snapshots for the network. The gain in performance comes with a slight drawback in increased snapshot size. +- Expose config max-round-blocks-to-import ([#9439](https://github.com/paritytech/parity-ethereum/pull/9439)): Parity Ethereum imports blocks in rounds. If at the end of any round, the queue is not empty, we consider it to be _importing_ and won't notify pubsub. On large re-orgs (10+ blocks), this is possible. The default `max_round_blocks_to_import` is increased to 12 and configurable via the `--max-round-blocks-to-import` CLI flag. With unstable network conditions, it is advised to increase the number. This shouldn't have any noticeable performance impact unless the number is set to really large. +- Increase Gas-floor-target and Gas Cap ([#9564](https://github.com/paritytech/parity-ethereum/pull/9564)): the default values for gas floor target are `8_000_000` and gas cap `10_000_000`, similar to Geth 1.8.15+. +- Produce portable binaries ([#9725](https://github.com/paritytech/parity-ethereum/pull/9725)): we now produce portable binaries, but it may incur some performance degradation. For ultimate performance it's now better to compile Parity Ethereum from source with `PORTABLE=OFF` environment variable. +- RPC: `parity_allTransactionHashes` ([#9745](https://github.com/paritytech/parity-ethereum/pull/9745)): Get all pending transactions from the queue with the high performant `parity_allTransactionHashes` RPC method. +- Support `eth_chainId` RPC method ([#9783](https://github.com/paritytech/parity-ethereum/pull/9783)): implements EIP-695 to get the chainID via RPC. +- AuRa: finalize blocks ([#9692](https://github.com/paritytech/parity-ethereum/pull/9692)): The AuRa engine was updated to emit ancestry actions to finalize blocks. The full client stores block finality in the database, the engine builds finality from an ancestry of `ExtendedHeader`; `is_epoch_end` was updated to take a vec of recently finalized headers; `is_epoch_end_light` was added which maintains the previous interface and is used by the light client since the client itself doesn't track finality. + +The full list of included changes: + +- Backport to parity 2.2.1 beta ([#9905](https://github.com/paritytech/parity-ethereum/pull/9905)) + - Bump version to 2.2.1 + - Fix: Intermittent failing CI due to addr in use ([#9885](https://github.com/paritytech/parity-ethereum/pull/9885)) + - Fix Parity not closing on Ctrl-C ([#9886](https://github.com/paritytech/parity-ethereum/pull/9886)) + - Fix json tracer overflow ([#9873](https://github.com/paritytech/parity-ethereum/pull/9873)) + - Fix docker script ([#9854](https://github.com/paritytech/parity-ethereum/pull/9854)) + - Add hardcoded headers for light client ([#9907](https://github.com/paritytech/parity-ethereum/pull/9907)) + - Gitlab-ci: make android release build succeed ([#9743](https://github.com/paritytech/parity-ethereum/pull/9743)) + - Allow to seal work on latest block ([#9876](https://github.com/paritytech/parity-ethereum/pull/9876)) + - Remove rust-toolchain file ([#9906](https://github.com/paritytech/parity-ethereum/pull/9906)) + - Light-fetch: Differentiate between out-of-gas/manual throw and use required gas from response on failure ([#9824](https://github.com/paritytech/parity-ethereum/pull/9824)) + - Eip-712 implementation ([#9631](https://github.com/paritytech/parity-ethereum/pull/9631)) + - Eip-191 implementation ([#9701](https://github.com/paritytech/parity-ethereum/pull/9701)) + - Simplify cargo audit ([#9918](https://github.com/paritytech/parity-ethereum/pull/9918)) + - Fix performance issue importing Kovan blocks ([#9914](https://github.com/paritytech/parity-ethereum/pull/9914)) + - Ci: nuke the gitlab caches ([#9855](https://github.com/paritytech/parity-ethereum/pull/9855)) +- Backports to parity beta 2.2.0 ([#9820](https://github.com/paritytech/parity-ethereum/pull/9820)) + - Ci: remove failing tests for android, windows, and macos ([#9788](https://github.com/paritytech/parity-ethereum/pull/9788)) + - Implement NoProof for json tests and update tests reference ([#9814](https://github.com/paritytech/parity-ethereum/pull/9814)) + - Move state root verification before gas used ([#9841](https://github.com/paritytech/parity-ethereum/pull/9841)) + - Classic.json Bootnode Update ([#9828](https://github.com/paritytech/parity-ethereum/pull/9828)) +- Rpc: parity_allTransactionHashes ([#9745](https://github.com/paritytech/parity-ethereum/pull/9745)) +- Revert "prevent zero networkID ([#9763](https://github.com/paritytech/parity-ethereum/pull/9763))" ([#9815](https://github.com/paritytech/parity-ethereum/pull/9815)) +- Allow zero chain id in EIP155 signing process ([#9792](https://github.com/paritytech/parity-ethereum/pull/9792)) +- Add readiness check for docker container ([#9804](https://github.com/paritytech/parity-ethereum/pull/9804)) +- Insert dev account before unlocking ([#9813](https://github.com/paritytech/parity-ethereum/pull/9813)) +- Removed "rustup" & added new runner tag ([#9731](https://github.com/paritytech/parity-ethereum/pull/9731)) +- Expose config max-round-blocks-to-import ([#9439](https://github.com/paritytech/parity-ethereum/pull/9439)) +- Aura: finalize blocks ([#9692](https://github.com/paritytech/parity-ethereum/pull/9692)) +- Sync: retry different peer after empty subchain heads response ([#9753](https://github.com/paritytech/parity-ethereum/pull/9753)) +- Fix(light-rpc/parity) : Remove unused client ([#9802](https://github.com/paritytech/parity-ethereum/pull/9802)) +- Drops support for olympic testnet, closes [#9800](https://github.com/paritytech/parity-ethereum/issues/9800) ([#9801](https://github.com/paritytech/parity-ethereum/pull/9801)) +- Replace `tokio_core` with `tokio` (`ring` -> 0.13) ([#9657](https://github.com/paritytech/parity-ethereum/pull/9657)) +- Support eth_chainId RPC method ([#9783](https://github.com/paritytech/parity-ethereum/pull/9783)) +- Ethcore: bump ropsten forkblock checkpoint ([#9775](https://github.com/paritytech/parity-ethereum/pull/9775)) +- Docs: changelogs for 2.0.8 and 2.1.3 ([#9758](https://github.com/paritytech/parity-ethereum/pull/9758)) +- Prevent zero networkID ([#9763](https://github.com/paritytech/parity-ethereum/pull/9763)) +- Skip seal fields count check when --no-seal-check is used ([#9757](https://github.com/paritytech/parity-ethereum/pull/9757)) +- Aura: fix panic on extra_info with unsealed block ([#9755](https://github.com/paritytech/parity-ethereum/pull/9755)) +- Docs: update changelogs ([#9742](https://github.com/paritytech/parity-ethereum/pull/9742)) +- Removed extra assert in generation_session_is_removed_when_succeeded ([#9738](https://github.com/paritytech/parity-ethereum/pull/9738)) +- Make checkpoint_storage_at use plain loop instead of recursion ([#9734](https://github.com/paritytech/parity-ethereum/pull/9734)) +- Use signed 256-bit integer for sstore gas refund substate ([#9746](https://github.com/paritytech/parity-ethereum/pull/9746)) +- Heads ref not present for branches beta and stable ([#9741](https://github.com/paritytech/parity-ethereum/pull/9741)) +- Add Callisto support ([#9534](https://github.com/paritytech/parity-ethereum/pull/9534)) +- Add --force to cargo audit install script ([#9735](https://github.com/paritytech/parity-ethereum/pull/9735)) +- Remove unused expired value from Handshake ([#9732](https://github.com/paritytech/parity-ethereum/pull/9732)) +- Add hardcoded headers ([#9730](https://github.com/paritytech/parity-ethereum/pull/9730)) +- Produce portable binaries ([#9725](https://github.com/paritytech/parity-ethereum/pull/9725)) +- Gitlab ci: releasable_branches: change variables condition to schedule ([#9729](https://github.com/paritytech/parity-ethereum/pull/9729)) +- Update a few parity-common dependencies ([#9663](https://github.com/paritytech/parity-ethereum/pull/9663)) +- Hf in POA Core (2018-10-22) ([#9724](https://github.com/paritytech/parity-ethereum/pull/9724)) +- Schedule nightly builds ([#9717](https://github.com/paritytech/parity-ethereum/pull/9717)) +- Fix ancient blocks sync ([#9531](https://github.com/paritytech/parity-ethereum/pull/9531)) +- Ci: Skip docs job for nightly ([#9693](https://github.com/paritytech/parity-ethereum/pull/9693)) +- Fix (light/provider) : Make `read_only executions` read-only ([#9591](https://github.com/paritytech/parity-ethereum/pull/9591)) +- Ethcore: fix detection of major import ([#9552](https://github.com/paritytech/parity-ethereum/pull/9552)) +- Return 0 on error ([#9705](https://github.com/paritytech/parity-ethereum/pull/9705)) +- Ethcore: delay ropsten hardfork ([#9704](https://github.com/paritytech/parity-ethereum/pull/9704)) +- Make instantSeal engine backwards compatible, closes [#9696](https://github.com/paritytech/parity-ethereum/issues/9696) ([#9700](https://github.com/paritytech/parity-ethereum/pull/9700)) +- Implement CREATE2 gas changes and fix some potential overflowing ([#9694](https://github.com/paritytech/parity-ethereum/pull/9694)) +- Don't hash the init_code of CREATE. ([#9688](https://github.com/paritytech/parity-ethereum/pull/9688)) +- Ethcore: minor optimization of modexp by using LR exponentiation ([#9697](https://github.com/paritytech/parity-ethereum/pull/9697)) +- Removed redundant clone before each block import ([#9683](https://github.com/paritytech/parity-ethereum/pull/9683)) +- Add Foundation Bootnodes ([#9666](https://github.com/paritytech/parity-ethereum/pull/9666)) +- Docker: run as parity user ([#9689](https://github.com/paritytech/parity-ethereum/pull/9689)) +- Ethcore: mcip3 block reward contract ([#9605](https://github.com/paritytech/parity-ethereum/pull/9605)) +- Verify block syncing responses against requests ([#9670](https://github.com/paritytech/parity-ethereum/pull/9670)) +- Add a new RPC `parity_submitWorkDetail` similar `eth_submitWork` but return block hash ([#9404](https://github.com/paritytech/parity-ethereum/pull/9404)) +- Resumable EVM and heap-allocated callstack ([#9360](https://github.com/paritytech/parity-ethereum/pull/9360)) +- Update parity-wordlist library ([#9682](https://github.com/paritytech/parity-ethereum/pull/9682)) +- Ci: Remove unnecessary pipes ([#9681](https://github.com/paritytech/parity-ethereum/pull/9681)) +- Test.sh: use cargo --target for platforms other than linux, win or mac ([#9650](https://github.com/paritytech/parity-ethereum/pull/9650)) +- Ci: fix push script ([#9679](https://github.com/paritytech/parity-ethereum/pull/9679)) +- Hardfork the testnets ([#9562](https://github.com/paritytech/parity-ethereum/pull/9562)) +- Calculate sha3 instead of sha256 for push-release. ([#9673](https://github.com/paritytech/parity-ethereum/pull/9673)) +- Ethcore-io retries failed work steal ([#9651](https://github.com/paritytech/parity-ethereum/pull/9651)) +- Fix(light_fetch): avoid race with BlockNumber::Latest ([#9665](https://github.com/paritytech/parity-ethereum/pull/9665)) +- Test fix for windows cache name... ([#9658](https://github.com/paritytech/parity-ethereum/pull/9658)) +- Refactor(fetch) : light use only one `DNS` thread ([#9647](https://github.com/paritytech/parity-ethereum/pull/9647)) +- Ethereum libfuzzer integration small change ([#9547](https://github.com/paritytech/parity-ethereum/pull/9547)) +- Cli: remove reference to --no-ui in --unlock flag help ([#9616](https://github.com/paritytech/parity-ethereum/pull/9616)) +- Remove master from releasable branches ([#9655](https://github.com/paritytech/parity-ethereum/pull/9655)) +- Ethcore/VerificationQueue don't spawn up extra `worker-threads` when explictly specified not to ([#9620](https://github.com/paritytech/parity-ethereum/pull/9620)) +- Rpc: parity_getBlockReceipts ([#9527](https://github.com/paritytech/parity-ethereum/pull/9527)) +- Remove unused dependencies ([#9589](https://github.com/paritytech/parity-ethereum/pull/9589)) +- Ignore key_server_cluster randomly failing tests ([#9639](https://github.com/paritytech/parity-ethereum/pull/9639)) +- Ethcore: handle vm exception when estimating gas ([#9615](https://github.com/paritytech/parity-ethereum/pull/9615)) +- Fix bad-block reporting no reason ([#9638](https://github.com/paritytech/parity-ethereum/pull/9638)) +- Use static call and apparent value transfer for block reward contract code ([#9603](https://github.com/paritytech/parity-ethereum/pull/9603)) +- Hf in POA Sokol (2018-09-19) ([#9607](https://github.com/paritytech/parity-ethereum/pull/9607)) +- Bump smallvec to 0.6 in ethcore-light, ethstore and whisper ([#9588](https://github.com/paritytech/parity-ethereum/pull/9588)) +- Add constantinople conf to EvmTestClient. ([#9570](https://github.com/paritytech/parity-ethereum/pull/9570)) +- Fix(network): don't disconnect reserved peers ([#9608](https://github.com/paritytech/parity-ethereum/pull/9608)) +- Fix failing node-table tests on mac os, closes [#9632](https://github.com/paritytech/parity-ethereum/issues/9632) ([#9633](https://github.com/paritytech/parity-ethereum/pull/9633)) +- Update ropsten.json ([#9602](https://github.com/paritytech/parity-ethereum/pull/9602)) +- Simplify ethcore errors by removing BlockImportError ([#9593](https://github.com/paritytech/parity-ethereum/pull/9593)) +- Fix windows compilation, replaces [#9561](https://github.com/paritytech/parity-ethereum/issues/9561) ([#9621](https://github.com/paritytech/parity-ethereum/pull/9621)) +- Master: rpc-docs set github token ([#9610](https://github.com/paritytech/parity-ethereum/pull/9610)) +- Docs: add changelogs for 1.11.10, 1.11.11, 2.0.3, 2.0.4, 2.0.5, 2.0.6, 2.1.0, and 2.1.1 ([#9554](https://github.com/paritytech/parity-ethereum/pull/9554)) +- Docs(rpc): annotate tag with the provided message ([#9601](https://github.com/paritytech/parity-ethereum/pull/9601)) +- Ci: fix regex roll_eyes ([#9597](https://github.com/paritytech/parity-ethereum/pull/9597)) +- Remove snapcraft clean ([#9585](https://github.com/paritytech/parity-ethereum/pull/9585)) +- Add snapcraft package image (master) ([#9584](https://github.com/paritytech/parity-ethereum/pull/9584)) +- Docs(rpc): push the branch along with tags ([#9578](https://github.com/paritytech/parity-ethereum/pull/9578)) +- Fix typo for jsonrpc-threads flag ([#9574](https://github.com/paritytech/parity-ethereum/pull/9574)) +- Fix informant compile ([#9571](https://github.com/paritytech/parity-ethereum/pull/9571)) +- Added ropsten bootnodes ([#9569](https://github.com/paritytech/parity-ethereum/pull/9569)) +- Increase Gas-floor-target and Gas Cap ([#9564](https://github.com/paritytech/parity-ethereum/pull/9564)) +- While working on the platform tests make them non-breaking ([#9563](https://github.com/paritytech/parity-ethereum/pull/9563)) +- Improve P2P discovery ([#9526](https://github.com/paritytech/parity-ethereum/pull/9526)) +- Move dockerfile for android build container to scripts repo ([#9560](https://github.com/paritytech/parity-ethereum/pull/9560)) +- Simultaneous platform tests WIP ([#9557](https://github.com/paritytech/parity-ethereum/pull/9557)) +- Update ethabi-derive, serde, serde_json, serde_derive, syn && quote ([#9553](https://github.com/paritytech/parity-ethereum/pull/9553)) +- Ci: fix rpc docs generation 2 ([#9550](https://github.com/paritytech/parity-ethereum/pull/9550)) +- Ci: always run build pipelines for win, mac, linux, and android ([#9537](https://github.com/paritytech/parity-ethereum/pull/9537)) +- Multithreaded snapshot creation ([#9239](https://github.com/paritytech/parity-ethereum/pull/9239)) +- New ethabi ([#9511](https://github.com/paritytech/parity-ethereum/pull/9511)) +- Remove initial token for WS. ([#9545](https://github.com/paritytech/parity-ethereum/pull/9545)) +- Net_version caches network_id to avoid redundant aquire of sync readlock ([#9544](https://github.com/paritytech/parity-ethereum/pull/9544)) +- Correct before_script for nightly build versions ([#9543](https://github.com/paritytech/parity-ethereum/pull/9543)) +- Deps: bump kvdb-rocksdb to 0.1.4 ([#9539](https://github.com/paritytech/parity-ethereum/pull/9539)) +- State: test when contract creation fails, old storage values should re-appear ([#9532](https://github.com/paritytech/parity-ethereum/pull/9532)) +- Allow dropping light client RPC query with no results ([#9318](https://github.com/paritytech/parity-ethereum/pull/9318)) +- Bump master to 2.2.0 ([#9517](https://github.com/paritytech/parity-ethereum/pull/9517)) +- Enable all Constantinople hard fork changes in constantinople_test.json ([#9505](https://github.com/paritytech/parity-ethereum/pull/9505)) +- [Light] Validate `account balance` before importing transactions ([#9417](https://github.com/paritytech/parity-ethereum/pull/9417)) +- In create memory calculation is the same for create2 because the additional parameter was popped before. ([#9522](https://github.com/paritytech/parity-ethereum/pull/9522)) +- Update patricia trie to 0.2.2 ([#9525](https://github.com/paritytech/parity-ethereum/pull/9525)) +- Replace hardcoded JSON with serde json! macro ([#9489](https://github.com/paritytech/parity-ethereum/pull/9489)) +- Fix typo in version string ([#9516](https://github.com/paritytech/parity-ethereum/pull/9516)) diff --git a/docs/CHANGELOG-2.3.md b/docs/CHANGELOG-2.3.md new file mode 100644 index 0000000000..34286baf1b --- /dev/null +++ b/docs/CHANGELOG-2.3.md @@ -0,0 +1,288 @@ +## Parity-Ethereum [v2.3.8](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.8) (2019-03-22) + +Parity-Ethereum 2.3.8-stable is a bugfix release that improves performance and stability. This patch release contains a critical bug fix where serving light clients previously led to client crashes. Upgrading is highly recommended. + +The full list of included changes: +- 2.3.8 stable backports ([#10507](https://github.com/paritytech/parity-ethereum/pull/10507)) + - Version: bump stable + - Add additional request tests ([#10503](https://github.com/paritytech/parity-ethereum/pull/10503)) + +## Parity-Ethereum [v2.3.7](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.7) (2019-03-20) + +Parity-Ethereum 2.3.7-stable is a bugfix release that improves performance and stability. + +The full list of included changes: +- 2.3.7 stable backports ([#10487](https://github.com/paritytech/parity-ethereum/pull/10487)) + - Version: bump stable + - Сaching through docker volume ([#10477](https://github.com/paritytech/parity-ethereum/pull/10477)) + - fix win&mac build ([#10486](https://github.com/paritytech/parity-ethereum/pull/10486)) + - fix(extract `timestamp_checked_add` as lib) ([#10383](https://github.com/paritytech/parity-ethereum/pull/10383)) + +## Parity-Ethereum [v2.3.6](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.6) (2019-03-19) + +Parity-Ethereum 2.3.6-stable is a bugfix release that improves performance and stability. + +The full list of included changes: +- 2.3.6 stable backports ([#10470](https://github.com/paritytech/parity-ethereum/pull/10470)) + - Version: bump stable + - CI publish to aws ([#10446](https://github.com/paritytech/parity-ethereum/pull/10446)) + - Ensure static validator set changes are recognized ([#10467](https://github.com/paritytech/parity-ethereum/pull/10467)) + - CI aws git checkout ([#10451](https://github.com/paritytech/parity-ethereum/pull/10451)) + - Revert "CI aws git checkout ([#10451](https://github.com/paritytech/parity-ethereum/pull/10451))" ([#10456](https://github.com/paritytech/parity-ethereum/pull/10456)) + - Tests parallelized ([#10452](https://github.com/paritytech/parity-ethereum/pull/10452)) + +## Parity-Ethereum [v2.3.5](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.5) (2019-02-25) + +Parity-Ethereum 2.3.5-stable is a bugfix release that improves performance and stability. + +Note, all 2.2 releases and older are now unsupported and upgrading is recommended. + +The full list of included changes: + +- More Backports for Stable 2.3.5 ([#10430](https://github.com/paritytech/parity-ethereum/pull/10430)) + - Revert some changes, could be buggy ([#10399](https://github.com/paritytech/parity-ethereum/pull/10399)) + - Ci: clean up gitlab-ci.yml leftovers from previous merge ([#10429](https://github.com/paritytech/parity-ethereum/pull/10429)) + - 10000 > 5000 ([#10422](https://github.com/paritytech/parity-ethereum/pull/10422)) + - Fix underflow in pip, closes [#10419](https://github.com/paritytech/parity-ethereum/pull/10419) ([#10423](https://github.com/paritytech/parity-ethereum/pull/10423)) + - Fix panic when logging directory does not exist, closes [#10420](https://github.com/paritytech/parity-ethereum/pull/10420) ([#10424](https://github.com/paritytech/parity-ethereum/pull/10424)) + - Update hardcoded headers for Foundation, Ropsten, Kovan and Classic ([#10417](https://github.com/paritytech/parity-ethereum/pull/10417)) +- Backports for Stable 2.3.5 ([#10414](https://github.com/paritytech/parity-ethereum/pull/10414)) + - No-git for publish jobs, empty artifacts dir ([#10393](https://github.com/paritytech/parity-ethereum/pull/10393)) + - Snap: reenable i386, arm64, armhf architecture publishing ([#10386](https://github.com/paritytech/parity-ethereum/pull/10386)) + - Tx pool: always accept local transactions ([#10375](https://github.com/paritytech/parity-ethereum/pull/10375)) + - Fix to_pod storage trie value decoding ([#10368)](https://github.com/paritytech/parity-ethereum/pull/10368)) +- Version: mark 2.3.5 as stable + +## Parity-Ethereum [v2.3.4](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.4) (2019-02-21) + +Parity-Ethereum 2.3.4-beta is a maintenance release that fixes snap and docker installations. + +The full list of included changes: +- Beta: snap: release untagged versions from branches to the candidate ([#10357](https://github.com/paritytech/parity-ethereum/pull/10357)) ([#10373](https://github.com/paritytech/parity-ethereum/pull/10373)) + - Snap: release untagged versions from branches to the candidate snap channel ([#10357](https://github.com/paritytech/parity-ethereum/pull/10357)) + - Snap: add the removable-media plug ([#10377](https://github.com/paritytech/parity-ethereum/pull/10377)) + - Exchanged old(azure) bootnodes with new(ovh) ones ([#10309](https://github.com/paritytech/parity-ethereum/pull/10309)) +- Beta Backports ([#10354](https://github.com/paritytech/parity-ethereum/pull/10354)) + - Version: bump beta to 2.3.4 + - Snap: prefix version and populate candidate channel ([#10343](https://github.com/paritytech/parity-ethereum/pull/10343)) + - Snap: populate candidate releases with beta snaps to avoid stale channel + - Snap: prefix version with v* + - No volumes are needed, just run -v volume:/path/in/the/container ([#10345](https://github.com/paritytech/parity-ethereum/pull/10345)) + +## Parity-Ethereum [v2.3.3](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.3) (2019-02-13) + +Parity-Ethereum 2.3.3-beta is a security-relevant release. A bug in the JSONRPC-deserialization module can cause crashes of all versions of Parity Ethereum nodes if an attacker is able to submit a specially-crafted RPC to certain publicly available endpoints. + +- https://www.parity.io/new-parity-ethereum-update-fixes-several-rpc-vulnerabilities/ + +The full list of included changes: + +- Additional error for invalid gas ([#10327](https://github.com/paritytech/parity-ethereum/pull/10327)) ([#10328](https://github.com/paritytech/parity-ethereum/pull/10328)) +- Backports for Beta 2.3.3 ([#10333](https://github.com/paritytech/parity-ethereum/pull/10333)) + - Properly handle check_epoch_end_signal errors ([#10015](https://github.com/paritytech/parity-ethereum/pull/10015)) + - import rpc transactions sequentially ([#10051](https://github.com/paritytech/parity-ethereum/pull/10051)) + - fix(docker): fix not receives SIGINT ([#10059](https://github.com/paritytech/parity-ethereum/pull/10059)) + - snap: official image / test ([#10168](https://github.com/paritytech/parity-ethereum/pull/10168)) + - Extract CallContract and RegistryInfo traits into their own crate ([#10178](https://github.com/paritytech/parity-ethereum/pull/10178)) + - perform stripping during build ([#10208](https://github.com/paritytech/parity-ethereum/pull/10208)) + - Remove CallContract and RegistryInfo re-exports from `ethcore/client` ([#10205](https://github.com/paritytech/parity-ethereum/pull/10205)) + - fixed: types::transaction::SignedTransaction; ([#10229](https://github.com/paritytech/parity-ethereum/pull/10229)) + - Additional tests for uint/hash/bytes deserialization. ([#10279](https://github.com/paritytech/parity-ethereum/pull/10279)) + - Fix Windows build ([#10284](https://github.com/paritytech/parity-ethereum/pull/10284)) + - Don't run the CPP example on CI ([#10285](https://github.com/paritytech/parity-ethereum/pull/10285)) + - CI optimizations ([#10297](https://github.com/paritytech/parity-ethereum/pull/10297)) + - fix publish job ([#10317](https://github.com/paritytech/parity-ethereum/pull/10317)) + - Add Statetest support for Constantinople Fix ([#10323](https://github.com/paritytech/parity-ethereum/pull/10323)) + - Add helper for Timestamp overflows ([#10330](https://github.com/paritytech/parity-ethereum/pull/10330)) + - Don't add discovery initiators to the node table ([#10305](https://github.com/paritytech/parity-ethereum/pull/10305)) + - change docker image based on debian instead of ubuntu due to the chan ([#10336](https://github.com/paritytech/parity-ethereum/pull/10336)) + - role back docker build image and docker deploy image to ubuntu:xenial based ([#10338](https://github.com/paritytech/parity-ethereum/pull/10338)) + +## Parity-Ethereum [v2.3.2](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.2) (2019-02-03) + +Parity-Ethereum 2.3.2-stable is a security-relevant release. A bug in the JSONRPC-deserialization module can cause crashes of all versions of Parity Ethereum nodes if an attacker is able to submit a specially-crafted RPC to certain publicly available endpoints. + +- https://www.parity.io/security-alert-parity-ethereum-03-02/ + +The full list of included changes: +- Version: bump beta to 2.3.2 ([#10283](https://github.com/paritytech/parity-ethereum/pull/10283)) +- Additional tests for uint deserialization. ([#10279](https://github.com/paritytech/parity-ethereum/pull/10279)) ([#10280](https://github.com/paritytech/parity-ethereum/pull/10280)) +- Backport [#10285](https://github.com/paritytech/parity-ethereum/pull/10285) to beta ([#10286](https://github.com/paritytech/parity-ethereum/pull/10286)) + +## Parity-Ethereum [v2.3.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.1) (2019-02-01) + +Parity-Ethereum 2.3.1-beta is a consensus-relevant release that enables _St. Petersfork_ on: + +- Ethereum Block `7280000` (along with Constantinople) +- Kovan Block `10255201` +- Ropsten Block `4939394` +- POA Sokol Block `7026400` + +In addition to this, Constantinople is cancelled for the POA Core network. Upgrading is mandatory for clients on any of these chains. + +The full list of included changes: + +- Backports for beta 2.3.1 ([#10225](https://github.com/paritytech/parity-ethereum/pull/10225)) + - Fix _cannot recursively call into `Core`_ issue ([#10144](https://github.com/paritytech/parity-ethereum/pull/10144)) + - Update for Android cross-compilation. ([#10180](https://github.com/paritytech/parity-ethereum/pull/10180)) + - Fix _cannot recursively call into `Core`_ - Part 2 ([#10195](https://github.com/paritytech/parity-ethereum/pull/10195)) + - Cancel Constantinople HF on POA Core ([#10198](https://github.com/paritytech/parity-ethereum/pull/10198)) + - Add EIP-1283 disable transition ([#10214](https://github.com/paritytech/parity-ethereum/pull/10214)) + - Enable St-Peters-Fork ("Constantinople Fix") ([#10223](https://github.com/paritytech/parity-ethereum/pull/10223)) +- Beta: Macos heapsize force jemalloc ([#10234](https://github.com/paritytech/parity-ethereum/pull/10234)) ([#10259](https://github.com/paritytech/parity-ethereum/pull/10259)) + +## Parity-Ethereum [v2.3.0](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.0) (2019-01-16) + +Parity-Ethereum 2.3.0-beta is a consensus-relevant security release that reverts Constantinople on the Ethereum network. Upgrading is mandatory for Ethereum, and strongly recommended for other networks. + +- **Consensus** - Ethereum Network: Pull Constantinople protocol upgrade on Ethereum ([#10189](https://github.com/paritytech/parity-ethereum/pull/10189)) + - Read more: [Security Alert: Ethereum Constantinople Postponement](https://blog.ethereum.org/2019/01/15/security-alert-ethereum-constantinople-postponement/) +- **Networking** - All networks: Ping nodes from discovery ([#10167](https://github.com/paritytech/parity-ethereum/pull/10167)) +- **Wasm** - Kovan Network: Update pwasm-utils to 0.6.1 ([#10134](https://github.com/paritytech/parity-ethereum/pull/10134)) + +Other notable changes: + +- Existing blocks in the database are now kept when restoring a Snapshot. ([#8643](https://github.com/paritytech/parity-ethereum/pull/8643)) +- Block and transaction propagation is improved significantly. ([#9954](https://github.com/paritytech/parity-ethereum/pull/9954)) +- The ERC-191 Signed Data Standard is now supported by `personal_sign191`. ([#9701](https://github.com/paritytech/parity-ethereum/pull/9701)) +- Add support for ERC-191/712 `eth_signTypedData` as a standard for machine-verifiable and human-readable typed data signing with Ethereum keys. ([#9631](https://github.com/paritytech/parity-ethereum/pull/9631)) +- Add support for ERC-1186 `eth_getProof` ([#9001](https://github.com/paritytech/parity-ethereum/pull/9001)) +- Add experimental RPCs flag to enable ERC-191, ERC-712, and ERC-1186 APIs via `--jsonrpc-experimental` ([#9928](https://github.com/paritytech/parity-ethereum/pull/9928)) +- Make `CALLCODE` to trace value to be the code address. ([#9881](https://github.com/paritytech/parity-ethereum/pull/9881)) + +Configuration changes: + +- The EIP-98 transition is now disabled by default. If you previously had no `eip98transition` specified in your chain specification, you would enable this now manually on block `0x0`. ([#9955](https://github.com/paritytech/parity-ethereum/pull/9955)) +- Also, unknown fields in chain specs are now rejected. ([#9972](https://github.com/paritytech/parity-ethereum/pull/9972)) +- The Tendermint engine was removed from Parity Ethereum and is no longer available and maintained. ([#9980](https://github.com/paritytech/parity-ethereum/pull/9980)) +- Ropsten testnet data and keys moved from `test/` to `ropsten/` subdir. To reuse your old keys and data either copy or symlink them to the new location. ([#10123](https://github.com/paritytech/parity-ethereum/pull/10123)) +- Strict empty steps validation ([#10041](https://github.com/paritytech/parity-ethereum/pull/10041)) + - If you have a chain with`empty_steps` already running, some blocks most likely contain non-strict entries (unordered or duplicated empty steps). In this release `strict_empty_steps_transition` is enabled by default at block `0x0` for any chain with `empty_steps`. + - If your network uses `empty_steps` you **must** (A) plan a hard fork and change `strict_empty_steps_transition` to the desired fork block and (B) update the clients of the whole network to 2.2.7-stable / 2.3.0-beta. If for some reason you don't want to do this please set`strict_empty_steps_transition` to `0xfffffffff` to disable it. + +_Note:_ This release marks Parity 2.3 as _beta_. All versions of Parity 2.2 are now considered _stable_. + +The full list of included changes: + +- Backports for 2.3.0 beta ([#10164](https://github.com/paritytech/parity-ethereum/pull/10164)) +- Snap: fix path in script ([#10157](https://github.com/paritytech/parity-ethereum/pull/10157)) +- Make sure parent block is not in importing queue when importing ancient blocks ([#10138](https://github.com/paritytech/parity-ethereum/pull/10138)) +- Ci: re-enable snap publishing ([#10142](https://github.com/paritytech/parity-ethereum/pull/10142)) +- Hf in POA Core (2019-01-18) - Constantinople ([#10155](https://github.com/paritytech/parity-ethereum/pull/10155)) +- Update EWF's tobalaba chainspec ([#10152](https://github.com/paritytech/parity-ethereum/pull/10152)) +- Replace ethcore-logger with env-logger. ([#10102](https://github.com/paritytech/parity-ethereum/pull/10102)) +- Finality: dont require chain head to be in the chain ([#10054](https://github.com/paritytech/parity-ethereum/pull/10054)) +- Remove caching for node connections ([#10143](https://github.com/paritytech/parity-ethereum/pull/10143)) +- Blooms file iterator empty on out of range position. ([#10145](https://github.com/paritytech/parity-ethereum/pull/10145)) +- Autogen docs for the "Configuring Parity Ethereum" wiki page. ([#10067](https://github.com/paritytech/parity-ethereum/pull/10067)) +- Misc: bump license header to 2019 ([#10135](https://github.com/paritytech/parity-ethereum/pull/10135)) +- Hide most of the logs from cpp example. ([#10139](https://github.com/paritytech/parity-ethereum/pull/10139)) +- Don't try to send oversized packets ([#10042](https://github.com/paritytech/parity-ethereum/pull/10042)) +- Private tx enabled flag added into STATUS packet ([#9999](https://github.com/paritytech/parity-ethereum/pull/9999)) +- Update pwasm-utils to 0.6.1 ([#10134](https://github.com/paritytech/parity-ethereum/pull/10134)) +- Extract blockchain from ethcore ([#10114](https://github.com/paritytech/parity-ethereum/pull/10114)) +- Ethcore: update hardcoded headers ([#10123](https://github.com/paritytech/parity-ethereum/pull/10123)) +- Identity fix ([#10128](https://github.com/paritytech/parity-ethereum/pull/10128)) +- Use LenCachingMutex to optimize verification. ([#10117](https://github.com/paritytech/parity-ethereum/pull/10117)) +- Pyethereum keystore support ([#9710](https://github.com/paritytech/parity-ethereum/pull/9710)) +- Bump rocksdb-sys to 0.5.5 ([#10124](https://github.com/paritytech/parity-ethereum/pull/10124)) +- Parity-clib: `async C bindings to RPC requests` + `subscribe/unsubscribe to websocket events` ([#9920](https://github.com/paritytech/parity-ethereum/pull/9920)) +- Refactor (hardware wallet) : reduce the number of threads ([#9644](https://github.com/paritytech/parity-ethereum/pull/9644)) +- Hf in POA Sokol (2019-01-04) ([#10077](https://github.com/paritytech/parity-ethereum/pull/10077)) +- Fix broken links ([#10119](https://github.com/paritytech/parity-ethereum/pull/10119)) +- Follow-up to [#10105](https://github.com/paritytech/parity-ethereum/issues/10105) ([#10107](https://github.com/paritytech/parity-ethereum/pull/10107)) +- Move EIP-712 crate back to parity-ethereum ([#10106](https://github.com/paritytech/parity-ethereum/pull/10106)) +- Move a bunch of stuff around ([#10101](https://github.com/paritytech/parity-ethereum/pull/10101)) +- Revert "Add --frozen when running cargo ([#10081](https://github.com/paritytech/parity-ethereum/pull/10081))" ([#10105](https://github.com/paritytech/parity-ethereum/pull/10105)) +- Fix left over small grumbles on whitespaces ([#10084](https://github.com/paritytech/parity-ethereum/pull/10084)) +- Add --frozen when running cargo ([#10081](https://github.com/paritytech/parity-ethereum/pull/10081)) +- Fix pubsub new_blocks notifications to include all blocks ([#9987](https://github.com/paritytech/parity-ethereum/pull/9987)) +- Update some dependencies for compilation with pc-windows-gnu ([#10082](https://github.com/paritytech/parity-ethereum/pull/10082)) +- Fill transaction hash on ethGetLog of light client. ([#9938](https://github.com/paritytech/parity-ethereum/pull/9938)) +- Update changelog update for 2.2.5-beta and 2.1.10-stable ([#10064](https://github.com/paritytech/parity-ethereum/pull/10064)) +- Implement len caching for parking_lot RwLock ([#10032](https://github.com/paritytech/parity-ethereum/pull/10032)) +- Update parking_lot to 0.7 ([#10050](https://github.com/paritytech/parity-ethereum/pull/10050)) +- Bump crossbeam. ([#10048](https://github.com/paritytech/parity-ethereum/pull/10048)) +- Ethcore: enable constantinople on ethereum ([#10031](https://github.com/paritytech/parity-ethereum/pull/10031)) +- Strict empty steps validation ([#10041](https://github.com/paritytech/parity-ethereum/pull/10041)) +- Center the Subtitle, use some CAPS ([#10034](https://github.com/paritytech/parity-ethereum/pull/10034)) +- Change test miner max memory to malloc reports. ([#10024](https://github.com/paritytech/parity-ethereum/pull/10024)) +- Sort the storage for private state ([#10018](https://github.com/paritytech/parity-ethereum/pull/10018)) +- Fix: test corpus_inaccessible panic ([#10019](https://github.com/paritytech/parity-ethereum/pull/10019)) +- Ci: move future releases to ethereum subdir on s3 ([#10017](https://github.com/paritytech/parity-ethereum/pull/10017)) +- Light(on_demand): decrease default time window to 10 secs ([#10016](https://github.com/paritytech/parity-ethereum/pull/10016)) +- Light client : failsafe crate (circuit breaker) ([#9790](https://github.com/paritytech/parity-ethereum/pull/9790)) +- Lencachingmutex ([#9988](https://github.com/paritytech/parity-ethereum/pull/9988)) +- Version and notification for private contract wrapper added ([#9761](https://github.com/paritytech/parity-ethereum/pull/9761)) +- Handle failing case for update account cache in require ([#9989](https://github.com/paritytech/parity-ethereum/pull/9989)) +- Add tokio runtime to ethcore io worker ([#9979](https://github.com/paritytech/parity-ethereum/pull/9979)) +- Move daemonize before creating account provider ([#10003](https://github.com/paritytech/parity-ethereum/pull/10003)) +- Docs: update changelogs ([#9990](https://github.com/paritytech/parity-ethereum/pull/9990)) +- Fix daemonize ([#10000](https://github.com/paritytech/parity-ethereum/pull/10000)) +- Fix Bloom migration ([#9992](https://github.com/paritytech/parity-ethereum/pull/9992)) +- Remove tendermint engine support ([#9980](https://github.com/paritytech/parity-ethereum/pull/9980)) +- Calculate gas for deployment transaction ([#9840](https://github.com/paritytech/parity-ethereum/pull/9840)) +- Fix unstable peers and slowness in sync ([#9967](https://github.com/paritytech/parity-ethereum/pull/9967)) +- Adds parity_verifySignature RPC method ([#9507](https://github.com/paritytech/parity-ethereum/pull/9507)) +- Improve block and transaction propagation ([#9954](https://github.com/paritytech/parity-ethereum/pull/9954)) +- Deny unknown fields for chainspec ([#9972](https://github.com/paritytech/parity-ethereum/pull/9972)) +- Fix docker build ([#9971](https://github.com/paritytech/parity-ethereum/pull/9971)) +- Ci: rearrange pipeline by logic ([#9970](https://github.com/paritytech/parity-ethereum/pull/9970)) +- Add changelogs for 2.0.9, 2.1.4, 2.1.6, and 2.2.1 ([#9963](https://github.com/paritytech/parity-ethereum/pull/9963)) +- Add Error message when sync is still in progress. ([#9475](https://github.com/paritytech/parity-ethereum/pull/9475)) +- Make CALLCODE to trace value to be the code address ([#9881](https://github.com/paritytech/parity-ethereum/pull/9881)) +- Fix light client informant while syncing ([#9932](https://github.com/paritytech/parity-ethereum/pull/9932)) +- Add a optional json dump state to evm-bin ([#9706](https://github.com/paritytech/parity-ethereum/pull/9706)) +- Disable EIP-98 transition by default ([#9955](https://github.com/paritytech/parity-ethereum/pull/9955)) +- Remove secret_store runtimes. ([#9888](https://github.com/paritytech/parity-ethereum/pull/9888)) +- Fix a deadlock ([#9952](https://github.com/paritytech/parity-ethereum/pull/9952)) +- Chore(eip712): remove unused `failure-derive` ([#9958](https://github.com/paritytech/parity-ethereum/pull/9958)) +- Do not use the home directory as the working dir in docker ([#9834](https://github.com/paritytech/parity-ethereum/pull/9834)) +- Prevent silent errors in daemon mode, closes [#9367](https://github.com/paritytech/parity-ethereum/issues/9367) ([#9946](https://github.com/paritytech/parity-ethereum/pull/9946)) +- Fix empty steps ([#9939](https://github.com/paritytech/parity-ethereum/pull/9939)) +- Adjust requests costs for light client ([#9925](https://github.com/paritytech/parity-ethereum/pull/9925)) +- Eip-1186: add `eth_getProof` RPC-Method ([#9001](https://github.com/paritytech/parity-ethereum/pull/9001)) +- Missing blocks in filter_changes RPC ([#9947](https://github.com/paritytech/parity-ethereum/pull/9947)) +- Allow rust-nightly builds fail in nightly builds ([#9944](https://github.com/paritytech/parity-ethereum/pull/9944)) +- Update eth-secp256k1 to include fix for BSDs ([#9935](https://github.com/paritytech/parity-ethereum/pull/9935)) +- Unbreak build on rust -stable ([#9934](https://github.com/paritytech/parity-ethereum/pull/9934)) +- Keep existing blocks when restoring a Snapshot ([#8643](https://github.com/paritytech/parity-ethereum/pull/8643)) +- Add experimental RPCs flag ([#9928](https://github.com/paritytech/parity-ethereum/pull/9928)) +- Clarify poll lifetime ([#9922](https://github.com/paritytech/parity-ethereum/pull/9922)) +- Docs(require rust 1.30) ([#9923](https://github.com/paritytech/parity-ethereum/pull/9923)) +- Use block header for building finality ([#9914](https://github.com/paritytech/parity-ethereum/pull/9914)) +- Simplify cargo audit ([#9918](https://github.com/paritytech/parity-ethereum/pull/9918)) +- Light-fetch: Differentiate between out-of-gas/manual throw and use required gas from response on failure ([#9824](https://github.com/paritytech/parity-ethereum/pull/9824)) +- Eip 191 ([#9701](https://github.com/paritytech/parity-ethereum/pull/9701)) +- Fix(logger): `reqwest` no longer a dependency ([#9908](https://github.com/paritytech/parity-ethereum/pull/9908)) +- Remove rust-toolchain file ([#9906](https://github.com/paritytech/parity-ethereum/pull/9906)) +- Foundation: 6692865, ropsten: 4417537, kovan: 9363457 ([#9907](https://github.com/paritytech/parity-ethereum/pull/9907)) +- Ethcore: use Machine::verify_transaction on parent block ([#9900](https://github.com/paritytech/parity-ethereum/pull/9900)) +- Chore(rpc-tests): remove unused rand ([#9896](https://github.com/paritytech/parity-ethereum/pull/9896)) +- Fix: Intermittent failing CI due to addr in use ([#9885](https://github.com/paritytech/parity-ethereum/pull/9885)) +- Chore(bump docopt): 0.8 -> 1.0 ([#9889](https://github.com/paritytech/parity-ethereum/pull/9889)) +- Use expect ([#9883](https://github.com/paritytech/parity-ethereum/pull/9883)) +- Use Weak reference in PubSubClient ([#9886](https://github.com/paritytech/parity-ethereum/pull/9886)) +- Ci: nuke the gitlab caches ([#9855](https://github.com/paritytech/parity-ethereum/pull/9855)) +- Remove unused code ([#9884](https://github.com/paritytech/parity-ethereum/pull/9884)) +- Fix json tracer overflow ([#9873](https://github.com/paritytech/parity-ethereum/pull/9873)) +- Allow to seal work on latest block ([#9876](https://github.com/paritytech/parity-ethereum/pull/9876)) +- Fix docker script ([#9854](https://github.com/paritytech/parity-ethereum/pull/9854)) +- Health endpoint ([#9847](https://github.com/paritytech/parity-ethereum/pull/9847)) +- Gitlab-ci: make android release build succeed ([#9743](https://github.com/paritytech/parity-ethereum/pull/9743)) +- Clean up existing benchmarks ([#9839](https://github.com/paritytech/parity-ethereum/pull/9839)) +- Update Callisto block reward code to support HF1 ([#9811](https://github.com/paritytech/parity-ethereum/pull/9811)) +- Option to disable keep alive for JSON-RPC http transport ([#9848](https://github.com/paritytech/parity-ethereum/pull/9848)) +- Classic.json Bootnode Update ([#9828](https://github.com/paritytech/parity-ethereum/pull/9828)) +- Support MIX. ([#9767](https://github.com/paritytech/parity-ethereum/pull/9767)) +- Ci: remove failing tests for android, windows, and macos ([#9788](https://github.com/paritytech/parity-ethereum/pull/9788)) +- Implement NoProof for json tests and update tests reference (replaces [#9744](https://github.com/paritytech/parity-ethereum/issues/9744)) ([#9814](https://github.com/paritytech/parity-ethereum/pull/9814)) +- Chore(bump regex) ([#9842](https://github.com/paritytech/parity-ethereum/pull/9842)) +- Ignore global cache for patched accounts ([#9752](https://github.com/paritytech/parity-ethereum/pull/9752)) +- Move state root verification before gas used ([#9841](https://github.com/paritytech/parity-ethereum/pull/9841)) +- Fix(docker-aarch64) : cross-compile config ([#9798](https://github.com/paritytech/parity-ethereum/pull/9798)) +- Version: bump nightly to 2.3.0 ([#9819](https://github.com/paritytech/parity-ethereum/pull/9819)) +- Tests modification for windows CI ([#9671](https://github.com/paritytech/parity-ethereum/pull/9671)) +- Eip-712 implementation ([#9631](https://github.com/paritytech/parity-ethereum/pull/9631)) +- Fix typo ([#9826](https://github.com/paritytech/parity-ethereum/pull/9826)) +- Clean up serde rename and use rename_all = camelCase when possible ([#9823](https://github.com/paritytech/parity-ethereum/pull/9823)) diff --git a/docs/CHANGELOG-2.4.md b/docs/CHANGELOG-2.4.md new file mode 100644 index 0000000000..ad7fc373d9 --- /dev/null +++ b/docs/CHANGELOG-2.4.md @@ -0,0 +1,128 @@ +## Parity-Ethereum [v2.4.9](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.9) + +Parity Ethereum v2.4.9-stable is a security update which addresses servo/rust-smallvec#148 + +The full list of included changes: + +* cargo update -p smallvec ([#10822](https://github.com/paritytech/parity-ethereum/pull/10822)) + +## Parity-Ethereum [v2.4.8](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.8) + +Parity-Ethereum 2.4.8-stable is a bugfix release that improves performance and stability. + +* Blockchain: fix reset chain +* State tests: treat empty accounts the same as non-existant accounts (EIP 1052) +* Aura: fix Timestamp Overflow +* Networking: support discovery-only peers (geth bootnodes) +* Snapshotting: fix unclean shutdown while snappshotting is under way + +The full list of included changes: + +* ethcore/res: activate atlantis classic hf on block 8772000 ([#10766](https://github.com/paritytech/parity-ethereum/pull/10766)) +* fix docker tags for publishing ([#10741](https://github.com/paritytech/parity-ethereum/pull/10741)) +* Reset blockchain properly ([#10669](https://github.com/paritytech/parity-ethereum/pull/10669)) +* adds rpc error message for --no-ancient-blocks ([#10608](https://github.com/paritytech/parity-ethereum/pull/10608)) +* Treat empty account the same as non-exist accounts in EIP-1052 ([#10775](https://github.com/paritytech/parity-ethereum/pull/10775)) +* fix: aura don't add `SystemTime::now()` ([#10720](https://github.com/paritytech/parity-ethereum/pull/10720)) +* DevP2p: Get node IP address and udp port from Socket, if not included in PING packet ([#10705](https://github.com/paritytech/parity-ethereum/pull/10705)) +* Revert "fix: aura don't add `SystemTime::now()` ([#10720](https://github.com/paritytech/parity-ethereum/pull/10720))" +* Add a way to signal shutdown to snapshotting threads ([#10744](https://github.com/paritytech/parity-ethereum/pull/10744)) + +## Parity-Ethereum [v2.4.7](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.7) + +Parity-Ethereum 2.4.7-stable is a bugfix release that improves performance and stability. + +Among others, it enables the _Atlantis_ hardfork on **Morden** and **Kotti** Classic networks. + +The full list of included changes: + +* [CI] allow cargo audit to fail ([#10676](https://github.com/paritytech/parity-ethereum/pull/10676)) +* new image ([#10673](https://github.com/paritytech/parity-ethereum/pull/10673)) +* Update publishing ([#10644](https://github.com/paritytech/parity-ethereum/pull/10644)) +* enable lto for release builds ([#10717](https://github.com/paritytech/parity-ethereum/pull/10717)) +* Use RUSTFLAGS to set the optimization level ([#10719](https://github.com/paritytech/parity-ethereum/pull/10719)) +* ethcore: enable ECIP-1054 for classic ([#10731](https://github.com/paritytech/parity-ethereum/pull/10731)) + +## Parity-Ethereum [v2.4.6](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.6) + +Parity-Ethereum 2.4.6-stable is a bugfix release that improves performance and stability. + +Among others, it enables the Petersburg hardfork on **Rinkeby** and **POA-Core** Network, as well as the **Kovan** Network community hardfork. + +The full list of included changes: + +* ci: publish docs debug ([#10638](https://github.com/paritytech/parity-ethereum/pull/10638)) + +## Parity-Ethereum [v2.4.5](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.5) + +Parity-Ethereum 2.4.5-stable is a bugfix release that improves performance and stability. This release improves memory optimizations around timestamp handling and stabilizes the 2.4 release branch. + +As of today, Parity-Ethereum 2.3 reaches end of life and everyone is encouraged to upgrade. + +## Parity-Ethereum [v2.4.4](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.4) + +Parity-Ethereum 2.4.4-beta is a bugfix release that improves performance and stability. This patch release removes the dead chain configs for Easthub and Ethereum Social. + +The full list of included changes: + +* fix(rpc-types): replace uint and hash with `ethereum_types v0.4` ([#10217](https://github.com/paritytech/parity-ethereum/pull/10217)) +* chore(bump ethereum-types) ([#10396](https://github.com/paritytech/parity-ethereum/pull/10396)) +* fix(light eth_gasPrice): ask network if not in cache ([#10535](https://github.com/paritytech/parity-ethereum/pull/10535)) +* fix(light account response): update `tx_queue` ([#10545](https://github.com/paritytech/parity-ethereum/pull/10545)) +* fix(bump dependencies) ([#10540](https://github.com/paritytech/parity-ethereum/pull/10540)) +* tx-pool: check transaction readiness before replacing ([#10526](https://github.com/paritytech/parity-ethereum/pull/10526)) +* fix #10390 ([#10391](https://github.com/paritytech/parity-ethereum/pull/10391)) +* private-tx: replace error_chain ([#10510](https://github.com/paritytech/parity-ethereum/pull/10510)) + +## Parity-Ethereum [v2.4.3](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.3) + +Parity-Ethereum 2.4.3-beta is a bugfix release that improves performance and stability. This patch release contains a critical bug fix where serving light clients previously led to client crashes. Upgrading is highly recommended. + +The full list of included changes: + +* Add additional request tests ([#10503](https://github.com/paritytech/parity-ethereum/pull/10503)) + +## Parity-Ethereum [v2.4.2](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.2) + +Parity-Ethereum 2.4.2-beta is a bugfix release that improves performance and stability. + +The full list of included changes: + +* Сaching through docker volume ([#10477](https://github.com/paritytech/parity-ethereum/pull/10477)) +* fix win&mac build ([#10486](https://github.com/paritytech/parity-ethereum/pull/10486)) +* fix(extract `timestamp_checked_add` as lib) ([#10383](https://github.com/paritytech/parity-ethereum/pull/10383)) + +## Parity-Ethereum [v2.4.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.1) + +Parity-Ethereum 2.4.1-beta is a bugfix release that improves performance and stability. + +The full list of included changes: + +* Implement parity_versionInfo & parity_setChain on LC; fix parity_setChain ([#10312](https://github.com/paritytech/parity-ethereum/pull/10312)) +* CI publish to aws ([#10446](https://github.com/paritytech/parity-ethereum/pull/10446)) +* CI aws git checkout ([#10451](https://github.com/paritytech/parity-ethereum/pull/10451)) +* Revert "CI aws git checkout ([#10451](https://github.com/paritytech/parity-ethereum/pull/10451))" (#10456) +* Revert "CI aws git checkout ([#10451](https://github.com/paritytech/parity-ethereum/pull/10451))" +* Tests parallelized ([#10452](https://github.com/paritytech/parity-ethereum/pull/10452)) +* Ensure static validator set changes are recognized ([#10467](https://github.com/paritytech/parity-ethereum/pull/10467)) + +## Parity-Ethereum [v2.4.0](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.0) + +Parity-Ethereum 2.4.0-beta is our trifortnightly minor version release coming with a lot of new features as well as bugfixes and performance improvements. + +Notable changes: +- Account management is now deprecated ([#10213](https://github.com/paritytech/parity-ethereum/pull/10213)) +- Local accounts can now be specified via CLI ([#9960](https://github.com/paritytech/parity-ethereum/pull/9960)) +- Chains can now be reset to a particular block via CLI ([#9782](https://github.com/paritytech/parity-ethereum/pull/9782)) +- Ethash now additionally implements ProgPoW ([#9762](https://github.com/paritytech/parity-ethereum/pull/9762)) +- The `eip1283DisableTransition` flag was added to revert EIP-1283 ([#10214](https://github.com/paritytech/parity-ethereum/pull/10214)) + +The full list of included changes: + +* revert some changes, could be buggy ([#10399](https://github.com/paritytech/parity-ethereum/pull/10399)) +* 10000 > 5000 ([#10422](https://github.com/paritytech/parity-ethereum/pull/10422)) +* fix panic when logging directory does not exist, closes #10420 ([#10424](https://github.com/paritytech/parity-ethereum/pull/10424)) +* fix underflow in pip, closes #10419 ([#10423](https://github.com/paritytech/parity-ethereum/pull/10423)) +* ci: clean up gitlab-ci.yml leftovers from previous merge ([#10429](https://github.com/paritytech/parity-ethereum/pull/10429)) +* Update hardcoded headers for Foundation, Ropsten, Kovan and Classic ([#10417](https://github.com/paritytech/parity-ethereum/pull/10417)) + diff --git a/ethash/Cargo.toml b/ethash/Cargo.toml index 5ebafb4537..59d26e128e 100644 --- a/ethash/Cargo.toml +++ b/ethash/Cargo.toml @@ -1,4 +1,5 @@ [package] +description = "Parity Ethereum Ethash & ProgPoW Implementations" name = "ethash" version = "1.12.0" authors = ["Parity Technologies "] @@ -14,9 +15,19 @@ parking_lot = "0.7" primal = "0.2.3" [dev-dependencies] -tempdir = "0.3" criterion = "0.2" +rustc-hex = "1.0" +serde_json = "1.0" +tempdir = "0.3" + +[features] +default = [] +bench = [] [[bench]] name = "basic" harness = false + +[[bench]] +name = "progpow" +harness = false diff --git a/ethash/benches/basic.rs b/ethash/benches/basic.rs index dcfc266b39..5bc10e948e 100644 --- a/ethash/benches/basic.rs +++ b/ethash/benches/basic.rs @@ -40,28 +40,28 @@ criterion_main!(basic); fn bench_light_compute_memmap(b: &mut Criterion) { use std::env; - let builder = NodeCacheBuilder::new(OptimizeFor::Memory); + let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value()); let light = builder.light(&env::temp_dir(), 486382); - b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| light.compute(&HASH, NONCE))); + b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| light.compute(&HASH, NONCE, u64::max_value()))); } fn bench_light_compute_memory(b: &mut Criterion) { use std::env; - let builder = NodeCacheBuilder::new(OptimizeFor::Cpu); + let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value()); let light = builder.light(&env::temp_dir(), 486382); - b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| light.compute(&HASH, NONCE))); + b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| light.compute(&HASH, NONCE, u64::max_value()))); } fn bench_light_new_round_trip_memmap(b: &mut Criterion) { use std::env; b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| { - let builder = NodeCacheBuilder::new(OptimizeFor::Memory); + let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value()); let light = builder.light(&env::temp_dir(), 486382); - light.compute(&HASH, NONCE); + light.compute(&HASH, NONCE, u64::max_value()); })); } @@ -69,9 +69,9 @@ fn bench_light_new_round_trip_memory(b: &mut Criterion) { use std::env; b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| { - let builder = NodeCacheBuilder::new(OptimizeFor::Cpu); + let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value()); let light = builder.light(&env::temp_dir(), 486382); - light.compute(&HASH, NONCE); + light.compute(&HASH, NONCE, u64::max_value()); })); } @@ -81,15 +81,15 @@ fn bench_light_from_file_round_trip_memory(b: &mut Criterion) { let dir = env::temp_dir(); let height = 486382; { - let builder = NodeCacheBuilder::new(OptimizeFor::Cpu); + let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value()); let mut dummy = builder.light(&dir, height); dummy.to_file().unwrap(); } b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| { - let builder = NodeCacheBuilder::new(OptimizeFor::Cpu); + let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value()); let light = builder.light_from_file(&dir, 486382).unwrap(); - light.compute(&HASH, NONCE); + light.compute(&HASH, NONCE, u64::max_value()); })); } @@ -100,14 +100,14 @@ fn bench_light_from_file_round_trip_memmap(b: &mut Criterion) { let height = 486382; { - let builder = NodeCacheBuilder::new(OptimizeFor::Memory); + let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value()); let mut dummy = builder.light(&dir, height); dummy.to_file().unwrap(); } b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| { - let builder = NodeCacheBuilder::new(OptimizeFor::Memory); + let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value()); let light = builder.light_from_file(&dir, 486382).unwrap(); - light.compute(&HASH, NONCE); + light.compute(&HASH, NONCE, u64::max_value()); })); } diff --git a/ethash/benches/progpow.rs b/ethash/benches/progpow.rs new file mode 100644 index 0000000000..e086a14b42 --- /dev/null +++ b/ethash/benches/progpow.rs @@ -0,0 +1,86 @@ +#[macro_use] +extern crate criterion; +extern crate ethash; +extern crate rustc_hex; +extern crate tempdir; + +use criterion::Criterion; +use ethash::progpow; + +use tempdir::TempDir; +use rustc_hex::FromHex; +use ethash::{NodeCacheBuilder, OptimizeFor}; +use ethash::compute::light_compute; + +fn bench_hashimoto_light(c: &mut Criterion) { + let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value()); + let tempdir = TempDir::new("").unwrap(); + let light = builder.light(&tempdir.path(), 1); + let h = FromHex::from_hex("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f").unwrap(); + let mut hash = [0; 32]; + hash.copy_from_slice(&h); + + c.bench_function("hashimoto_light", move |b| { + b.iter(|| light_compute(&light, &hash, 0)) + }); +} + +fn bench_progpow_light(c: &mut Criterion) { + let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value()); + let tempdir = TempDir::new("").unwrap(); + let cache = builder.new_cache(tempdir.into_path(), 0); + + let h = FromHex::from_hex("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f").unwrap(); + let mut hash = [0; 32]; + hash.copy_from_slice(&h); + + c.bench_function("progpow_light", move |b| { + b.iter(|| { + let c_dag = progpow::generate_cdag(cache.as_ref()); + progpow::progpow( + hash, + 0, + 0, + cache.as_ref(), + &c_dag, + ); + }) + }); +} + +fn bench_progpow_optimal_light(c: &mut Criterion) { + let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value()); + let tempdir = TempDir::new("").unwrap(); + let cache = builder.new_cache(tempdir.into_path(), 0); + let c_dag = progpow::generate_cdag(cache.as_ref()); + + let h = FromHex::from_hex("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f").unwrap(); + let mut hash = [0; 32]; + hash.copy_from_slice(&h); + + c.bench_function("progpow_optimal_light", move |b| { + b.iter(|| { + progpow::progpow( + hash, + 0, + 0, + cache.as_ref(), + &c_dag, + ); + }) + }); +} + +fn bench_keccak_f800_long(c: &mut Criterion) { + c.bench_function("keccak_f800_long(0, 0, 0)", |b| { + b.iter(|| progpow::keccak_f800_long([0; 32], 0, [0; 8])) + }); +} + +criterion_group!(benches, + bench_hashimoto_light, + bench_progpow_light, + bench_progpow_optimal_light, + bench_keccak_f800_long, +); +criterion_main!(benches); diff --git a/ethash/res/progpow_testvectors.json b/ethash/res/progpow_testvectors.json new file mode 100644 index 0000000000..2939f7106c --- /dev/null +++ b/ethash/res/progpow_testvectors.json @@ -0,0 +1,86 @@ +[ + [ + 0, + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000", + "faeb1be51075b03a4ff44b335067951ead07a3b078539ace76fd56fc410557a3", + "63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b" + ], + [ + 49, + "63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b", + "0000000006ff2c47", + "c789c1180f890ec555ff42042913465481e8e6bc512cb981e1c1108dc3f2227d", + "9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd922" + ], + [ + 50, + "9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd922", + "00000000076e482e", + "c7340542c2a06b3a7dc7222635f7cd402abf8b528ae971ddac6bbe2b0c7cb518", + "de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188d" + ], + [ + 99, + "de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188d", + "000000003917afab", + "f5e60b2c5bfddd136167a30cbc3c8dbdbd15a512257dee7964e0bc6daa9f8ba7", + "ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcce" + ], + [ + 29950, + "ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcce", + "005d409dbc23a62a", + "07393d15805eb08ee6fc6cb3ad4ad1010533bd0ff92d6006850246829f18fd6e", + "e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f5" + ], + [ + 29999, + "e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f5", + "005db5fa4c2a3d03", + "7551bddf977491da2f6cfc1679299544b23483e8f8ee0931c4c16a796558a0b8", + "d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c6454" + ], + [ + 30000, + "d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c6454", + "005db8607994ff30", + "f1c2c7c32266af9635462e6ce1c98ebe4e7e3ecab7a38aaabfbf2e731e0fbff4", + "8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef64" + ], + [ + 30049, + "8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef64", + "005e2e215a8ca2e7", + "57fe6a9fbf920b4e91deeb66cb0efa971e08229d1a160330e08da54af0689add", + "c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe09047" + ], + [ + 30050, + "c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe09047", + "005e30899481055e", + "ba30c61cc5a2c74a5ecaf505965140a08f24a296d687e78720f0b48baf712f2d", + "ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc71" + ], + [ + 30099, + "ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc71", + "005ea6aef136f88b", + "cfd5e46048cd133d40f261fe8704e51d3f497fc14203ac6a9ef6a0841780b1cd", + "49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd6" + ], + [ + 59950, + "49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd6", + "02ebe0503bd7b1da", + "21511fbaa31fb9f5fc4998a754e97b3083a866f4de86fa7500a633346f56d773", + "f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19cf" + ], + [ + 59999, + "f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19cf", + "02edb6275bd221e3", + "653eda37d337e39d311d22be9bbd3458d3abee4e643bee4a7280a6d08106ef98", + "341562d10d4afb706ec2c8d5537cb0c810de02b4ebb0a0eea5ae335af6fb2e88" + ] +] diff --git a/ethash/src/cache.rs b/ethash/src/cache.rs index 57dbd8cdab..b16d273145 100644 --- a/ethash/src/cache.rs +++ b/ethash/src/cache.rs @@ -69,6 +69,7 @@ pub struct NodeCacheBuilder { // TODO: Remove this locking and just use an `Rc`? seedhash: Arc>, optimize_for: OptimizeFor, + progpow_transition: u64, } // TODO: Abstract the "optimize for" logic @@ -82,17 +83,18 @@ pub struct NodeCache { impl NodeCacheBuilder { pub fn light(&self, cache_dir: &Path, block_number: u64) -> Light { - Light::new_with_builder(self, cache_dir, block_number) + Light::new_with_builder(self, cache_dir, block_number, self.progpow_transition) } pub fn light_from_file(&self, cache_dir: &Path, block_number: u64) -> io::Result { - Light::from_file_with_builder(self, cache_dir, block_number) + Light::from_file_with_builder(self, cache_dir, block_number, self.progpow_transition) } - pub fn new>>(optimize_for: T) -> Self { + pub fn new>>(optimize_for: T, progpow_transition: u64) -> Self { NodeCacheBuilder { seedhash: Arc::new(Mutex::new(SeedHashCompute::default())), optimize_for: optimize_for.into().unwrap_or_default(), + progpow_transition } } diff --git a/ethash/src/compute.rs b/ethash/src/compute.rs index 63762f3a82..36826121db 100644 --- a/ethash/src/compute.rs +++ b/ethash/src/compute.rs @@ -21,6 +21,7 @@ use keccak::{keccak_512, keccak_256, H256}; use cache::{NodeCache, NodeCacheBuilder}; +use progpow::{CDag, generate_cdag, progpow, keccak_f800_short, keccak_f800_long}; use seed_compute::SeedHashCompute; use shared::*; use std::io; @@ -30,7 +31,7 @@ use std::path::Path; const MIX_WORDS: usize = ETHASH_MIX_BYTES / 4; const MIX_NODES: usize = MIX_WORDS / NODE_WORDS; -const FNV_PRIME: u32 = 0x01000193; +pub const FNV_PRIME: u32 = 0x01000193; /// Computation result pub struct ProofOfWork { @@ -40,9 +41,15 @@ pub struct ProofOfWork { pub mix_hash: H256, } +enum Algorithm { + Hashimoto, + Progpow(Box), +} + pub struct Light { block_number: u64, cache: NodeCache, + algorithm: Algorithm, } /// Light cache structure @@ -51,32 +58,55 @@ impl Light { builder: &NodeCacheBuilder, cache_dir: &Path, block_number: u64, + progpow_transition: u64, ) -> Self { let cache = builder.new_cache(cache_dir.to_path_buf(), block_number); - Light { - block_number: block_number, - cache: cache, - } + let algorithm = if block_number >= progpow_transition { + Algorithm::Progpow(Box::new(generate_cdag(cache.as_ref()))) + } else { + Algorithm::Hashimoto + }; + + Light { block_number, cache, algorithm } } /// Calculate the light boundary data /// `header_hash` - The header hash to pack into the mix /// `nonce` - The nonce to pack into the mix - pub fn compute(&self, header_hash: &H256, nonce: u64) -> ProofOfWork { - light_compute(self, header_hash, nonce) + pub fn compute(&self, header_hash: &H256, nonce: u64, block_number: u64) -> ProofOfWork { + match self.algorithm { + Algorithm::Progpow(ref c_dag) => { + let (value, mix_hash) = progpow( + *header_hash, + nonce, + block_number, + self.cache.as_ref(), + c_dag, + ); + + ProofOfWork { value, mix_hash } + }, + Algorithm::Hashimoto => light_compute(self, header_hash, nonce), + } + } pub fn from_file_with_builder( builder: &NodeCacheBuilder, cache_dir: &Path, block_number: u64, + progpow_transition: u64, ) -> io::Result { let cache = builder.from_file(cache_dir.to_path_buf(), block_number)?; - Ok(Light { - block_number: block_number, - cache: cache, - }) + + let algorithm = if block_number >= progpow_transition { + Algorithm::Progpow(Box::new(generate_cdag(cache.as_ref()))) + } else { + Algorithm::Hashimoto + }; + + Ok(Light { block_number, cache, algorithm }) } pub fn to_file(&mut self) -> io::Result<&Path> { @@ -99,27 +129,32 @@ fn fnv_hash(x: u32, y: u32) -> u32 { /// `nonce` The block's nonce /// `mix_hash` The mix digest hash /// Boundary recovered from mix hash -pub fn quick_get_difficulty(header_hash: &H256, nonce: u64, mix_hash: &H256) -> H256 { +pub fn quick_get_difficulty(header_hash: &H256, nonce: u64, mix_hash: &H256, progpow: bool) -> H256 { unsafe { - // This is safe - the `keccak_512` call below reads the first 40 bytes (which we explicitly set - // with two `copy_nonoverlapping` calls) but writes the first 64, and then we explicitly write - // the next 32 bytes before we read the whole thing with `keccak_256`. - // - // This cannot be elided by the compiler as it doesn't know the implementation of - // `keccak_512`. - let mut buf: [u8; 64 + 32] = mem::uninitialized(); - - ptr::copy_nonoverlapping(header_hash.as_ptr(), buf.as_mut_ptr(), 32); - ptr::copy_nonoverlapping(&nonce as *const u64 as *const u8, buf[32..].as_mut_ptr(), 8); - - keccak_512::unchecked(buf.as_mut_ptr(), 64, buf.as_ptr(), 40); - ptr::copy_nonoverlapping(mix_hash.as_ptr(), buf[64..].as_mut_ptr(), 32); - - // This is initialized in `keccak_256` - let mut hash: [u8; 32] = mem::uninitialized(); - keccak_256::unchecked(hash.as_mut_ptr(), hash.len(), buf.as_ptr(), buf.len()); - - hash + if progpow { + let seed = keccak_f800_short(*header_hash, nonce, [0u32; 8]); + keccak_f800_long(*header_hash, seed, mem::transmute(*mix_hash)) + } else { + // This is safe - the `keccak_512` call below reads the first 40 bytes (which we explicitly set + // with two `copy_nonoverlapping` calls) but writes the first 64, and then we explicitly write + // the next 32 bytes before we read the whole thing with `keccak_256`. + // + // This cannot be elided by the compiler as it doesn't know the implementation of + // `keccak_512`. + let mut buf: [u8; 64 + 32] = mem::uninitialized(); + + ptr::copy_nonoverlapping(header_hash.as_ptr(), buf.as_mut_ptr(), 32); + ptr::copy_nonoverlapping(&nonce as *const u64 as *const u8, buf[32..].as_mut_ptr(), 8); + + keccak_512::unchecked(buf.as_mut_ptr(), 64, buf.as_ptr(), 40); + ptr::copy_nonoverlapping(mix_hash.as_ptr(), buf[64..].as_mut_ptr(), 32); + + // This is initialized in `keccak_256` + let mut hash: [u8; 32] = mem::uninitialized(); + keccak_256::unchecked(hash.as_mut_ptr(), hash.len(), buf.as_ptr(), buf.len()); + + hash + } } } @@ -272,7 +307,7 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64) // We overwrite the second half since `keccak_256` has an internal buffer and so allows // overlapping arrays as input. let write_ptr: *mut u8 = &mut buf.compress_bytes as *mut [u8; 32] as *mut u8; - unsafe { + unsafe { keccak_256::unchecked( write_ptr, buf.compress_bytes.len(), @@ -287,7 +322,7 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64) } // TODO: Use the `simd` crate -fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node { +pub fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node { let num_parent_nodes = cache.len(); let mut ret = cache[node_index as usize % num_parent_nodes].clone(); ret.as_words_mut()[0] ^= node_index; @@ -361,13 +396,13 @@ mod test { 0x4a, 0x8e, 0x95, 0x69, 0xef, 0xc7, 0xd7, 0x1b, 0x33, 0x35, 0xdf, 0x36, 0x8c, 0x9a, 0xe9, 0x7e, 0x53, 0x84, ]; - assert_eq!(quick_get_difficulty(&hash, nonce, &mix_hash)[..], boundary_good[..]); + assert_eq!(quick_get_difficulty(&hash, nonce, &mix_hash, false)[..], boundary_good[..]); let boundary_bad = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3a, 0x9b, 0x6c, 0x69, 0xbc, 0x2c, 0xe2, 0xa2, 0x4a, 0x8e, 0x95, 0x69, 0xef, 0xc7, 0xd7, 0x1b, 0x33, 0x35, 0xdf, 0x36, 0x8c, 0x9a, 0xe9, 0x7e, 0x53, 0x84, ]; - assert!(quick_get_difficulty(&hash, nonce, &mix_hash)[..] != boundary_bad[..]); + assert!(quick_get_difficulty(&hash, nonce, &mix_hash, false)[..] != boundary_bad[..]); } #[test] @@ -391,7 +426,7 @@ mod test { let tempdir = TempDir::new("").unwrap(); // difficulty = 0x085657254bd9u64; - let light = NodeCacheBuilder::new(None).light(tempdir.path(), 486382); + let light = NodeCacheBuilder::new(None, u64::max_value()).light(tempdir.path(), 486382); let result = light_compute(&light, &hash, nonce); assert_eq!(result.mix_hash[..], mix_hash[..]); assert_eq!(result.value[..], boundary[..]); @@ -400,7 +435,7 @@ mod test { #[test] fn test_drop_old_data() { let tempdir = TempDir::new("").unwrap(); - let builder = NodeCacheBuilder::new(None); + let builder = NodeCacheBuilder::new(None, u64::max_value()); let first = builder.light(tempdir.path(), 0).to_file().unwrap().to_owned(); let second = builder.light(tempdir.path(), ETHASH_EPOCH_LENGTH).to_file().unwrap().to_owned(); diff --git a/ethash/src/lib.rs b/ethash/src/lib.rs index d6cfa04572..e40c08920c 100644 --- a/ethash/src/lib.rs +++ b/ethash/src/lib.rs @@ -25,15 +25,30 @@ extern crate crunchy; #[macro_use] extern crate log; +#[cfg(test)] +extern crate rustc_hex; + +#[cfg(test)] +extern crate serde_json; + #[cfg(test)] extern crate tempdir; +#[cfg(feature = "bench")] +pub mod compute; +#[cfg(not(feature = "bench"))] mod compute; + mod seed_compute; mod cache; mod keccak; mod shared; +#[cfg(feature = "bench")] +pub mod progpow; +#[cfg(not(feature = "bench"))] +mod progpow; + pub use cache::{NodeCacheBuilder, OptimizeFor}; pub use compute::{ProofOfWork, quick_get_difficulty, slow_hash_block_number}; use compute::Light; @@ -59,14 +74,16 @@ pub struct EthashManager { nodecache_builder: NodeCacheBuilder, cache: Mutex, cache_dir: PathBuf, + progpow_transition: u64, } impl EthashManager { /// Create a new new instance of ethash manager - pub fn new>>(cache_dir: &Path, optimize_for: T) -> EthashManager { + pub fn new>>(cache_dir: &Path, optimize_for: T, progpow_transition: u64) -> EthashManager { EthashManager { cache_dir: cache_dir.to_path_buf(), - nodecache_builder: NodeCacheBuilder::new(optimize_for.into().unwrap_or_default()), + nodecache_builder: NodeCacheBuilder::new(optimize_for.into().unwrap_or_default(), progpow_transition), + progpow_transition: progpow_transition, cache: Mutex::new(LightCache { recent_epoch: None, recent: None, @@ -85,27 +102,33 @@ impl EthashManager { let epoch = block_number / ETHASH_EPOCH_LENGTH; let light = { let mut lights = self.cache.lock(); - let light = match lights.recent_epoch.clone() { - Some(ref e) if *e == epoch => lights.recent.clone(), - _ => match lights.prev_epoch.clone() { - Some(e) if e == epoch => { - // don't swap if recent is newer. - if lights.recent_epoch > lights.prev_epoch { - None - } else { - // swap - let t = lights.prev_epoch; - lights.prev_epoch = lights.recent_epoch; - lights.recent_epoch = t; - let t = lights.prev.clone(); - lights.prev = lights.recent.clone(); - lights.recent = t; - lights.recent.clone() + let light = if block_number == self.progpow_transition { + // we need to regenerate the cache to trigger algorithm change to progpow inside `Light` + None + } else { + match lights.recent_epoch.clone() { + Some(ref e) if *e == epoch => lights.recent.clone(), + _ => match lights.prev_epoch.clone() { + Some(e) if e == epoch => { + // don't swap if recent is newer. + if lights.recent_epoch > lights.prev_epoch { + None + } else { + // swap + let t = lights.prev_epoch; + lights.prev_epoch = lights.recent_epoch; + lights.recent_epoch = t; + let t = lights.prev.clone(); + lights.prev = lights.recent.clone(); + lights.recent = t; + lights.recent.clone() + } } - } - _ => None, - }, + _ => None, + }, + } }; + match light { None => { let light = match self.nodecache_builder.light_from_file( @@ -132,7 +155,7 @@ impl EthashManager { Some(light) => light, } }; - light.compute(header_hash, nonce) + light.compute(header_hash, nonce, block_number) } } @@ -164,7 +187,7 @@ fn test_lru() { use tempdir::TempDir; let tempdir = TempDir::new("").unwrap(); - let ethash = EthashManager::new(tempdir.path(), None); + let ethash = EthashManager::new(tempdir.path(), None, u64::max_value()); let hash = [0u8; 32]; ethash.compute_light(1, &hash, 1); ethash.compute_light(50000, &hash, 1); diff --git a/ethash/src/progpow.rs b/ethash/src/progpow.rs new file mode 100644 index 0000000000..038f38c225 --- /dev/null +++ b/ethash/src/progpow.rs @@ -0,0 +1,595 @@ +// Copyright 2015-2019 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 compute::{FNV_PRIME, calculate_dag_item}; +use keccak::H256; +use shared::{ETHASH_ACCESSES, ETHASH_MIX_BYTES, Node, get_data_size}; + +const PROGPOW_CACHE_BYTES: usize = 16 * 1024; +const PROGPOW_CACHE_WORDS: usize = PROGPOW_CACHE_BYTES / 4; +const PROGPOW_CNT_CACHE: usize = 12; +const PROGPOW_CNT_MATH: usize = 20; +const PROGPOW_CNT_DAG: usize = ETHASH_ACCESSES; +const PROGPOW_DAG_LOADS: usize = 4; +const PROGPOW_MIX_BYTES: usize = 2 * ETHASH_MIX_BYTES; +const PROGPOW_PERIOD_LENGTH: usize = 50; // blocks per progpow epoch (N) +const PROGPOW_LANES: usize = 16; +const PROGPOW_REGS: usize = 32; + +const FNV_HASH: u32 = 0x811c9dc5; + +const KECCAKF_RNDC: [u32; 24] = [ + 0x00000001, 0x00008082, 0x0000808a, 0x80008000, 0x0000808b, 0x80000001, + 0x80008081, 0x00008009, 0x0000008a, 0x00000088, 0x80008009, 0x8000000a, + 0x8000808b, 0x0000008b, 0x00008089, 0x00008003, 0x00008002, 0x00000080, + 0x0000800a, 0x8000000a, 0x80008081, 0x00008080, 0x80000001, 0x80008008 +]; + +const KECCAKF_ROTC: [u32; 24] = [ + 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, + 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 +]; + +const KECCAKF_PILN: [usize; 24] = [ + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 +]; + +fn keccak_f800_round(st: &mut [u32; 25], r: usize) { + // Theta + let mut bc = [0u32; 5]; + for i in 0..bc.len() { + bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20]; + } + + for i in 0..bc.len() { + let t = bc[(i + 4) % 5] ^ bc[(i + 1) % 5].rotate_left(1); + for j in (0..st.len()).step_by(5) { + st[j + i] ^= t; + } + } + + // Rho Pi + let mut t = st[1]; + + debug_assert_eq!(KECCAKF_ROTC.len(), 24); + for i in 0..24 { + let j = KECCAKF_PILN[i]; + bc[0] = st[j]; + st[j] = t.rotate_left(KECCAKF_ROTC[i]); + t = bc[0]; + } + + // Chi + for j in (0..st.len()).step_by(5) { + for i in 0..bc.len() { + bc[i] = st[j + i]; + } + for i in 0..bc.len() { + st[j + i] ^= (!bc[(i + 1) % 5]) & bc[(i + 2) % 5]; + } + } + + // Iota + debug_assert!(r < KECCAKF_RNDC.len()); + st[0] ^= KECCAKF_RNDC[r]; +} + +fn keccak_f800(header_hash: H256, nonce: u64, result: [u32; 8], st: &mut [u32; 25]) { + for i in 0..8 { + st[i] = (header_hash[4 * i] as u32) + + ((header_hash[4 * i + 1] as u32) << 8) + + ((header_hash[4 * i + 2] as u32) << 16) + + ((header_hash[4 * i + 3] as u32) << 24); + } + + st[8] = nonce as u32; + st[9] = (nonce >> 32) as u32; + + for i in 0..8 { + st[10 + i] = result[i]; + } + + for r in 0..22 { + keccak_f800_round(st, r); + } +} + +pub fn keccak_f800_short(header_hash: H256, nonce: u64, result: [u32; 8]) -> u64 { + let mut st = [0u32; 25]; + keccak_f800(header_hash, nonce, result, &mut st); + (st[0].swap_bytes() as u64) << 32 | st[1].swap_bytes() as u64 +} + +pub fn keccak_f800_long(header_hash: H256, nonce: u64, result: [u32; 8]) -> H256 { + let mut st = [0u32; 25]; + keccak_f800(header_hash, nonce, result, &mut st); + + // NOTE: transmute from `[u32; 8]` to `[u8; 32]` + unsafe { + std::mem::transmute( + [st[0], st[1], st[2], st[3], st[4], st[5], st[6], st[7]] + ) + } +} + +#[inline] +fn fnv1a_hash(h: u32, d: u32) -> u32 { + (h ^ d).wrapping_mul(FNV_PRIME) +} + +#[derive(Clone)] +struct Kiss99 { + z: u32, + w: u32, + jsr: u32, + jcong: u32, +} + +impl Kiss99 { + fn new(z: u32, w: u32, jsr: u32, jcong: u32) -> Kiss99 { + Kiss99 { z, w, jsr, jcong } + } + + #[inline] + fn next_u32(&mut self) -> u32 { + self.z = 36969u32.wrapping_mul(self.z & 65535).wrapping_add(self.z >> 16); + self.w = 18000u32.wrapping_mul(self.w & 65535).wrapping_add(self.w >> 16); + let mwc = (self.z << 16).wrapping_add(self.w); + self.jsr ^= self.jsr << 17; + self.jsr ^= self.jsr >> 13; + self.jsr ^= self.jsr << 5; + self.jcong = 69069u32.wrapping_mul(self.jcong).wrapping_add(1234567); + + (mwc ^ self.jcong).wrapping_add(self.jsr) + } +} + +fn fill_mix(seed: u64, lane_id: u32) -> [u32; PROGPOW_REGS] { + // Use FNV to expand the per-warp seed to per-lane + // Use KISS to expand the per-lane seed to fill mix + let z = fnv1a_hash(FNV_HASH, seed as u32); + let w = fnv1a_hash(z, (seed >> 32) as u32); + let jsr = fnv1a_hash(w, lane_id); + let jcong = fnv1a_hash(jsr, lane_id); + + let mut rnd = Kiss99::new(z, w, jsr, jcong); + + let mut mix = [0; PROGPOW_REGS]; + + debug_assert_eq!(PROGPOW_REGS, 32); + for i in 0..32 { + mix[i] = rnd.next_u32(); + } + + mix +} + +// Merge new data from b into the value in a. Assuming A has high entropy only +// do ops that retain entropy even if B is low entropy (IE don't do A&B) +fn merge(a: u32, b: u32, r: u32) -> u32 { + match r % 4 { + 0 => a.wrapping_mul(33).wrapping_add(b), + 1 => (a ^ b).wrapping_mul(33), + 2 => a.rotate_left(((r >> 16) % 31) + 1) ^ b, + _ => a.rotate_right(((r >> 16) % 31) + 1) ^ b, + } +} + +fn math(a: u32, b: u32, r: u32) -> u32 { + match r % 11 { + 0 => a.wrapping_add(b), + 1 => a.wrapping_mul(b), + 2 => ((a as u64).wrapping_mul(b as u64) >> 32) as u32, + 3 => a.min(b), + 4 => a.rotate_left(b), + 5 => a.rotate_right(b), + 6 => a & b, + 7 => a | b, + 8 => a ^ b, + 9 => a.leading_zeros() + b.leading_zeros(), + _ => a.count_ones() + b.count_ones(), + } +} + +fn progpow_init(seed: u64) -> (Kiss99, [u32; PROGPOW_REGS], [u32; PROGPOW_REGS]) { + let z = fnv1a_hash(FNV_HASH, seed as u32); + let w = fnv1a_hash(z, (seed >> 32) as u32); + let jsr = fnv1a_hash(w, seed as u32); + let jcong = fnv1a_hash(jsr, (seed >> 32) as u32); + + let mut rnd = Kiss99::new(z, w, jsr, jcong); + + // Create a random sequence of mix destinations for merge() and mix sources + // for cache reads guarantees every destination merged once and guarantees + // no duplicate cache reads, which could be optimized away. Uses + // Fisher-Yates shuffle. + let mut mix_seq_dst = [0u32; PROGPOW_REGS]; + let mut mix_seq_cache = [0u32; PROGPOW_REGS]; + for i in 0..mix_seq_dst.len() { + mix_seq_dst[i] = i as u32; + mix_seq_cache[i] = i as u32; + } + + for i in (1..mix_seq_dst.len()).rev() { + let j = rnd.next_u32() as usize % (i + 1); + mix_seq_dst.swap(i, j); + + let j = rnd.next_u32() as usize % (i + 1); + mix_seq_cache.swap(i, j); + } + + (rnd, mix_seq_dst, mix_seq_cache) +} + +pub type CDag = [u32; PROGPOW_CACHE_WORDS]; + +fn progpow_loop( + seed: u64, + loop_: usize, + mix: &mut [[u32; PROGPOW_REGS]; PROGPOW_LANES], + cache: &[Node], + c_dag: &CDag, + data_size: usize, +) { + // All lanes share a base address for the global load. Global offset uses + // mix[0] to guarantee it depends on the load result. + let g_offset = mix[loop_ % PROGPOW_LANES][0] as usize % + (64 * data_size / (PROGPOW_LANES * PROGPOW_DAG_LOADS)); + + // 256 bytes of dag data + let mut dag_item = [0u32; 64]; + + // Fetch DAG nodes (64 bytes each) + for l in 0..PROGPOW_DAG_LOADS { + let index = g_offset * PROGPOW_LANES * PROGPOW_DAG_LOADS + l * 16; + let node = calculate_dag_item(index as u32 / 16, cache); + dag_item[l * 16..(l + 1) * 16].clone_from_slice(node.as_words()); + } + + let (rnd, mix_seq_dst, mix_seq_cache) = progpow_init(seed); + + // Lanes can execute in parallel and will be convergent + for l in 0..mix.len() { + let mut rnd = rnd.clone(); + + // Initialize the seed and mix destination sequence + let mut mix_seq_dst_cnt = 0; + let mut mix_seq_cache_cnt = 0; + + let mut mix_dst = || { + let res = mix_seq_dst[mix_seq_dst_cnt % PROGPOW_REGS] as usize; + mix_seq_dst_cnt += 1; + res + }; + let mut mix_cache = || { + let res = mix_seq_cache[mix_seq_cache_cnt % PROGPOW_REGS] as usize; + mix_seq_cache_cnt += 1; + res + }; + + for i in 0..PROGPOW_CNT_CACHE.max(PROGPOW_CNT_MATH) { + if i < PROGPOW_CNT_CACHE { + // Cached memory access, lanes access random 32-bit locations + // within the first portion of the DAG + let offset = mix[l][mix_cache()] as usize % PROGPOW_CACHE_WORDS; + let data = c_dag[offset]; + let dst = mix_dst(); + + mix[l][dst] = merge(mix[l][dst], data, rnd.next_u32()); + } + + if i < PROGPOW_CNT_MATH { + // Random math + // Generate 2 unique sources + let src_rnd = rnd.next_u32() % (PROGPOW_REGS * (PROGPOW_REGS - 1)) as u32; + let src1 = src_rnd % PROGPOW_REGS as u32; // 0 <= src1 < PROGPOW_REGS + let mut src2 = src_rnd / PROGPOW_REGS as u32; // 0 <= src2 < PROGPOW_REGS - 1 + if src2 >= src1 { + src2 += 1; // src2 is now any reg other than src1 + } + + let data = math(mix[l][src1 as usize], mix[l][src2 as usize], rnd.next_u32()); + let dst = mix_dst(); + + mix[l][dst] = merge(mix[l][dst], data, rnd.next_u32()); + } + } + + // Global load to sequential locations + let mut data_g = [0u32; PROGPOW_DAG_LOADS]; + let index = ((l ^ loop_) % PROGPOW_LANES) * PROGPOW_DAG_LOADS; + for i in 0..PROGPOW_DAG_LOADS { + data_g[i] = dag_item[index + i]; + } + + // Consume the global load data at the very end of the loop to allow + // full latency hiding. Always merge into `mix[0]` to feed the offset + // calculation. + mix[l][0] = merge(mix[l][0], data_g[0], rnd.next_u32()); + for i in 1..PROGPOW_DAG_LOADS { + let dst = mix_dst(); + mix[l][dst] = merge(mix[l][dst], data_g[i], rnd.next_u32()); + } + } +} + +pub fn progpow( + header_hash: H256, + nonce: u64, + block_number: u64, + cache: &[Node], + c_dag: &CDag, +) -> (H256, H256) { + let mut mix = [[0u32; PROGPOW_REGS]; PROGPOW_LANES]; + let mut lane_results = [0u32; PROGPOW_LANES]; + let mut result = [0u32; 8]; + + let data_size = get_data_size(block_number) / PROGPOW_MIX_BYTES; + + // NOTE: This assert is required to aid the optimizer elide the non-zero + // remainder check in `progpow_loop`. + assert!(data_size > 0); + + // Initialize mix for all lanes + let seed = keccak_f800_short(header_hash, nonce, result); + + for l in 0..mix.len() { + mix[l] = fill_mix(seed, l as u32); + } + + // Execute the randomly generated inner loop + let period = block_number / PROGPOW_PERIOD_LENGTH as u64; + for i in 0..PROGPOW_CNT_DAG { + progpow_loop( + period, + i, + &mut mix, + cache, + c_dag, + data_size, + ); + } + + // Reduce mix data to a single per-lane result + for l in 0..lane_results.len() { + lane_results[l] = FNV_HASH; + for i in 0..PROGPOW_REGS { + lane_results[l] = fnv1a_hash(lane_results[l], mix[l][i]); + } + } + + // Reduce all lanes to a single 128-bit result + result = [FNV_HASH; 8]; + for l in 0..PROGPOW_LANES { + result[l % 8] = fnv1a_hash(result[l % 8], lane_results[l]); + } + + let digest = keccak_f800_long(header_hash, seed, result); + + // NOTE: transmute from `[u32; 8]` to `[u8; 32]` + let result = unsafe { ::std::mem::transmute(result) }; + + (digest, result) +} + +pub fn generate_cdag(cache: &[Node]) -> CDag { + let mut c_dag = [0u32; PROGPOW_CACHE_WORDS]; + + for i in 0..PROGPOW_CACHE_WORDS / 16 { + let node = calculate_dag_item(i as u32, cache); + for j in 0..16 { + c_dag[i * 16 + j] = node.as_words()[j]; + } + } + + c_dag +} + +#[cfg(test)] +mod test { + use tempdir::TempDir; + + use cache::{NodeCacheBuilder, OptimizeFor}; + use keccak::H256; + use rustc_hex::FromHex; + use serde_json::{self, Value}; + use std::collections::VecDeque; + use super::*; + + fn h256(hex: &str) -> H256 { + let bytes = FromHex::from_hex(hex).unwrap(); + let mut res = [0; 32]; + res.copy_from_slice(&bytes); + res + } + + #[test] + fn test_cdag() { + let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value()); + let tempdir = TempDir::new("").unwrap(); + let cache = builder.new_cache(tempdir.into_path(), 0); + + let c_dag = generate_cdag(cache.as_ref()); + + let expected = vec![ + 690150178u32, 1181503948, 2248155602, 2118233073, 2193871115, + 1791778428, 1067701239, 724807309, 530799275, 3480325829, 3899029234, + 1998124059, 2541974622, 1100859971, 1297211151, 3268320000, 2217813733, + 2690422980, 3172863319, 2651064309 + ]; + + assert_eq!( + c_dag.iter().take(20).cloned().collect::>(), + expected, + ); + } + + #[test] + fn test_random_merge() { + let tests = [ + (1000000u32, 101u32, 33000101u32), + (2000000, 102, 66003366), + (3000000, 103, 6000103), + (4000000, 104, 2000104), + (1000000, 0, 33000000), + (2000000, 0, 66000000), + (3000000, 0, 6000000), + (4000000, 0, 2000000), + ]; + + for (i, &(a, b, expected)) in tests.iter().enumerate() { + assert_eq!( + merge(a, b, i as u32), + expected, + ); + } + } + + #[test] + fn test_random_math() { + let tests = [ + (20u32, 22u32, 42u32), + (70000, 80000, 1305032704), + (70000, 80000, 1), + (1, 2, 1), + (3, 10000, 196608), + (3, 0, 3), + (3, 6, 2), + (3, 6, 7), + (3, 6, 5), + (0, 0xffffffff, 32), + (3 << 13, 1 << 5, 3), + (22, 20, 42), + (80000, 70000, 1305032704), + (80000, 70000, 1), + (2, 1, 1), + (10000, 3, 80000), + (0, 3, 0), + (6, 3, 2), + (6, 3, 7), + (6, 3, 5), + (0, 0xffffffff, 32), + (3 << 13, 1 << 5, 3), + ]; + + for (i, &(a, b, expected)) in tests.iter().enumerate() { + assert_eq!( + math(a, b, i as u32), + expected, + ); + } + } + + #[test] + fn test_keccak_256() { + let expected = "5dd431e5fbc604f499bfa0232f45f8f142d0ff5178f539e5a7800bf0643697af"; + assert_eq!( + keccak_f800_long([0; 32], 0, [0; 8]), + h256(expected), + ); + } + + #[test] + fn test_keccak_64() { + let expected: u64 = 0x5dd431e5fbc604f4; + assert_eq!( + keccak_f800_short([0; 32], 0, [0; 8]), + expected, + ); + } + + #[test] + fn test_progpow_hash() { + let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value()); + let tempdir = TempDir::new("").unwrap(); + let cache = builder.new_cache(tempdir.into_path(), 0); + let c_dag = generate_cdag(cache.as_ref()); + + let header_hash = [0; 32]; + + let (digest, result) = progpow( + header_hash, + 0, + 0, + cache.as_ref(), + &c_dag, + ); + + let expected_digest = FromHex::from_hex("63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b").unwrap(); + let expected_result = FromHex::from_hex("faeb1be51075b03a4ff44b335067951ead07a3b078539ace76fd56fc410557a3").unwrap(); + + assert_eq!( + digest.to_vec(), + expected_digest, + ); + + assert_eq!( + result.to_vec(), + expected_result, + ); + } + + #[test] + fn test_progpow_testvectors() { + struct ProgpowTest { + block_number: u64, + header_hash: H256, + nonce: u64, + mix_hash: H256, + final_hash: H256, + } + + let tests: Vec> = + serde_json::from_slice(include_bytes!("../res/progpow_testvectors.json")).unwrap(); + + let tests: Vec = tests.into_iter().map(|mut test: VecDeque| { + assert!(test.len() == 5); + + let block_number: u64 = serde_json::from_value(test.pop_front().unwrap()).unwrap(); + let header_hash: String = serde_json::from_value(test.pop_front().unwrap()).unwrap(); + let nonce: String = serde_json::from_value(test.pop_front().unwrap()).unwrap(); + let mix_hash: String = serde_json::from_value(test.pop_front().unwrap()).unwrap(); + let final_hash: String = serde_json::from_value(test.pop_front().unwrap()).unwrap(); + + ProgpowTest { + block_number, + header_hash: h256(&header_hash), + nonce: u64::from_str_radix(&nonce, 16).unwrap(), + mix_hash: h256(&mix_hash), + final_hash: h256(&final_hash), + } + }).collect(); + + for test in tests { + let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value()); + let tempdir = TempDir::new("").unwrap(); + let cache = builder.new_cache(tempdir.path().to_owned(), test.block_number); + let c_dag = generate_cdag(cache.as_ref()); + + let (digest, result) = progpow( + test.header_hash, + test.nonce, + test.block_number, + cache.as_ref(), + &c_dag, + ); + + assert_eq!(digest, test.final_hash); + assert_eq!(result, test.mix_hash); + } + } +} diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 6adb69f67a..16013d5479 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -1,5 +1,5 @@ [package] -description = "Ethcore library" +description = "Parity Ethereum (EthCore) Library" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore" @@ -12,7 +12,8 @@ blooms-db = { path = "../util/blooms-db", optional = true } bn = { git = "https://github.com/paritytech/bn", default-features = false } byteorder = "1.0" common-types = { path = "types" } -crossbeam = "0.4" +crossbeam-utils = "0.6" +eip-152 = { version = "0.1", path = "../util/EIP-152" } env_logger = { version = "0.5", optional = true } error-chain = { version = "0.12", default-features = false } ethabi = "6.0" @@ -29,9 +30,8 @@ ethcore-stratum = { path = "../miner/stratum", optional = true } ethereum-types = "0.4" ethjson = { path = "../json" } ethkey = { path = "../accounts/ethkey" } -ethstore = { path = "../accounts/ethstore" } evm = { path = "evm" } -hashdb = "0.3.0" +hash-db = "0.11.0" heapsize = "0.4" itertools = "0.5" journaldb = { path = "../util/journaldb" } @@ -40,24 +40,23 @@ keccak-hasher = { path = "../util/keccak-hasher" } kvdb = "0.1" kvdb-memorydb = "0.1" kvdb-rocksdb = { version = "0.1.3", optional = true } -lazy_static = "1.0" +lazy_static = "1.2.0" len-caching-lock = { path = "../util/len-caching-lock" } log = "0.4" lru-cache = "0.1" macros = { path = "../util/macros" } memory-cache = { path = "../util/memory-cache" } -memorydb = "0.3.0" +memory-db = "0.11.0" num = { version = "0.1", default-features = false, features = ["bigint"] } num_cpus = "1.2" parity-bytes = "0.1" -parity-crypto = "0.2" -parity-machine = { path = "../machine" } +parity-crypto = "0.3.0" parity-snappy = "0.1" parking_lot = "0.7" -patricia-trie = "0.3.0" +trie-db = "0.11.0" patricia-trie-ethereum = { path = "../util/patricia-trie-ethereum" } rand = "0.4" -rayon = "1.0" +rayon = "1.1" rlp = { version = "0.3.0", features = ["ethereum"] } rlp_derive = { path = "../util/rlp-derive" } rustc-hex = "1.0" @@ -65,6 +64,7 @@ serde = "1.0" serde_derive = "1.0" stats = { path = "../util/stats" } tempdir = {version="0.3", optional = true} +time-utils = { path = "../util/time-utils" } trace-time = "0.1" triehash-ethereum = { version = "0.2", path = "../util/triehash-ethereum" } unexpected = { path = "../util/unexpected" } @@ -72,17 +72,15 @@ using_queue = { path = "../miner/using-queue" } vm = { path = "vm" } wasm = { path = "wasm" } -[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))'.dependencies] -hardware-wallet = { path = "../accounts/hw" } - -[target.'cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))'.dependencies] -fake-hardware-wallet = { path = "../accounts/fake-hardware-wallet" } - [dev-dependencies] blooms-db = { path = "../util/blooms-db" } criterion = "0.2" env_logger = "0.5" +ethcore-accounts = { path = "../accounts" } +fetch = { path = "../util/fetch" } +hex-literal = "0.2.1" kvdb-rocksdb = "0.1.3" +parity-runtime = { path = "../util/runtime" } rlp_compress = { path = "../util/rlp-compress" } tempdir = "0.3" trie-standardmap = "0.1" @@ -111,7 +109,7 @@ slow-blocks = [] # Run JSON consensus tests. json-tests = ["env_logger", "test-helpers", "to-pod-full"] # Skip JSON consensus tests with pending issues. -ci-skip-issue = [] +ci-skip-tests = [] # Run memory/cpu heavy tests. test-heavy = [] # Compile test helpers diff --git a/ethcore/blockchain/Cargo.toml b/ethcore/blockchain/Cargo.toml index a263697570..be434c51e1 100644 --- a/ethcore/blockchain/Cargo.toml +++ b/ethcore/blockchain/Cargo.toml @@ -1,5 +1,5 @@ [package] -description = "Ethcore blockchain database" +description = "Parity Ethereum Blockchain Database, Test Generator, Configuration, Caching, Importing Blocks, and Block Information" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore-blockchain" @@ -8,26 +8,28 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -ansi_term = "0.10" +ansi_term = "0.11" blooms-db = { path = "../../util/blooms-db" } common-types = { path = "../types" } ethcore-db = { path = "../db" } ethereum-types = "0.4" heapsize = "0.4" itertools = "0.5" +keccak-hash = "0.1" kvdb = "0.1" log = "0.4" parity-bytes = "0.1" parking_lot = "0.7" -rayon = "1.0" +rand = "0.6" +rayon = "1.1" rlp = { version = "0.3.0", features = ["ethereum"] } rlp_compress = { path = "../../util/rlp-compress" } rlp_derive = { path = "../../util/rlp-derive" } +triehash-ethereum = { version = "0.2", path = "../../util/triehash-ethereum" } [dev-dependencies] env_logger = "0.5" ethkey = { path = "../../accounts/ethkey" } -keccak-hash = "0.1" rustc-hex = "1.0" tempdir = "0.3" kvdb-memorydb = "0.1" diff --git a/ethcore/blockchain/src/blockchain.rs b/ethcore/blockchain/src/blockchain.rs index 88f1503880..c5759d3462 100644 --- a/ethcore/blockchain/src/blockchain.rs +++ b/ethcore/blockchain/src/blockchain.rs @@ -713,6 +713,10 @@ impl BlockChain { /// /// If the tree route verges into pruned or unknown blocks, /// `None` is returned. + /// + /// `is_from_route_finalized` returns whether the `from` part of the + /// route contains a finalized block. This only holds if the two parts (from + /// and to) are on different branches, ie. on 2 different forks. pub fn tree_route(&self, from: H256, to: H256) -> Option { let mut from_branch = vec![]; let mut is_from_route_finalized = false; @@ -726,9 +730,9 @@ impl BlockChain { // reset from && to to the same level while from_details.number > to_details.number { from_branch.push(current_from); + is_from_route_finalized = is_from_route_finalized || from_details.is_finalized; current_from = from_details.parent.clone(); from_details = self.block_details(&from_details.parent)?; - is_from_route_finalized = is_from_route_finalized || from_details.is_finalized; } while to_details.number > from_details.number { @@ -742,9 +746,9 @@ impl BlockChain { // move to shared parent while current_from != current_to { from_branch.push(current_from); + is_from_route_finalized = is_from_route_finalized || from_details.is_finalized; current_from = from_details.parent.clone(); from_details = self.block_details(&from_details.parent)?; - is_from_route_finalized = is_from_route_finalized || from_details.is_finalized; to_branch.push(current_to); current_to = to_details.parent.clone(); @@ -854,6 +858,14 @@ impl BlockChain { } } + /// clears all caches for testing purposes + pub fn clear_cache(&self) { + self.block_bodies.write().clear(); + self.block_details.write().clear(); + self.block_hashes.write().clear(); + self.block_headers.write().clear(); + } + /// Update the best ancient block to the given hash, after checking that /// it's directly linked to the currently known best ancient block pub fn update_best_ancient_block(&self, hash: &H256) { @@ -2483,4 +2495,74 @@ mod tests { assert_eq!(bc.epoch_transition_for(fork_hash).unwrap().block_number, 0); } } + + #[test] + fn tree_rout_with_finalization() { + let genesis = BlockBuilder::genesis(); + let a = genesis.add_block(); + // First branch + let a1 = a.add_block_with_random_transactions(); + let a2 = a1.add_block_with_random_transactions(); + let a3 = a2.add_block_with_random_transactions(); + // Second branch + let b1 = a.add_block_with_random_transactions(); + let b2 = b1.add_block_with_random_transactions(); + + let a_hash = a.last().hash(); + let a1_hash = a1.last().hash(); + let a2_hash = a2.last().hash(); + let a3_hash = a3.last().hash(); + let b2_hash = b2.last().hash(); + + let bootstrap_chain = |blocks: Vec<&BlockBuilder>| { + let db = new_db(); + let bc = new_chain(genesis.last().encoded(), db.clone()); + let mut batch = db.key_value().transaction(); + for block in blocks { + insert_block_batch(&mut batch, &bc, block.last().encoded(), vec![]); + bc.commit(); + } + db.key_value().write(batch).unwrap(); + (db, bc) + }; + + let mark_finalized = |block_hash: H256, db: &Arc, bc: &BlockChain| { + let mut batch = db.key_value().transaction(); + bc.mark_finalized(&mut batch, block_hash).unwrap(); + bc.commit(); + db.key_value().write(batch).unwrap(); + }; + + // Case 1: fork, with finalized common ancestor + { + let (db, bc) = bootstrap_chain(vec![&a, &a1, &a2, &a3, &b1, &b2]); + assert_eq!(bc.best_block_hash(), a3_hash); + assert_eq!(bc.block_hash(2).unwrap(), a1_hash); + + mark_finalized(a_hash, &db, &bc); + assert!(!bc.tree_route(a3_hash, b2_hash).unwrap().is_from_route_finalized); + assert!(!bc.tree_route(b2_hash, a3_hash).unwrap().is_from_route_finalized); + } + + // Case 2: fork with a finalized block on a branch + { + let (db, bc) = bootstrap_chain(vec![&a, &a1, &a2, &a3, &b1, &b2]); + assert_eq!(bc.best_block_hash(), a3_hash); + assert_eq!(bc.block_hash(2).unwrap(), a1_hash); + + mark_finalized(a2_hash, &db, &bc); + assert!(bc.tree_route(a3_hash, b2_hash).unwrap().is_from_route_finalized); + assert!(!bc.tree_route(b2_hash, a3_hash).unwrap().is_from_route_finalized); + } + + // Case 3: no-fork, with a finalized block + { + let (db, bc) = bootstrap_chain(vec![&a, &a1, &a2]); + assert_eq!(bc.best_block_hash(), a2_hash); + + mark_finalized(a1_hash, &db, &bc); + assert!(!bc.tree_route(a1_hash, a2_hash).unwrap().is_from_route_finalized); + assert!(!bc.tree_route(a2_hash, a1_hash).unwrap().is_from_route_finalized); + } + } } diff --git a/ethcore/blockchain/src/generator.rs b/ethcore/blockchain/src/generator.rs index 32ec2802df..e5161d4098 100644 --- a/ethcore/blockchain/src/generator.rs +++ b/ethcore/blockchain/src/generator.rs @@ -21,11 +21,13 @@ use ethereum_types::{U256, H256, Bloom}; use common_types::encoded; use common_types::header::Header; -use common_types::transaction::SignedTransaction; +use common_types::transaction::{SignedTransaction, Transaction, Action}; use common_types::view; use common_types::views::BlockView; +use keccak_hash::keccak; use rlp::encode; use rlp_derive::RlpEncodable; +use triehash_ethereum::ordered_trie_root; /// Helper structure, used for encoding blocks. #[derive(Default, Clone, RlpEncodable)] @@ -136,6 +138,29 @@ impl BlockBuilder { }) } + /// Add a block with randomly generated transactions. + #[inline] + pub fn add_block_with_random_transactions(&self) -> Self { + // Maximum of ~50 transactions + let count = rand::random::() as usize / 5; + let transactions = std::iter::repeat_with(|| { + let data_len = rand::random::(); + let data = std::iter::repeat_with(|| rand::random::()) + .take(data_len as usize) + .collect::>(); + Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Create, + value: 100.into(), + data, + }.sign(&keccak("").into(), None) + }).take(count); + + self.add_block_with_transactions(transactions) + } + /// Add a block with given transactions. #[inline] pub fn add_block_with_transactions(&self, transactions: T) -> Self @@ -166,11 +191,15 @@ impl BlockBuilder { let mut block = Block::default(); let metadata = get_metadata(); let block_number = parent_number + 1; + let transactions = metadata.transactions; + let transactions_root = ordered_trie_root(transactions.iter().map(rlp::encode)); + block.header.set_parent_hash(parent_hash); block.header.set_number(block_number); block.header.set_log_bloom(metadata.bloom); block.header.set_difficulty(metadata.difficulty); - block.transactions = metadata.transactions; + block.header.set_transactions_root(transactions_root); + block.transactions = transactions; parent_hash = block.hash(); parent_number = block_number; diff --git a/ethcore/blockchain/src/lib.rs b/ethcore/blockchain/src/lib.rs index 0ee7a5c1c8..3f07a6d807 100644 --- a/ethcore/blockchain/src/lib.rs +++ b/ethcore/blockchain/src/lib.rs @@ -33,5 +33,5 @@ pub use self::cache::CacheSize; pub use self::config::Config; pub use self::import_route::ImportRoute; pub use self::update::ExtrasInsert; -pub use ethcore_db::keys::{BlockReceipts, BlockDetails, TransactionAddress}; +pub use ethcore_db::keys::{BlockReceipts, BlockDetails, TransactionAddress, BlockNumberKey}; pub use common_types::tree_route::TreeRoute; diff --git a/ethcore/call-contract/Cargo.toml b/ethcore/call-contract/Cargo.toml index 068434a1de..7ee9bb7e65 100644 --- a/ethcore/call-contract/Cargo.toml +++ b/ethcore/call-contract/Cargo.toml @@ -1,4 +1,5 @@ [package] +description = "Parity Ethereum (EthCore) Contract Calls and Blockchain Service & Registry Information" name = "ethcore-call-contract" version = "0.1.0" license = "GPL-3.0" diff --git a/ethcore/evm/Cargo.toml b/ethcore/evm/Cargo.toml index cb70c42e42..b5f4d0685f 100644 --- a/ethcore/evm/Cargo.toml +++ b/ethcore/evm/Cargo.toml @@ -1,4 +1,5 @@ [package] +description = "Parity Ethereum Virtual Machine (EVM) Rust Implementation" name = "evm" version = "0.1.0" authors = ["Parity Technologies "] @@ -14,10 +15,12 @@ vm = { path = "../vm" } keccak-hash = "0.1" parking_lot = "0.7" memory-cache = { path = "../../util/memory-cache" } +num-bigint = "0.2" [dev-dependencies] rustc-hex = "1.0" criterion = "0.2" +hex-literal = "0.2.0" [features] evm-debug = [] diff --git a/ethcore/evm/benches/basic.rs b/ethcore/evm/benches/basic.rs index f17ba363a5..c86afcc575 100644 --- a/ethcore/evm/benches/basic.rs +++ b/ethcore/evm/benches/basic.rs @@ -45,7 +45,9 @@ criterion_group!( mem_gas_calculation_same_usize, mem_gas_calculation_same_u256, mem_gas_calculation_increasing_usize, - mem_gas_calculation_increasing_u256 + mem_gas_calculation_increasing_u256, + blockhash_mulmod_small, + blockhash_mulmod_large, ); criterion_main!(basic); @@ -150,6 +152,54 @@ fn mem_gas_calculation_increasing(gas: U256, b: &mut Bencher) { }); } +fn blockhash_mulmod_small(b: &mut Criterion) { + b.bench_function("blockhash_mulmod_small", |b| { + let factory = Factory::default(); + let mut ext = FakeExt::new(); + + let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + + b.iter(|| { + let code = black_box( + "6080604052348015600f57600080fd5b5060005a90505b60c881111560de5760017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095060017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095060017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095060017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095060017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8009505a90506016565b506035806100ed6000396000f3fe6080604052600080fdfea165627a7a72305820bde4a0ac6d0fac28fc879244baf8a6a0eda514bc95fb7ecbcaaebf2556e2687c0029".from_hex().unwrap() + ); + + let mut params = ActionParams::default(); + params.address = address.clone(); + params.gas = U256::from(4_000u64); + params.code = Some(Arc::new(code.clone())); + + let vm = factory.create(params, ext.schedule(), 0); + + result(vm.exec(&mut ext).ok().unwrap()) + }); + }); +} + +fn blockhash_mulmod_large(b: &mut Criterion) { + b.bench_function("blockhash_mulmod_large", |b| { + let factory = Factory::default(); + let mut ext = FakeExt::new(); + + let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + + b.iter(|| { + let code = black_box( + "608060405234801561001057600080fd5b5060005a90505b60c8811115610177577efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08009507efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08009507efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08009507efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08009507efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08009505a9050610017565b506035806101866000396000f3fe6080604052600080fdfea165627a7a72305820dcaec306f67bb96f3044fff25c9af2ec66f01d0954d0656964f046f42f2780670029".from_hex().unwrap() + ); + + let mut params = ActionParams::default(); + params.address = address.clone(); + params.gas = U256::from(4_000u64); + params.code = Some(Arc::new(code.clone())); + + let vm = factory.create(params, ext.schedule(), 0); + + result(vm.exec(&mut ext).ok().unwrap()) + }); + }); +} + fn result(r: Result) -> U256 { match r { Ok(GasLeft::Known(gas_left)) => gas_left, diff --git a/ethcore/evm/src/evm.rs b/ethcore/evm/src/evm.rs index f8a08b2b2e..3c88155f2f 100644 --- a/ethcore/evm/src/evm.rs +++ b/ethcore/evm/src/evm.rs @@ -44,12 +44,18 @@ pub trait Finalize { impl Finalize for Result { fn finalize(self, ext: E) -> Result { match self { - Ok(GasLeft::Known(gas_left)) => Ok(FinalizationResult { gas_left: gas_left, apply_state: true, return_data: ReturnData::empty() }), - Ok(GasLeft::NeedsReturn { gas_left, data, apply_state }) => ext.ret(&gas_left, &data, apply_state).map(|gas_left| FinalizationResult { - gas_left: gas_left, - apply_state: apply_state, - return_data: data, - }), + Ok(GasLeft::Known(gas_left)) => { + Ok(FinalizationResult { + gas_left, + apply_state: true, + return_data: ReturnData::empty() + }) + }, + Ok(GasLeft::NeedsReturn { gas_left, data, apply_state }) => { + ext.ret(&gas_left, &data, apply_state).map(|gas_left| + FinalizationResult { gas_left, apply_state, return_data: data } + ) + }, Err(err) => Err(err), } } diff --git a/ethcore/evm/src/factory.rs b/ethcore/evm/src/factory.rs index 484b2852fe..5dbaf4f829 100644 --- a/ethcore/evm/src/factory.rs +++ b/ethcore/evm/src/factory.rs @@ -47,7 +47,7 @@ impl Factory { /// for caching jump destinations. pub fn new(evm: VMType, cache_size: usize) -> Self { Factory { - evm: evm, + evm, evm_cache: Arc::new(SharedCache::new(cache_size)), } } diff --git a/ethcore/evm/src/instructions.rs b/ethcore/evm/src/instructions.rs index 0cdbb5687d..b0a66c159e 100644 --- a/ethcore/evm/src/instructions.rs +++ b/ethcore/evm/src/instructions.rs @@ -149,6 +149,10 @@ enum_with_from_u8! { DIFFICULTY = 0x44, #[doc = "get the block's gas limit"] GASLIMIT = 0x45, + #[doc = "get chain ID"] + CHAINID = 0x46, + #[doc = "get balance of own account"] + SELFBALANCE = 0x47, #[doc = "remove item from stack"] POP = 0x50, @@ -442,12 +446,7 @@ pub struct InstructionInfo { impl InstructionInfo { /// Create new instruction info. pub fn new(name: &'static str, args: usize, ret: usize, tier: GasPriceTier) -> Self { - InstructionInfo { - name: name, - args: args, - ret: ret, - tier: tier - } + InstructionInfo { name, args, ret, tier } } } @@ -504,6 +503,8 @@ lazy_static! { arr[NUMBER as usize] = Some(InstructionInfo::new("NUMBER", 0, 1, GasPriceTier::Base)); arr[DIFFICULTY as usize] = Some(InstructionInfo::new("DIFFICULTY", 0, 1, GasPriceTier::Base)); arr[GASLIMIT as usize] = Some(InstructionInfo::new("GASLIMIT", 0, 1, GasPriceTier::Base)); + arr[CHAINID as usize] = Some(InstructionInfo::new("CHAINID", 0, 1, GasPriceTier::Base)); + arr[SELFBALANCE as usize] = Some(InstructionInfo::new("SELFBALANCE", 0, 1, GasPriceTier::Low)); arr[POP as usize] = Some(InstructionInfo::new("POP", 1, 0, GasPriceTier::Base)); arr[MLOAD as usize] = Some(InstructionInfo::new("MLOAD", 1, 1, GasPriceTier::VeryLow)); arr[MSTORE as usize] = Some(InstructionInfo::new("MSTORE", 2, 0, GasPriceTier::VeryLow)); diff --git a/ethcore/evm/src/interpreter/gasometer.rs b/ethcore/evm/src/interpreter/gasometer.rs index 26fec2d937..b90540d9e9 100644 --- a/ethcore/evm/src/interpreter/gasometer.rs +++ b/ethcore/evm/src/interpreter/gasometer.rs @@ -121,6 +121,9 @@ impl Gasometer { Request::Gas(Gas::from(1)) }, instructions::SSTORE => { + if schedule.eip1706 && self.current_gas <= Gas::from(schedule.call_stipend) { + return Err(vm::Error::OutOfGas); + } let address = H256::from(stack.peek(0)); let newval = stack.peek(1); let val = U256::from(&*ext.storage_at(&address)?); diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index d699e61cbe..21e7b463b2 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -28,7 +28,8 @@ use std::{cmp, mem}; use std::sync::Arc; use hash::keccak; use bytes::Bytes; -use ethereum_types::{U256, U512, H256, Address}; +use ethereum_types::{U256, H256, Address}; +use num_bigint::BigUint; use vm::{ self, ActionParams, ParamsType, ActionValue, CallType, MessageCallResult, @@ -61,6 +62,17 @@ const TWO_POW_96: U256 = U256([0, 0x100000000, 0, 0]); //0x1 00000000 00000000 0 const TWO_POW_224: U256 = U256([0, 0, 0, 0x100000000]); //0x1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 const TWO_POW_248: U256 = U256([0, 0, 0, 0x100000000000000]); //0x1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000000 +fn to_biguint(x: U256) -> BigUint { + let mut bytes = [0u8; 32]; + x.to_little_endian(&mut bytes); + BigUint::from_bytes_le(&bytes) +} + +fn from_biguint(x: BigUint) -> U256 { + let bytes = x.to_bytes_le(); + U256::from_little_endian(&bytes) +} + /// Abstraction over raw vector of Bytes. Easier state management of PC. struct CodeReader { position: ProgramCounter, @@ -107,8 +119,6 @@ enum InstructionResult { Trap(TrapKind), } -enum Never {} - /// ActionParams without code, so that it can be feed into CodeReader. #[derive(Debug)] struct InterpreterParams { @@ -166,12 +176,6 @@ pub enum InterpreterResult { Trap(TrapKind), } -impl From for InterpreterResult { - fn from(error: vm::Error) -> InterpreterResult { - InterpreterResult::Done(Err(error)) - } -} - /// Intepreter EVM implementation pub struct Interpreter { mem: Vec, @@ -282,6 +286,8 @@ impl Interpreter { cache, params, reader, informant, valid_jump_destinations, gasometer, stack, done: false, + // Overridden in `step_inner` based on + // the result of `ext.trace_next_instruction`. do_trace: true, mem: Vec::new(), return_data: ReturnData::empty(), @@ -302,21 +308,26 @@ impl Interpreter { let result = if self.gasometer.is_none() { InterpreterResult::Done(Err(vm::Error::OutOfGas)) } else if self.reader.len() == 0 { - InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_ref().expect("Gasometer None case is checked above; qed").current_gas.as_u256()))) + let current_gas = self.gasometer + .as_ref() + .expect("Gasometer None case is checked above; qed") + .current_gas + .as_u256(); + InterpreterResult::Done(Ok(GasLeft::Known(current_gas))) } else { - self.step_inner(ext).err().expect("step_inner never returns Ok(()); qed") + self.step_inner(ext) }; if let &InterpreterResult::Done(_) = &result { self.done = true; self.informant.done(); } - return result; + result } /// Inner helper function for step. #[inline(always)] - fn step_inner(&mut self, ext: &mut vm::Ext) -> Result { + fn step_inner(&mut self, ext: &mut dyn vm::Ext) -> InterpreterResult { let result = match self.resume_result.take() { Some(result) => result, None => { @@ -331,22 +342,31 @@ impl Interpreter { let instruction = match instruction { Some(i) => i, - None => return Err(InterpreterResult::Done(Err(vm::Error::BadInstruction { + None => return InterpreterResult::Done(Err(vm::Error::BadInstruction { instruction: opcode - }))), + })), }; let info = instruction.info(); self.last_stack_ret_len = info.ret; - self.verify_instruction(ext, instruction, info)?; + if let Err(e) = self.verify_instruction(ext, instruction, info) { + return InterpreterResult::Done(Err(e)); + }; // Calculate gas cost - let requirements = self.gasometer.as_mut().expect(GASOMETER_PROOF).requirements(ext, instruction, info, &self.stack, self.mem.size())?; + let requirements = match self.gasometer.as_mut().expect(GASOMETER_PROOF).requirements(ext, instruction, info, &self.stack, self.mem.size()) { + Ok(t) => t, + Err(e) => return InterpreterResult::Done(Err(e)), + }; if self.do_trace { ext.trace_prepare_execute(self.reader.position - 1, opcode, requirements.gas_cost.as_u256(), Self::mem_written(instruction, &self.stack), Self::store_written(instruction, &self.stack)); } - - self.gasometer.as_mut().expect(GASOMETER_PROOF).verify_gas(&requirements.gas_cost)?; + if let Err(e) = self.gasometer.as_mut().expect(GASOMETER_PROOF).verify_gas(&requirements.gas_cost) { + if self.do_trace { + ext.trace_failed(); + } + return InterpreterResult::Done(Err(e)); + } self.mem.expand(requirements.memory_required_size); self.gasometer.as_mut().expect(GASOMETER_PROOF).current_mem_gas = requirements.memory_total_gas; self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas = self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas - requirements.gas_cost; @@ -355,18 +375,24 @@ impl Interpreter { // Execute instruction let current_gas = self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas; - let result = self.exec_instruction( + let result = match self.exec_instruction( current_gas, ext, instruction, requirements.provide_gas - )?; - + ) { + Err(x) => { + if self.do_trace { + ext.trace_failed(); + } + return InterpreterResult::Done(Err(x)); + }, + Ok(x) => x, + }; evm_debug!({ self.informant.after_instruction(instruction) }); - result }, }; if let InstructionResult::Trap(trap) = result { - return Err(InterpreterResult::Trap(trap)); + return InterpreterResult::Trap(trap); } if let InstructionResult::UnusedGas(ref gas) = result { @@ -388,28 +414,31 @@ impl Interpreter { self.valid_jump_destinations = Some(self.cache.jump_destinations(&self.params.code_hash, &self.reader.code)); } let jump_destinations = self.valid_jump_destinations.as_ref().expect("jump_destinations are initialized on first jump; qed"); - let pos = self.verify_jump(position, jump_destinations)?; + let pos = match self.verify_jump(position, jump_destinations) { + Ok(x) => x, + Err(e) => return InterpreterResult::Done(Err(e)) + }; self.reader.position = pos; }, InstructionResult::StopExecutionNeedsReturn {gas, init_off, init_size, apply} => { let mem = mem::replace(&mut self.mem, Vec::new()); - return Err(InterpreterResult::Done(Ok(GasLeft::NeedsReturn { + return InterpreterResult::Done(Ok(GasLeft::NeedsReturn { gas_left: gas.as_u256(), data: mem.into_return_data(init_off, init_size), apply_state: apply - }))); + })); }, InstructionResult::StopExecution => { - return Err(InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256())))); + return InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256()))); }, _ => {}, } if self.reader.position >= self.reader.len() { - return Err(InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256())))); + return InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256()))); } - Err(InterpreterResult::Continue) + InterpreterResult::Continue } fn verify_instruction(&self, ext: &vm::Ext, instruction: Instruction, info: &InstructionInfo) -> vm::Result<()> { @@ -421,7 +450,9 @@ impl Interpreter { ((instruction == instructions::RETURNDATACOPY || instruction == instructions::RETURNDATASIZE) && !schedule.have_return_data) || (instruction == instructions::REVERT && !schedule.have_revert) || ((instruction == instructions::SHL || instruction == instructions::SHR || instruction == instructions::SAR) && !schedule.have_bitwise_shifting) || - (instruction == instructions::EXTCODEHASH && !schedule.have_extcodehash) + (instruction == instructions::EXTCODEHASH && !schedule.have_extcodehash) || + (instruction == instructions::CHAINID && !schedule.have_chain_id) || + (instruction == instructions::SELFBALANCE && !schedule.have_selfbalance) { return Err(vm::Error::BadInstruction { instruction: instruction as u8 @@ -836,6 +867,12 @@ impl Interpreter { instructions::GASLIMIT => { self.stack.push(ext.env_info().gas_limit.clone()); }, + instructions::CHAINID => { + self.stack.push(ext.chain_id().into()) + }, + instructions::SELFBALANCE => { + self.stack.push(ext.balance(&self.params.address)?); + } // Stack instructions @@ -1009,11 +1046,12 @@ impl Interpreter { let c = self.stack.pop_back(); self.stack.push(if !c.is_zero() { - // upcast to 512 - let a5 = U512::from(a); - let res = a5.overflowing_add(U512::from(b)).0; - let x = res % U512::from(c); - U256::from(x) + let a_num = to_biguint(a); + let b_num = to_biguint(b); + let c_num = to_biguint(c); + let res = a_num + b_num; + let x = res % c_num; + from_biguint(x) } else { U256::zero() }); @@ -1024,10 +1062,12 @@ impl Interpreter { let c = self.stack.pop_back(); self.stack.push(if !c.is_zero() { - let a5 = U512::from(a); - let res = a5.overflowing_mul(U512::from(b)).0; - let x = res % U512::from(c); - U256::from(x) + let a_num = to_biguint(a); + let b_num = to_biguint(b); + let c_num = to_biguint(c); + let res = a_num * b_num; + let x = res % c_num; + from_biguint(x) } else { U256::zero() }); diff --git a/ethcore/evm/src/lib.rs b/ethcore/evm/src/lib.rs index 3548a1fe5e..6e9409375b 100644 --- a/ethcore/evm/src/lib.rs +++ b/ethcore/evm/src/lib.rs @@ -24,6 +24,7 @@ extern crate vm; extern crate keccak_hash as hash; extern crate memory_cache; extern crate parity_bytes as bytes; +extern crate num_bigint; #[macro_use] extern crate lazy_static; @@ -33,6 +34,8 @@ extern crate log; #[cfg(test)] extern crate rustc_hex; +#[cfg(test)] +extern crate hex_literal; pub mod evm; pub mod interpreter; diff --git a/ethcore/evm/src/tests.rs b/ethcore/evm/src/tests.rs index dd039311eb..73a176ee09 100644 --- a/ethcore/evm/src/tests.rs +++ b/ethcore/evm/src/tests.rs @@ -25,6 +25,7 @@ use vm::{self, ActionParams, ActionValue, Ext}; use vm::tests::{FakeExt, FakeCall, FakeCallType, test_finalize}; use factory::Factory; use vmtype::VMType; +use hex_literal::hex; evm_test!{test_add: test_add_int} fn test_add(factory: super::Factory) { @@ -108,6 +109,32 @@ fn test_origin(factory: super::Factory) { assert_store(&ext, 0, "000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681"); } +evm_test!{test_selfbalance: test_selfbalance_int} +fn test_selfbalance(factory: super::Factory) { + let own_addr = Address::from_str("1337000000000000000000000000000000000000").unwrap(); + // 47 SELFBALANCE + // 60 ff PUSH ff + // 55 SSTORE + let code = hex!("47 60 ff 55").to_vec(); + + let mut params = ActionParams::default(); + params.address = own_addr.clone(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(code)); + let mut ext = FakeExt::new_istanbul(); + ext.balances = { + let mut x = HashMap::new(); + x.insert(own_addr, U256::from(1_025)); // 0x401 + x + }; + let gas_left = { + let vm = factory.create(params, ext.schedule(), ext.depth()); + test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap() + }; + assert_eq!(gas_left, U256::from(79_992)); // TODO[dvdplm]: do the sums here, SELFBALANCE-5 + PUSH1-3 + ONEBYTE-4 + SSTORE-?? = 100_000 - 79_992 + assert_store(&ext, 0xff, "0000000000000000000000000000000000000000000000000000000000000401"); +} + evm_test!{test_sender: test_sender_int} fn test_sender(factory: super::Factory) { let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); @@ -130,6 +157,27 @@ fn test_sender(factory: super::Factory) { assert_store(&ext, 0, "000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681"); } +evm_test!{test_chain_id: test_chain_id_int} +fn test_chain_id(factory: super::Factory) { + // 46 CHAINID + // 60 00 PUSH 0 + // 55 SSTORE + let code = hex!("46 60 00 55").to_vec(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(code)); + let mut ext = FakeExt::new_istanbul().with_chain_id(9); + + let gas_left = { + let vm = factory.create(params, ext.schedule(), ext.depth()); + test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap() + }; + + assert_eq!(gas_left, U256::from(79_995)); + assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000009"); +} + evm_test!{test_extcodecopy: test_extcodecopy_int} fn test_extcodecopy(factory: super::Factory) { // 33 - sender @@ -262,7 +310,6 @@ fn test_calldataload(factory: super::Factory) { assert_eq!(gas_left, U256::from(79_991)); assert_store(&ext, 0, "23ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23"); - } evm_test!{test_author: test_author_int} diff --git a/ethcore/light/Cargo.toml b/ethcore/light/Cargo.toml index 7e0c8aaebf..bf5866846c 100644 --- a/ethcore/light/Cargo.toml +++ b/ethcore/light/Cargo.toml @@ -1,5 +1,5 @@ [package] -description = "Parity Light Client Implementation" +description = "Parity Ethereum (EthCore) Light Client Implementation (Block Import IO Service, Blockchain Data Fetching, Light Client Header Chain Storage, Parity Light Protocol (PLP) Provider, Light Transaction Queue, CHT Definitions, Light Client Data Cache), Parity Light Protocol (PLP) Implementation, P2P Network I/O and Event Context Generalization, Peer Error Handling & Punishment, Request Load Timer & Distribution Manager, Pending Request Set Storage, Request Credit Management, Light Client Request Types, Request Chain Builder Utility, On-demand Chain Request Service over LES (for RPCs), ResponseGuard Implementation)" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore-light" @@ -14,12 +14,12 @@ ethcore = { path = ".."} ethcore-db = { path = "../db" } ethcore-blockchain = { path = "../blockchain" } ethereum-types = "0.4" -memorydb = "0.3.0" -patricia-trie = "0.3.0" +memory-db = "0.11.0" +trie-db = "0.11.0" patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" } ethcore-network = { path = "../../util/network" } ethcore-io = { path = "../../util/io" } -hashdb = "0.3.0" +hash-db = "0.11.0" heapsize = "0.4" vm = { path = "../vm" } fastmap = { path = "../../util/fastmap" } @@ -41,6 +41,7 @@ triehash-ethereum = { version = "0.2", path = "../../util/triehash-ethereum" } kvdb = "0.1" memory-cache = { path = "../../util/memory-cache" } error-chain = { version = "0.12", default-features = false } +journaldb = { path = "../../util/journaldb" } [dev-dependencies] ethcore = { path = "..", features = ["test-helpers"] } diff --git a/ethcore/light/src/cht.rs b/ethcore/light/src/cht.rs index b1a5049ab0..a9bc5d7f26 100644 --- a/ethcore/light/src/cht.rs +++ b/ethcore/light/src/cht.rs @@ -25,10 +25,11 @@ use common_types::ids::BlockId; use ethereum_types::{H256, U256}; -use hashdb::HashDB; +use hash_db::HashDB; use keccak_hasher::KeccakHasher; use kvdb::DBValue; -use memorydb::MemoryDB; +use memory_db::MemoryDB; +use journaldb::new_memory_db; use bytes::Bytes; use trie::{TrieMut, Trie, Recorder}; use ethtrie::{self, TrieDB, TrieDBMut}; @@ -73,7 +74,8 @@ impl> CHT { if block_to_cht_number(num) != Some(self.number) { return Ok(None) } let mut recorder = Recorder::with_depth(from_level); - let t = TrieDB::new(&self.db, &self.root)?; + let db: &HashDB<_,_> = &self.db; + let t = TrieDB::new(&db, &self.root)?; t.get_with(&key!(num), &mut recorder)?; Ok(Some(recorder.drain().into_iter().map(|x| x.data).collect())) @@ -96,7 +98,7 @@ pub struct BlockInfo { pub fn build(cht_num: u64, mut fetcher: F) -> Option>> where F: FnMut(BlockId) -> Option { - let mut db = MemoryDB::::new(); + let mut db = new_memory_db(); // start from the last block by number and work backwards. let last_num = start_number(cht_num + 1) - 1; @@ -150,7 +152,7 @@ pub fn compute_root(cht_num: u64, iterable: I) -> Option /// verify the given trie branch and extract the canonical hash and total difficulty. // TODO: better support for partially-checked queries. pub fn check_proof(proof: &[Bytes], num: u64, root: H256) -> Option<(H256, U256)> { - let mut db = MemoryDB::::new(); + let mut db = new_memory_db(); for node in proof { db.insert(&node[..]); } let res = match TrieDB::new(&db, &root) { diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index 90ebba39aa..8205ae2ab3 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -116,6 +116,9 @@ pub trait LightChainClient: Send + Sync { /// Query whether a block is known. fn is_known(&self, hash: &H256) -> bool; + /// Set the chain via a spec name. + fn set_spec_name(&self, new_spec_name: String) -> Result<(), ()>; + /// Clear the queue. fn clear_queue(&self); @@ -164,6 +167,8 @@ pub struct Client { listeners: RwLock>>, fetcher: T, verify_full: bool, + /// A closure to call when we want to restart the client + exit_handler: Mutex>>, } impl Client { @@ -190,6 +195,7 @@ impl Client { listeners: RwLock::new(vec![]), fetcher, verify_full: config.verify_full, + exit_handler: Mutex::new(None), }) } @@ -360,6 +366,14 @@ impl Client { self.chain.heap_size_of_children() } + /// Set a closure to call when the client wants to be restarted. + /// + /// The parameter passed to the callback is the name of the new chain spec to use after + /// the restart. + pub fn set_exit_handler(&self, f: F) where F: Fn(String) + 'static + Send { + *self.exit_handler.lock() = Some(Box::new(f)); + } + /// Get a handle to the verification engine. pub fn engine(&self) -> &Arc { &self.engine @@ -563,6 +577,17 @@ impl LightChainClient for Client { Client::engine(self) } + fn set_spec_name(&self, new_spec_name: String) -> Result<(), ()> { + trace!(target: "mode", "Client::set_spec_name({:?})", new_spec_name); + if let Some(ref h) = *self.exit_handler.lock() { + (*h)(new_spec_name); + Ok(()) + } else { + warn!("Not hypervised; cannot change chain."); + Err(()) + } + } + fn is_known(&self, hash: &H256) -> bool { self.status(hash) == BlockStatus::InChain } diff --git a/ethcore/light/src/lib.rs b/ethcore/light/src/lib.rs index db52b95482..93e912e1d6 100644 --- a/ethcore/light/src/lib.rs +++ b/ethcore/light/src/lib.rs @@ -62,14 +62,14 @@ extern crate ethcore_network as network; extern crate parity_bytes as bytes; extern crate ethereum_types; extern crate ethcore; -extern crate hashdb; +extern crate hash_db; extern crate heapsize; extern crate failsafe; extern crate futures; extern crate itertools; extern crate keccak_hasher; -extern crate memorydb; -extern crate patricia_trie as trie; +extern crate memory_db; +extern crate trie_db as trie; extern crate patricia_trie_ethereum as ethtrie; extern crate fastmap; extern crate rand; @@ -92,3 +92,4 @@ extern crate error_chain; extern crate kvdb_memorydb; #[cfg(test)] extern crate tempdir; +extern crate journaldb; diff --git a/ethcore/light/src/on_demand/mod.rs b/ethcore/light/src/on_demand/mod.rs index ff1c980e28..7d1f4fabf8 100644 --- a/ethcore/light/src/on_demand/mod.rs +++ b/ethcore/light/src/on_demand/mod.rs @@ -24,7 +24,6 @@ use std::marker::PhantomData; use std::sync::Arc; use std::time::Duration; -use ethcore::executed::{Executed, ExecutionError}; use futures::{Poll, Future, Async}; use futures::sync::oneshot::{self, Receiver}; use network::PeerId; @@ -41,10 +40,10 @@ use cache::Cache; use request::{self as basic_request, Request as NetworkRequest}; use self::request::CheckedRequest; +pub use ethcore::executed::ExecutionResult; pub use self::request::{Request, Response, HeaderRef, Error as ValidityError}; pub use self::request_guard::{RequestGuard, Error as RequestError}; pub use self::response_guard::{ResponseGuard, Error as ResponseGuardError, Inner as ResponseGuardInner}; - pub use types::request::ResponseError; #[cfg(test)] @@ -54,9 +53,6 @@ pub mod request; mod request_guard; mod response_guard; -/// The result of execution -pub type ExecutionResult = Result; - /// The initial backoff interval for OnDemand queries pub const DEFAULT_REQUEST_MIN_BACKOFF_DURATION: Duration = Duration::from_secs(10); /// The maximum request interval for OnDemand queries @@ -70,6 +66,10 @@ pub const DEFAULT_NUM_CONSECUTIVE_FAILED_REQUESTS: usize = 1; /// OnDemand related errors pub mod error { + // Silence: `use of deprecated item 'std::error::Error::cause': replaced by Error::source, which can support downcasting` + // https://github.com/paritytech/parity-ethereum/issues/10302 + #![allow(deprecated)] + use futures::sync::oneshot::Canceled; error_chain! { @@ -94,6 +94,24 @@ pub mod error { } } +/// Public interface for performing network requests `OnDemand` +pub trait OnDemandRequester: Send + Sync { + /// Submit a strongly-typed batch of requests. + /// + /// Fails if back-reference are not coherent. + fn request(&self, ctx: &BasicContext, requests: T) -> Result, basic_request::NoSuchOutput> + where + T: request::RequestAdapter; + + /// Submit a vector of requests to be processed together. + /// + /// Fails if back-references are not coherent. + /// The returned vector of responses will correspond to the requests exactly. + fn request_raw(&self, ctx: &BasicContext, requests: Vec) + -> Result, basic_request::NoSuchOutput>; +} + + // relevant peer info. #[derive(Debug, Clone, PartialEq, Eq)] struct Peer { @@ -355,71 +373,8 @@ pub struct OnDemand { request_number_of_consecutive_errors: usize } -impl OnDemand { - - /// Create a new `OnDemand` service with the given cache. - pub fn new( - cache: Arc>, - response_time_window: Duration, - request_backoff_start: Duration, - request_backoff_max: Duration, - request_backoff_rounds_max: usize, - request_number_of_consecutive_errors: usize, - ) -> Self { - - Self { - pending: RwLock::new(Vec::new()), - peers: RwLock::new(HashMap::new()), - in_transit: RwLock::new(HashMap::new()), - cache, - no_immediate_dispatch: false, - response_time_window: Self::sanitize_circuit_breaker_input(response_time_window, "Response time window"), - request_backoff_start: Self::sanitize_circuit_breaker_input(request_backoff_start, "Request initial backoff time window"), - request_backoff_max: Self::sanitize_circuit_breaker_input(request_backoff_max, "Request maximum backoff time window"), - request_backoff_rounds_max, - request_number_of_consecutive_errors, - } - } - - fn sanitize_circuit_breaker_input(dur: Duration, name: &'static str) -> Duration { - if dur.as_secs() < 1 { - warn!(target: "on_demand", - "{} is too short must be at least 1 second, configuring it to 1 second", name); - Duration::from_secs(1) - } else { - dur - } - } - - // make a test version: this doesn't dispatch pending requests - // until you trigger it manually. - #[cfg(test)] - fn new_test( - cache: Arc>, - request_ttl: Duration, - request_backoff_start: Duration, - request_backoff_max: Duration, - request_backoff_rounds_max: usize, - request_number_of_consecutive_errors: usize, - ) -> Self { - let mut me = OnDemand::new( - cache, - request_ttl, - request_backoff_start, - request_backoff_max, - request_backoff_rounds_max, - request_number_of_consecutive_errors, - ); - me.no_immediate_dispatch = true; - - me - } - - /// Submit a vector of requests to be processed together. - /// - /// Fails if back-references are not coherent. - /// The returned vector of responses will correspond to the requests exactly. - pub fn request_raw(&self, ctx: &BasicContext, requests: Vec) +impl OnDemandRequester for OnDemand { + fn request_raw(&self, ctx: &BasicContext, requests: Vec) -> Result, basic_request::NoSuchOutput> { let (sender, receiver) = oneshot::channel(); @@ -475,10 +430,7 @@ impl OnDemand { Ok(receiver) } - /// Submit a strongly-typed batch of requests. - /// - /// Fails if back-reference are not coherent. - pub fn request(&self, ctx: &BasicContext, requests: T) -> Result, basic_request::NoSuchOutput> + fn request(&self, ctx: &BasicContext, requests: T) -> Result, basic_request::NoSuchOutput> where T: request::RequestAdapter { self.request_raw(ctx, requests.make_requests()).map(|recv| OnResponses { @@ -487,6 +439,69 @@ impl OnDemand { }) } +} + +impl OnDemand { + + /// Create a new `OnDemand` service with the given cache. + pub fn new( + cache: Arc>, + response_time_window: Duration, + request_backoff_start: Duration, + request_backoff_max: Duration, + request_backoff_rounds_max: usize, + request_number_of_consecutive_errors: usize, + ) -> Self { + + Self { + pending: RwLock::new(Vec::new()), + peers: RwLock::new(HashMap::new()), + in_transit: RwLock::new(HashMap::new()), + cache, + no_immediate_dispatch: false, + response_time_window: Self::sanitize_circuit_breaker_input(response_time_window, "Response time window"), + request_backoff_start: Self::sanitize_circuit_breaker_input(request_backoff_start, "Request initial backoff time window"), + request_backoff_max: Self::sanitize_circuit_breaker_input(request_backoff_max, "Request maximum backoff time window"), + request_backoff_rounds_max, + request_number_of_consecutive_errors, + } + } + + fn sanitize_circuit_breaker_input(dur: Duration, name: &'static str) -> Duration { + if dur.as_secs() < 1 { + warn!(target: "on_demand", + "{} is too short must be at least 1 second, configuring it to 1 second", name); + Duration::from_secs(1) + } else { + dur + } + } + + // make a test version: this doesn't dispatch pending requests + // until you trigger it manually. + #[cfg(test)] + fn new_test( + cache: Arc>, + request_ttl: Duration, + request_backoff_start: Duration, + request_backoff_max: Duration, + request_backoff_rounds_max: usize, + request_number_of_consecutive_errors: usize, + ) -> Self { + let mut me = OnDemand::new( + cache, + request_ttl, + request_backoff_start, + request_backoff_max, + request_backoff_rounds_max, + request_number_of_consecutive_errors, + ); + me.no_immediate_dispatch = true; + + me + } + + // maybe dispatch pending requests. // sometimes fn attempt_dispatch(&self, ctx: &BasicContext) { diff --git a/ethcore/light/src/on_demand/request.rs b/ethcore/light/src/on_demand/request.rs index a2167fa38d..a183dcbcab 100644 --- a/ethcore/light/src/on_demand/request.rs +++ b/ethcore/light/src/on_demand/request.rs @@ -30,9 +30,8 @@ use ethcore::state::{self, ProvedExecution}; use ethereum_types::{H256, U256, Address}; use ethtrie::{TrieError, TrieDB}; use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY, KECCAK_EMPTY_LIST_RLP, keccak}; -use hashdb::HashDB; +use hash_db::HashDB; use kvdb::DBValue; -use memorydb::MemoryDB; use parking_lot::Mutex; use request::{self as net_request, IncompleteRequest, CompleteRequest, Output, OutputKind, Field}; use rlp::{RlpStream, Rlp}; @@ -981,7 +980,7 @@ impl Account { let header = self.header.as_ref()?; let state_root = header.state_root(); - let mut db = MemoryDB::new(); + let mut db = journaldb::new_memory_db(); for node in proof { db.insert(&node[..]); } match TrieDB::new(&db, &state_root).and_then(|t| t.get(&keccak(&self.address)))? { @@ -1101,7 +1100,6 @@ mod tests { use super::*; use std::time::Duration; use ethereum_types::{H256, Address}; - use memorydb::MemoryDB; use parking_lot::Mutex; use trie::{Trie, TrieMut}; use ethtrie::{SecTrieDB, SecTrieDBMut}; @@ -1281,7 +1279,7 @@ mod tests { use rlp::RlpStream; let mut root = H256::default(); - let mut db = MemoryDB::new(); + let mut db = journaldb::new_memory_db(); let mut header = Header::new(); header.set_number(123_456); header.set_extra_data(b"test_header".to_vec()); diff --git a/ethcore/light/src/on_demand/tests.rs b/ethcore/light/src/on_demand/tests.rs index fd0e8b0f97..49ec35f10d 100644 --- a/ethcore/light/src/on_demand/tests.rs +++ b/ethcore/light/src/on_demand/tests.rs @@ -29,7 +29,7 @@ use std::sync::Arc; use std::time::{Duration, Instant}; use std::thread; -use super::{request, OnDemand, Peer, HeaderRef}; +use super::{request, OnDemand, OnDemandRequester, Peer, HeaderRef}; // useful contexts to give the service. enum Context { diff --git a/ethcore/light/src/types/request/batch.rs b/ethcore/light/src/types/request/batch.rs index 6dc75c2497..63641b5daa 100644 --- a/ethcore/light/src/types/request/batch.rs +++ b/ethcore/light/src/types/request/batch.rs @@ -255,4 +255,63 @@ mod tests { hash: Field::BackReference(0, 0), })).unwrap(); } + + #[test] + fn batch_tx_index_backreference() { + let mut builder = Builder::default(); + builder.push(Request::HeaderProof(IncompleteHeaderProofRequest { + num: 100.into(), // header proof puts hash at output 0. + })).unwrap(); + builder.push(Request::TransactionIndex(IncompleteTransactionIndexRequest { + hash: Field::BackReference(0, 0), + })).unwrap(); + + let mut batch = builder.build(); + batch.requests[1].fill(|_req_idx, _out_idx| Ok(Output::Hash(42.into()))); + + assert!(batch.next_complete().is_some()); + batch.answered += 1; + assert!(batch.next_complete().is_some()); + } + + #[test] + fn batch_tx_index_backreference_public_api() { + let mut builder = Builder::default(); + builder.push(Request::HeaderProof(IncompleteHeaderProofRequest { + num: 100.into(), // header proof puts hash at output 0. + })).unwrap(); + builder.push(Request::TransactionIndex(IncompleteTransactionIndexRequest { + hash: Field::BackReference(0, 0), + })).unwrap(); + + let mut batch = builder.build(); + + assert!(batch.next_complete().is_some()); + let hdr_proof_res = header_proof::Response { + proof: vec![], + hash: 12.into(), + td: 21.into(), + }; + batch.supply_response_unchecked(&hdr_proof_res); + + assert!(batch.next_complete().is_some()); + } + + #[test] + fn batch_receipts_backreference() { + let mut builder = Builder::default(); + builder.push(Request::HeaderProof(IncompleteHeaderProofRequest { + num: 100.into(), // header proof puts hash at output 0. + })).unwrap(); + builder.push(Request::Receipts(IncompleteReceiptsRequest { + hash: Field::BackReference(0, 0), + })).unwrap(); + + let mut batch = builder.build(); + batch.requests[1].fill(|_req_idx, _out_idx| Ok(Output::Hash(42.into()))); + + assert!(batch.next_complete().is_some()); + batch.answered += 1; + assert!(batch.next_complete().is_some()); + } } diff --git a/ethcore/light/src/types/request/mod.rs b/ethcore/light/src/types/request/mod.rs index d43aa72636..cacfbcbe50 100644 --- a/ethcore/light/src/types/request/mod.rs +++ b/ethcore/light/src/types/request/mod.rs @@ -907,7 +907,7 @@ pub mod transaction_index { fn fill(&mut self, oracle: F) where F: Fn(usize, usize) -> Result { if let Field::BackReference(req, idx) = self.hash { self.hash = match oracle(req, idx) { - Ok(Output::Number(hash)) => Field::Scalar(hash.into()), + Ok(Output::Hash(hash)) => Field::Scalar(hash.into()), _ => Field::BackReference(req, idx), } } @@ -982,7 +982,7 @@ pub mod block_receipts { fn fill(&mut self, oracle: F) where F: Fn(usize, usize) -> Result { if let Field::BackReference(req, idx) = self.hash { self.hash = match oracle(req, idx) { - Ok(Output::Number(hash)) => Field::Scalar(hash.into()), + Ok(Output::Hash(hash)) => Field::Scalar(hash.into()), _ => Field::BackReference(req, idx), } } diff --git a/ethcore/node-filter/Cargo.toml b/ethcore/node-filter/Cargo.toml index bd18468525..80823290c2 100644 --- a/ethcore/node-filter/Cargo.toml +++ b/ethcore/node-filter/Cargo.toml @@ -1,5 +1,5 @@ [package] -description = "Parity smart network connections" +description = "Parity Smart Contract based Node Filter, Manage Permissions of Network Connections" homepage = "http://parity.io" license = "GPL-3.0" name = "node-filter" diff --git a/ethcore/private-tx/Cargo.toml b/ethcore/private-tx/Cargo.toml index 5151deee44..ae8f83d872 100644 --- a/ethcore/private-tx/Cargo.toml +++ b/ethcore/private-tx/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Parity Technologies "] [dependencies] common-types = { path = "../types" } -error-chain = { version = "0.12", default-features = false } +derive_more = "0.14.0" ethabi = "6.0" ethabi-contract = "6.0" ethabi-derive = "6.0" @@ -24,9 +24,9 @@ heapsize = "0.4" keccak-hash = "0.1.2" log = "0.4" parity-bytes = "0.1" -parity-crypto = "0.2" +parity-crypto = "0.3.0" parking_lot = "0.7" -patricia-trie = "0.3.0" +trie-db = "0.11.0" patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" } rand = "0.3" rlp = { version = "0.3.0", features = ["ethereum"] } @@ -36,7 +36,7 @@ serde = "1.0" serde_derive = "1.0" serde_json = "1.0" tiny-keccak = "1.4" -transaction-pool = "1.13.2" +transaction-pool = "2.0.1" url = "1" [dev-dependencies] diff --git a/ethcore/private-tx/res/keys_acl.json b/ethcore/private-tx/res/keys_acl.json new file mode 100644 index 0000000000..3ec2daf9e9 --- /dev/null +++ b/ethcore/private-tx/res/keys_acl.json @@ -0,0 +1,43 @@ +[ + { + "constant": true, + "inputs": [ + { + "name":"user", + "type":"address" + } + ], + "name": "availableKeys", + "outputs": [ + { + "name": "", + "type": "bytes32[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant":true, + "inputs": [ + { + "name":"user", + "type":"address" + }, + { + "name":"document", + "type":"bytes32" + } + ], + "name":"checkPermissions", + "outputs": [ + { + "name":"", + "type":"bool" + } + ], + "payable":false, + "type":"function" + } +] diff --git a/ethcore/private-tx/src/encryptor.rs b/ethcore/private-tx/src/encryptor.rs index b19a53d29a..6a24cf9300 100644 --- a/ethcore/private-tx/src/encryptor.rs +++ b/ethcore/private-tx/src/encryptor.rs @@ -18,22 +18,23 @@ use std::io::Read; use std::str::FromStr; +use std::sync::Arc; use std::iter::repeat; use std::time::{Instant, Duration}; use std::collections::HashMap; use std::collections::hash_map::Entry; use parking_lot::Mutex; -use ethcore::account_provider::AccountProvider; use ethereum_types::{H128, H256, Address}; use ethjson; -use ethkey::{Signature, Password, Public}; +use ethkey::{Signature, Public}; use crypto; use futures::Future; use fetch::{Fetch, Client as FetchClient, Method, BodyReader, Request}; use bytes::{Bytes, ToPretty}; -use error::{Error, ErrorKind}; +use error::Error; use url::Url; -use super::find_account_password; +use super::Signer; +use super::key_server_keys::address_to_key; /// Initialization vector length. const INIT_VEC_LEN: usize = 16; @@ -47,7 +48,6 @@ pub trait Encryptor: Send + Sync + 'static { fn encrypt( &self, contract_address: &Address, - accounts: &AccountProvider, initialisation_vector: &H128, plain_data: &[u8], ) -> Result; @@ -56,12 +56,11 @@ pub trait Encryptor: Send + Sync + 'static { fn decrypt( &self, contract_address: &Address, - accounts: &AccountProvider, cypher: &[u8], ) -> Result; } -/// Configurtion for key server encryptor +/// Configuration for key server encryptor #[derive(Default, PartialEq, Debug, Clone)] pub struct EncryptorConfig { /// URL to key server @@ -70,8 +69,6 @@ pub struct EncryptorConfig { pub threshold: u32, /// Account used for signing requests to key server pub key_server_account: Option
, - /// Passwords used to unlock accounts - pub passwords: Vec, } struct EncryptionSession { @@ -84,14 +81,20 @@ pub struct SecretStoreEncryptor { config: EncryptorConfig, client: FetchClient, sessions: Mutex>, + signer: Arc, } impl SecretStoreEncryptor { /// Create new encryptor - pub fn new(config: EncryptorConfig, client: FetchClient) -> Result { + pub fn new( + config: EncryptorConfig, + client: FetchClient, + signer: Arc, + ) -> Result { Ok(SecretStoreEncryptor { config, client, + signer, sessions: Mutex::default(), }) } @@ -102,18 +105,17 @@ impl SecretStoreEncryptor { url_suffix: &str, use_post: bool, contract_address: &Address, - accounts: &AccountProvider, ) -> Result { // check if the key was already cached if let Some(key) = self.obtained_key(contract_address) { return Ok(key); } - let contract_address_signature = self.sign_contract_address(contract_address, accounts)?; - let requester = self.config.key_server_account.ok_or_else(|| ErrorKind::KeyServerAccountNotSet)?; + let contract_address_signature = self.sign_contract_address(contract_address)?; + let requester = self.config.key_server_account.ok_or_else(|| Error::KeyServerAccountNotSet)?; // key id in SS is H256 && we have H160 here => expand with assitional zeros let contract_address_extended: H256 = contract_address.into(); - let base_url = self.config.base_url.clone().ok_or_else(|| ErrorKind::KeyServerNotSet)?; + let base_url = self.config.base_url.clone().ok_or_else(|| Error::KeyServerNotSet)?; // prepare request url let url = format!("{}/{}/{}{}", @@ -130,16 +132,16 @@ impl SecretStoreEncryptor { Method::GET }; - let url = Url::from_str(&url).map_err(|e| ErrorKind::Encrypt(e.to_string()))?; + let url = Url::from_str(&url).map_err(|e| Error::Encrypt(e.to_string()))?; let response = self.client.fetch(Request::new(url, method), Default::default()).wait() - .map_err(|e| ErrorKind::Encrypt(e.to_string()))?; + .map_err(|e| Error::Encrypt(e.to_string()))?; if response.is_not_found() { - bail!(ErrorKind::EncryptionKeyNotFound(*contract_address)); + return Err(Error::EncryptionKeyNotFound(*contract_address)); } if !response.is_success() { - bail!(ErrorKind::Encrypt(response.status().canonical_reason().unwrap_or("unknown").into())); + return Err(Error::Encrypt(response.status().canonical_reason().unwrap_or("unknown").into())); } // read HTTP response @@ -147,11 +149,10 @@ impl SecretStoreEncryptor { BodyReader::new(response).read_to_string(&mut result)?; // response is JSON string (which is, in turn, hex-encoded, encrypted Public) - let encrypted_bytes: ethjson::bytes::Bytes = result.trim_matches('\"').parse().map_err(|e| ErrorKind::Encrypt(e))?; - let password = find_account_password(&self.config.passwords, &*accounts, &requester); + let encrypted_bytes: ethjson::bytes::Bytes = result.trim_matches('\"').parse().map_err(|e| Error::Encrypt(e))?; // decrypt Public - let decrypted_bytes = accounts.decrypt(requester, password, &crypto::DEFAULT_MAC, &encrypted_bytes)?; + let decrypted_bytes = self.signer.decrypt(requester, &crypto::DEFAULT_MAC, &encrypted_bytes)?; let decrypted_key = Public::from_slice(&decrypted_bytes); // and now take x coordinate of Public as a key @@ -187,12 +188,9 @@ impl SecretStoreEncryptor { } } - fn sign_contract_address(&self, contract_address: &Address, accounts: &AccountProvider) -> Result { - // key id in SS is H256 && we have H160 here => expand with assitional zeros - let contract_address_extended: H256 = contract_address.into(); - let key_server_account = self.config.key_server_account.ok_or_else(|| ErrorKind::KeyServerAccountNotSet)?; - let password = find_account_password(&self.config.passwords, accounts, &key_server_account); - Ok(accounts.sign(key_server_account, password, H256::from_slice(&contract_address_extended))?) + fn sign_contract_address(&self, contract_address: &Address) -> Result { + let key_server_account = self.config.key_server_account.ok_or_else(|| Error::KeyServerAccountNotSet)?; + Ok(self.signer.sign(key_server_account, address_to_key(contract_address))?) } } @@ -200,16 +198,15 @@ impl Encryptor for SecretStoreEncryptor { fn encrypt( &self, contract_address: &Address, - accounts: &AccountProvider, initialisation_vector: &H128, plain_data: &[u8], ) -> Result { // retrieve the key, try to generate it if it doesn't exist yet - let key = match self.retrieve_key("", false, contract_address, &*accounts) { + let key = match self.retrieve_key("", false, contract_address) { Ok(key) => Ok(key), - Err(Error(ErrorKind::EncryptionKeyNotFound(_), _)) => { + Err(Error::EncryptionKeyNotFound(_)) => { trace!(target: "privatetx", "Key for account wasnt found in sstore. Creating. Address: {:?}", contract_address); - self.retrieve_key(&format!("/{}", self.config.threshold), true, contract_address, &*accounts) + self.retrieve_key(&format!("/{}", self.config.threshold), true, contract_address) } Err(err) => Err(err), }?; @@ -218,7 +215,7 @@ impl Encryptor for SecretStoreEncryptor { let mut cypher = Vec::with_capacity(plain_data.len() + initialisation_vector.len()); cypher.extend(repeat(0).take(plain_data.len())); crypto::aes::encrypt_128_ctr(&key, initialisation_vector, plain_data, &mut cypher) - .map_err(|e| ErrorKind::Encrypt(e.to_string()))?; + .map_err(|e| Error::Encrypt(e.to_string()))?; cypher.extend_from_slice(&initialisation_vector); Ok(cypher) @@ -228,24 +225,23 @@ impl Encryptor for SecretStoreEncryptor { fn decrypt( &self, contract_address: &Address, - accounts: &AccountProvider, cypher: &[u8], ) -> Result { // initialization vector takes INIT_VEC_LEN bytes let cypher_len = cypher.len(); if cypher_len < INIT_VEC_LEN { - bail!(ErrorKind::Decrypt("Invalid cypher".into())); + return Err(Error::Decrypt("Invalid cypher".into())); } // retrieve existing key - let key = self.retrieve_key("", false, contract_address, accounts)?; + let key = self.retrieve_key("", false, contract_address)?; // use symmetric decryption to decrypt document let (cypher, iv) = cypher.split_at(cypher_len - INIT_VEC_LEN); let mut plain_data = Vec::with_capacity(cypher_len - INIT_VEC_LEN); plain_data.extend(repeat(0).take(cypher_len - INIT_VEC_LEN)); crypto::aes::decrypt_128_ctr(&key, &iv, cypher, &mut plain_data) - .map_err(|e| ErrorKind::Decrypt(e.to_string()))?; + .map_err(|e| Error::Decrypt(e.to_string()))?; Ok(plain_data) } } @@ -258,7 +254,6 @@ impl Encryptor for NoopEncryptor { fn encrypt( &self, _contract_address: &Address, - _accounts: &AccountProvider, _initialisation_vector: &H128, data: &[u8], ) -> Result { @@ -268,7 +263,6 @@ impl Encryptor for NoopEncryptor { fn decrypt( &self, _contract_address: &Address, - _accounts: &AccountProvider, data: &[u8], ) -> Result { Ok(data.to_vec()) diff --git a/ethcore/private-tx/src/error.rs b/ethcore/private-tx/src/error.rs index 76a34f9023..eda08b2a56 100644 --- a/ethcore/private-tx/src/error.rs +++ b/ethcore/private-tx/src/error.rs @@ -14,191 +14,182 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +use std::error; +use derive_more::Display; use ethereum_types::Address; use rlp::DecoderError; use ethtrie::TrieError; -use ethcore::account_provider::SignError; use ethcore::error::{Error as EthcoreError, ExecutionError}; use types::transaction::Error as TransactionError; use ethkey::Error as KeyError; -use txpool::Error as TxPoolError; - -error_chain! { - foreign_links { - Io(::std::io::Error) #[doc = "Error concerning the Rust standard library's IO subsystem."]; - Decoder(DecoderError) #[doc = "RLP decoding error."]; - Trie(TrieError) #[doc = "Error concerning TrieDBs."]; - Txpool(TxPoolError) #[doc = "Tx pool error."]; - } - - errors { - #[doc = "Encryption error."] - Encrypt(err: String) { - description("Encryption error"), - display("Encryption error. ({})", err), - } - - #[doc = "Decryption error."] - Decrypt(err: String) { - description("Decryption error"), - display("Decryption error. ({})", err), - } - - #[doc = "Address not authorized."] - NotAuthorised(address: Address) { - description("Address not authorized"), - display("Private transaction execution is not authorised for {}", address), - } - - #[doc = "Transaction creates more than one contract."] - TooManyContracts { - description("Transaction creates more than one contract."), - display("Private transaction created too many contracts"), - } - - #[doc = "Contract call error."] - Call(err: String) { - description("Contract call error."), - display("Contract call error. ({})", err), - } - - #[doc = "State is not available."] - StatePruned { - description("State is not available."), - display("State is not available"), - } - - #[doc = "State is incorrect."] - StateIncorrect { - description("State is incorrect."), - display("State is incorrect"), - } - - #[doc = "Wrong private transaction type."] - BadTransactonType { - description("Wrong private transaction type."), - display("Wrong private transaction type"), - } - - #[doc = "Contract does not exist or was not created."] - ContractDoesNotExist { - description("Contract does not exist or was not created."), - display("Contract does not exist or was not created"), - } - - #[doc = "Reference to the client is corrupted."] - ClientIsMalformed { - description("Reference to the client is corrupted."), - display("Reference to the client is corrupted"), - } - - #[doc = "Queue of private transactions for verification is full."] - QueueIsFull { - description("Queue of private transactions for verification is full."), - display("Queue of private transactions for verification is full"), - } - - #[doc = "The transaction already exists in queue of private transactions."] - PrivateTransactionAlreadyImported { - description("The transaction already exists in queue of private transactions."), - display("The transaction already exists in queue of private transactions."), - } - - #[doc = "The information about private transaction is not found in the store."] - PrivateTransactionNotFound { - description("The information about private transaction is not found in the store."), - display("The information about private transaction is not found in the store."), - } - - #[doc = "Account for signing public transactions not set."] - SignerAccountNotSet { - description("Account for signing public transactions not set."), - display("Account for signing public transactions not set."), - } - - #[doc = "Account for validating private transactions not set."] - ValidatorAccountNotSet { - description("Account for validating private transactions not set."), - display("Account for validating private transactions not set."), - } - - #[doc = "Account for signing requests to key server not set."] - KeyServerAccountNotSet { - description("Account for signing requests to key server not set."), - display("Account for signing requests to key server not set."), - } - - #[doc = "Encryption key is not found on key server."] - EncryptionKeyNotFound(address: Address) { - description("Encryption key is not found on key server"), - display("Encryption key is not found on key server for {}", address), - } - - #[doc = "Key server URL is not set."] - KeyServerNotSet { - description("Key server URL is not set."), - display("Key server URL is not set."), - } - - #[doc = "VM execution error."] - Execution(err: ExecutionError) { - description("VM execution error."), - display("VM execution error {}", err), - } - - #[doc = "General signing error."] - Key(err: KeyError) { - description("General signing error."), - display("General signing error {}", err), - } - - #[doc = "Account provider signing error."] - Sign(err: SignError) { - description("Account provider signing error."), - display("Account provider signing error {}", err), - } +use ethkey::crypto::Error as CryptoError; +use txpool::VerifiedTransaction; +use private_transactions::VerifiedPrivateTransaction; + +type TxPoolError = txpool::Error<::Hash>; + +#[derive(Debug, Display)] +pub enum Error { + /// Error concerning the Rust standard library's IO subsystem. + #[display(fmt = "Io Error: {}", _0)] + Io(::std::io::Error), + /// RLP decoding error. + #[display(fmt = "Decoder Error: {}", _0)] + Decoder(DecoderError), + /// Error concerning TrieDBs. + #[display(fmt = "Trie Error: {}", _0)] + Trie(TrieError), + /// Transaction pool error. + #[display(fmt = "Transaction Pool Error: {}", _0)] + TxPool(TxPoolError), + /// Crypto error. + #[display(fmt = "Crypto Error {}", _0)] + Crypto(CryptoError), + /// Encryption error. + #[display(fmt = "Encryption error. ({})", _0)] + Encrypt(String), + /// Decryption error. + #[display(fmt = "Decryption error. ({})", _0)] + Decrypt(String), + /// Address not authorized. + #[display(fmt = "Private transaction execution is not authorised for {}", _0)] + NotAuthorised(Address), + /// Transaction creates more than one contract. + #[display(fmt = "Private transaction created too many contracts")] + TooManyContracts, + /// Contract call error. + #[display(fmt = "Contract call error. ({})", _0)] + Call(String), + /// State is not available. + #[display(fmt = "State is not available")] + StatePruned, + /// State is incorrect. + #[display(fmt = "State is incorrect")] + StateIncorrect, + /// Wrong private transaction type. + #[display(fmt = "Wrong private transaction type")] + BadTransactionType, + /// Contract does not exist or was not created. + #[display(fmt = "Contract does not exist or was not created")] + ContractDoesNotExist, + /// Reference to the client is corrupted. + #[display(fmt = "Reference to the client is corrupted")] + ClientIsMalformed, + /// Queue of private transactions for verification is full. + #[display(fmt = "Queue of private transactions for verification is full")] + QueueIsFull, + /// The transaction already exists in queue of private transactions. + #[display(fmt = "The transaction already exists in queue of private transactions.")] + PrivateTransactionAlreadyImported, + /// The information about private transaction is not found in the store. + #[display(fmt = "The information about private transaction is not found in the store.")] + PrivateTransactionNotFound, + /// Account for signing public transactions not set. + #[display(fmt = "Account for signing public transactions not set.")] + SignerAccountNotSet, + /// Account for validating private transactions not set. + #[display(fmt = "Account for validating private transactions not set.")] + ValidatorAccountNotSet, + /// Account for signing requests to key server not set. + #[display(fmt = "Account for signing requests to key server not set.")] + KeyServerAccountNotSet, + /// Encryption key is not found on key server. + #[display(fmt = "Encryption key is not found on key server for {}", _0)] + EncryptionKeyNotFound(Address), + /// Key server URL is not set. + #[display(fmt = "Key server URL is not set.")] + KeyServerNotSet, + /// VM execution error. + #[display(fmt = "VM execution error {}", _0)] + Execution(ExecutionError), + /// General signing error. + #[display(fmt = "General signing error {}", _0)] + Key(KeyError), + /// Error of transactions processing. + #[display(fmt = "Error of transactions processing {}", _0)] + Transaction(TransactionError), + /// General ethcore error. + #[display(fmt = "General ethcore error {}", _0)] + Ethcore(EthcoreError), + /// A convenient variant for String. + #[display(fmt = "{}", _0)] + Msg(String), +} - #[doc = "Error of transactions processing."] - Transaction(err: TransactionError) { - description("Error of transactions processing."), - display("Error of transactions processing {}", err), +impl error::Error for Error { + fn source(&self) -> Option<&(error::Error + 'static)> { + match self { + Error::Io(e) => Some(e), + Error::Decoder(e) => Some(e), + Error::Trie(e) => Some(e), + Error::TxPool(e) => Some(e), + Error::Crypto(e) => Some(e), + Error::Execution(e) => Some(e), + Error::Key(e) => Some(e), + Error::Transaction(e) => Some(e), + Error::Ethcore(e) => Some(e), + _ => None, } + } +} - #[doc = "General ethcore error."] - Ethcore(err: EthcoreError) { - description("General ethcore error."), - display("General ethcore error {}", err), - } +impl From for Error { + fn from(s: String) -> Self { + Error::Msg(s) } } -impl From for Error { - fn from(err: SignError) -> Self { - ErrorKind::Sign(err).into() +impl From for Error { + fn from(err: std::io::Error) -> Self { + Error::Io(err).into() } } impl From for Error { fn from(err: KeyError) -> Self { - ErrorKind::Key(err).into() + Error::Key(err).into() + } +} + +impl From for Error { + fn from(err: CryptoError) -> Self { + Error::Crypto(err).into() + } +} + +impl From for Error { + fn from(err: DecoderError) -> Self { + Error::Decoder(err).into() } } impl From for Error { fn from(err: ExecutionError) -> Self { - ErrorKind::Execution(err).into() + Error::Execution(err).into() } } impl From for Error { fn from(err: TransactionError) -> Self { - ErrorKind::Transaction(err).into() + Error::Transaction(err).into() + } +} + +impl From for Error { + fn from(err: TrieError) -> Self { + Error::Trie(err).into() + } +} + +impl From for Error { + fn from(err: TxPoolError) -> Self { + Error::TxPool(err).into() } } impl From for Error { fn from(err: EthcoreError) -> Self { - ErrorKind::Ethcore(err).into() + Error::Ethcore(err).into() } } diff --git a/ethcore/private-tx/src/key_server_keys.rs b/ethcore/private-tx/src/key_server_keys.rs new file mode 100644 index 0000000000..28d9b3cb91 --- /dev/null +++ b/ethcore/private-tx/src/key_server_keys.rs @@ -0,0 +1,173 @@ +// 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 . + +//! Wrapper around key server responsible for access keys processing. + +use std::sync::Arc; +use parking_lot::RwLock; +use ethereum_types::{H256, Address}; +use call_contract::{CallContract, RegistryInfo}; +use ethcore::client::BlockId; +use ethabi::FunctionOutputDecoder; + +const ACL_CHECKER_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_acl_checker"; + +use_contract!(keys_acl_contract, "res/keys_acl.json"); + +/// Returns the address (of the contract), that corresponds to the key +pub fn key_to_address(key: &H256) -> Address { + Address::from_slice(&key.to_vec()[..10]) +} + +/// Returns the key from the key server associated with the contract +pub fn address_to_key(contract_address: &Address) -> H256 { + // Current solution uses contract address extended with 0 as id + let contract_address_extended: H256 = contract_address.into(); + + H256::from_slice(&contract_address_extended) +} + +/// Trait for keys server keys provider. +pub trait KeyProvider: Send + Sync + 'static { + /// Account, that is used for communication with key server + fn key_server_account(&self) -> Option
; + + /// List of keys available for the account + fn available_keys(&self, block: BlockId, account: &Address) -> Option>; + + /// Update permissioning contract + fn update_acl_contract(&self); +} + +/// Secret Store keys provider +pub struct SecretStoreKeys where C: CallContract + RegistryInfo + Send + Sync + 'static { + client: Arc, + key_server_account: Option
, + keys_acl_contract: RwLock>, +} + +impl SecretStoreKeys where C: CallContract + RegistryInfo + Send + Sync + 'static { + /// Create provider + pub fn new(client: Arc, key_server_account: Option
) -> Self { + SecretStoreKeys { + client, + key_server_account, + keys_acl_contract: RwLock::new(None), + } + } +} + +impl KeyProvider for SecretStoreKeys where C: CallContract + RegistryInfo + Send + Sync + 'static { + fn key_server_account(&self) -> Option
{ + self.key_server_account + } + + fn available_keys(&self, block: BlockId, account: &Address) -> Option> { + match *self.keys_acl_contract.read() { + Some(acl_contract_address) => { + let (data, decoder) = keys_acl_contract::functions::available_keys::call(*account); + if let Ok(value) = self.client.call_contract(block, acl_contract_address, data) { + decoder.decode(&value).ok().map(|key_values| { + key_values.iter().map(key_to_address).collect() + }) + } else { + None + } + } + None => None, + } + } + + fn update_acl_contract(&self) { + let contract_address = self.client.registry_address(ACL_CHECKER_CONTRACT_REGISTRY_NAME.into(), BlockId::Latest); + if *self.keys_acl_contract.read() != contract_address { + trace!(target: "privatetx", "Configuring for ACL checker contract from address {:?}", + contract_address); + *self.keys_acl_contract.write() = contract_address; + } + } +} + +/// Dummy keys provider. +pub struct StoringKeyProvider { + available_keys: RwLock>>, + key_server_account: Option
, +} + +impl StoringKeyProvider { + /// Store available keys + pub fn set_available_keys(&self, keys: &Vec
) { + *self.available_keys.write() = Some(keys.clone()) + } +} + +impl Default for StoringKeyProvider { + fn default() -> Self { + StoringKeyProvider { + available_keys: RwLock::new(None), + key_server_account: Some(Address::default()), + } + } +} + +impl KeyProvider for StoringKeyProvider { + fn key_server_account(&self) -> Option
{ + self.key_server_account + } + + fn available_keys(&self, _block: BlockId, _account: &Address) -> Option> { + self.available_keys.read().clone() + } + + fn update_acl_contract(&self) {} +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + use ethkey::{Secret, KeyPair}; + use bytes::Bytes; + use super::*; + + struct DummyRegistryClient { + registry_address: Option
, + } + + impl DummyRegistryClient { + pub fn new(registry_address: Option
) -> Self { + DummyRegistryClient { + registry_address + } + } + } + + impl RegistryInfo for DummyRegistryClient { + fn registry_address(&self, _name: String, _block: BlockId) -> Option
{ self.registry_address } + } + + impl CallContract for DummyRegistryClient { + fn call_contract(&self, _id: BlockId, _address: Address, _data: Bytes) -> Result { Ok(vec![]) } + } + + #[test] + fn should_update_acl_contract() { + let key = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000011")).unwrap(); + let client = DummyRegistryClient::new(Some(key.address())); + let keys_data = SecretStoreKeys::new(Arc::new(client), None); + keys_data.update_acl_contract(); + assert_eq!(keys_data.keys_acl_contract.read().unwrap(), key.address()); + } +} \ No newline at end of file diff --git a/ethcore/private-tx/src/lib.rs b/ethcore/private-tx/src/lib.rs index cbf6baf554..dfe898b637 100644 --- a/ethcore/private-tx/src/lib.rs +++ b/ethcore/private-tx/src/lib.rs @@ -21,6 +21,7 @@ #![recursion_limit="256"] mod encryptor; +mod key_server_keys; mod private_transactions; mod messages; mod error; @@ -41,7 +42,7 @@ extern crate keccak_hash as hash; extern crate parity_bytes as bytes; extern crate parity_crypto as crypto; extern crate parking_lot; -extern crate patricia_trie as trie; +extern crate trie_db as trie; extern crate patricia_trie_ethereum as ethtrie; extern crate rlp; extern crate rustc_hex; @@ -53,8 +54,7 @@ extern crate log; extern crate ethabi_derive; #[macro_use] extern crate ethabi_contract; -#[macro_use] -extern crate error_chain; +extern crate derive_more; #[macro_use] extern crate rlp_derive; @@ -64,9 +64,10 @@ extern crate rand; extern crate env_logger; pub use encryptor::{Encryptor, SecretStoreEncryptor, EncryptorConfig, NoopEncryptor}; +pub use key_server_keys::{KeyProvider, SecretStoreKeys, StoringKeyProvider}; pub use private_transactions::{VerifiedPrivateTransaction, VerificationStore, PrivateTransactionSigningDesc, SigningStore}; pub use messages::{PrivateTransaction, SignedPrivateTransaction}; -pub use error::{Error, ErrorKind}; +pub use error::Error; use std::sync::{Arc, Weak}; use std::collections::{HashMap, HashSet, BTreeMap}; @@ -85,12 +86,11 @@ use ethcore::client::{ Client, ChainNotify, NewBlocks, ChainMessageType, ClientIoMessage, BlockId, Call, BlockInfo }; -use ethcore::account_provider::AccountProvider; use ethcore::miner::{self, Miner, MinerService, pool_client::NonceCache}; +use ethcore::{state, state_db}; use ethcore::trace::{Tracer, VMTracer}; use call_contract::CallContract; use rustc_hex::FromHex; -use ethkey::Password; use ethabi::FunctionOutputDecoder; // Source avaiable at https://github.com/parity-contracts/private-tx/blob/master/contracts/PrivateContract.sol @@ -117,8 +117,6 @@ pub struct ProviderConfig { pub validator_accounts: Vec
, /// Account used for signing public transactions created from private transactions pub signer_account: Option
, - /// Passwords used to unlock accounts - pub passwords: Vec, } #[derive(Debug)] @@ -126,50 +124,85 @@ pub struct ProviderConfig { pub struct Receipt { /// Private transaction hash. pub hash: H256, - /// Created contract address if any. - pub contract_address: Option
, + /// Contract address. + pub contract_address: Address, /// Execution status. pub status_code: u8, } +/// Payload signing and decrypting capabilities. +pub trait Signer: Send + Sync { + /// Decrypt payload using private key of given address. + fn decrypt(&self, account: Address, shared_mac: &[u8], payload: &[u8]) -> Result, Error>; + /// Sign given hash using provided account. + fn sign(&self, account: Address, hash: ethkey::Message) -> Result; +} + +/// Signer implementation that errors on any request. +pub struct DummySigner; +impl Signer for DummySigner { + fn decrypt(&self, _account: Address, _shared_mac: &[u8], _payload: &[u8]) -> Result, Error> { + Err("Decrypting is not supported.".to_owned())? + } + + fn sign(&self, _account: Address, _hash: ethkey::Message) -> Result { + Err("Signing is not supported.".to_owned())? + } +} + +/// Signer implementation using multiple keypairs +pub struct KeyPairSigner(pub Vec); +impl Signer for KeyPairSigner { + fn decrypt(&self, account: Address, shared_mac: &[u8], payload: &[u8]) -> Result, Error> { + let kp = self.0.iter().find(|k| k.address() == account).ok_or(ethkey::Error::InvalidAddress)?; + Ok(ethkey::crypto::ecies::decrypt(kp.secret(), shared_mac, payload)?) + } + + fn sign(&self, account: Address, hash: ethkey::Message) -> Result { + let kp = self.0.iter().find(|k| k.address() == account).ok_or(ethkey::Error::InvalidAddress)?; + Ok(ethkey::sign(kp.secret(), &hash)?) + } +} + /// Manager of private transactions pub struct Provider { encryptor: Box, validator_accounts: HashSet
, signer_account: Option
, - passwords: Vec, notify: RwLock>>, transactions_for_signing: RwLock, transactions_for_verification: VerificationStore, client: Arc, miner: Arc, - accounts: Arc, + accounts: Arc, channel: IoChannel, + keys_provider: Arc, } #[derive(Debug)] pub struct PrivateExecutionResult where T: Tracer, V: VMTracer { code: Option, state: Bytes, - contract_address: Option
, + contract_address: Address, result: Executed, } -impl Provider where { +impl Provider { /// Create a new provider. pub fn new( client: Arc, miner: Arc, - accounts: Arc, + accounts: Arc, encryptor: Box, config: ProviderConfig, channel: IoChannel, + keys_provider: Arc, ) -> Self { + keys_provider.update_acl_contract(); Provider { encryptor, validator_accounts: config.validator_accounts.into_iter().collect(), signer_account: config.signer_account, - passwords: config.passwords, notify: RwLock::default(), transactions_for_signing: RwLock::default(), transactions_for_verification: VerificationStore::default(), @@ -177,6 +210,7 @@ impl Provider where { miner, accounts, channel, + keys_provider, } } @@ -203,10 +237,10 @@ impl Provider where { trace!(target: "privatetx", "Creating private transaction from regular transaction: {:?}", signed_transaction); if self.signer_account.is_none() { warn!(target: "privatetx", "Signing account not set"); - bail!(ErrorKind::SignerAccountNotSet); + return Err(Error::SignerAccountNotSet); } let tx_hash = signed_transaction.hash(); - let contract = Self::contract_address_from_transaction(&signed_transaction).map_err(|_| ErrorKind::BadTransactonType)?; + let contract = Self::contract_address_from_transaction(&signed_transaction).map_err(|_| Error::BadTransactionType)?; let data = signed_transaction.rlp_bytes(); let encrypted_transaction = self.encrypt(&contract, &Self::iv_from_transaction(&signed_transaction), &data)?; let private = PrivateTransaction::new(encrypted_transaction, contract); @@ -227,7 +261,7 @@ impl Provider where { self.broadcast_private_transaction(private.hash(), private.rlp_bytes()); Ok(Receipt { hash: tx_hash, - contract_address: Some(contract), + contract_address: contract, status_code: 0, }) } @@ -241,21 +275,19 @@ impl Provider where { keccak(AsRef::<[u8]>::as_ref(&state_buf as &[u8])) } - fn pool_client<'a>(&'a self, nonce_cache: &'a NonceCache) -> miner::pool_client::PoolClient<'a, Client> { + fn pool_client<'a>(&'a self, nonce_cache: &'a NonceCache, local_accounts: &'a HashSet
) -> miner::pool_client::PoolClient<'a, Client> { let engine = self.client.engine(); - let refuse_service_transactions = true; miner::pool_client::PoolClient::new( &*self.client, nonce_cache, engine, - Some(&*self.accounts), - refuse_service_transactions, + local_accounts, + None, // refuse_service_transactions = true ) } /// Retrieve and verify the first available private transaction for every sender fn process_verification_queue(&self) -> Result<(), Error> { - let nonce_cache = NonceCache::new(NONCE_CACHE_SIZE); let process_transaction = |transaction: &VerifiedPrivateTransaction| -> Result<_, String> { let private_hash = transaction.private_transaction.hash(); match transaction.validator_account { @@ -275,20 +307,19 @@ impl Provider where { // TODO #9825 [ToDr] Usage of BlockId::Latest let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest); if let Err(e) = contract_nonce { - bail!("Cannot retrieve contract nonce: {:?}", e); + return Err(format!("Cannot retrieve contract nonce: {:?}", e).into()); } let contract_nonce = contract_nonce.expect("Error was checked before"); let private_state = self.execute_private_transaction(BlockId::Latest, &transaction.transaction); if let Err(e) = private_state { - bail!("Cannot retrieve private state: {:?}", e); + return Err(format!("Cannot retrieve private state: {:?}", e).into()); } let private_state = private_state.expect("Error was checked before"); let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce); trace!(target: "privatetx", "Hashed effective private state for validator: {:?}", private_state_hash); - let password = find_account_password(&self.passwords, &*self.accounts, &validator_account); - let signed_state = self.accounts.sign(validator_account, password, private_state_hash); + let signed_state = self.accounts.sign(validator_account, private_state_hash); if let Err(e) = signed_state { - bail!("Cannot sign the state: {:?}", e); + return Err(format!("Cannot sign the state: {:?}", e).into()); } let signed_state = signed_state.expect("Error was checked before"); let signed_private_transaction = SignedPrivateTransaction::new(private_hash, signed_state, None); @@ -298,7 +329,9 @@ impl Provider where { } Ok(()) }; - let ready_transactions = self.transactions_for_verification.drain(self.pool_client(&nonce_cache)); + let nonce_cache = NonceCache::new(NONCE_CACHE_SIZE); + let local_accounts = HashSet::new(); + let ready_transactions = self.transactions_for_verification.drain(self.pool_client(&nonce_cache, &local_accounts)); for transaction in ready_transactions { if let Err(e) = process_transaction(&transaction) { warn!(target: "privatetx", "Error: {:?}", e); @@ -327,26 +360,27 @@ impl Provider where { signatures.push(signed_tx.signature()); let rsv: Vec = signatures.into_iter().map(|sign| sign.into_electrum().into()).collect(); // Create public transaction + let signer_account = self.signer_account.ok_or_else(|| Error::SignerAccountNotSet)?; + let state = self.client.state_at(BlockId::Latest).ok_or(Error::StatePruned)?; + let nonce = state.nonce(&signer_account)?; let public_tx = self.public_transaction( desc.state.clone(), &desc.original_transaction, &rsv, - desc.original_transaction.nonce, + nonce, desc.original_transaction.gas_price )?; trace!(target: "privatetx", "Last required signature received, public transaction created: {:?}", public_tx); // Sign and add it to the queue let chain_id = desc.original_transaction.chain_id(); let hash = public_tx.hash(chain_id); - let signer_account = self.signer_account.ok_or_else(|| ErrorKind::SignerAccountNotSet)?; - let password = find_account_password(&self.passwords, &*self.accounts, &signer_account); - let signature = self.accounts.sign(signer_account, password, hash)?; + let signature = self.accounts.sign(signer_account, hash)?; let signed = SignedTransaction::new(public_tx.with_signature(signature, chain_id))?; match self.miner.import_own_transaction(&*self.client, signed.into()) { Ok(_) => trace!(target: "privatetx", "Public transaction added to queue"), Err(err) => { warn!(target: "privatetx", "Failed to add transaction to queue, error: {:?}", err); - bail!(err); + return Err(err.into()); } } // Notify about state changes @@ -361,7 +395,7 @@ impl Provider where { // Remove from store for signing if let Err(err) = self.transactions_for_signing.write().remove(&private_hash) { warn!(target: "privatetx", "Failed to remove transaction from signing store, error: {:?}", err); - bail!(err); + return Err(err); } } else { // Add signature to the store @@ -369,7 +403,7 @@ impl Provider where { Ok(_) => trace!(target: "privatetx", "Signature stored for private transaction"), Err(err) => { warn!(target: "privatetx", "Failed to add signature to signing store, error: {:?}", err); - bail!(err); + return Err(err); } } } @@ -381,7 +415,7 @@ impl Provider where { Action::Call(contract) => Ok(contract), _ => { warn!(target: "privatetx", "Incorrect type of action for the transaction"); - bail!(ErrorKind::BadTransactonType); + return Err(Error::BadTransactionType); } } } @@ -400,13 +434,13 @@ impl Provider where { } false => { warn!(target: "privatetx", "Sender's state doesn't correspond to validator's"); - bail!(ErrorKind::StateIncorrect); + return Err(Error::StateIncorrect); } } } Err(err) => { warn!(target: "privatetx", "Sender's state doesn't correspond to validator's, error {:?}", err); - bail!(err); + return Err(err.into()); } } } @@ -435,32 +469,32 @@ impl Provider where { fn encrypt(&self, contract_address: &Address, initialisation_vector: &H128, data: &[u8]) -> Result { trace!(target: "privatetx", "Encrypt data using key(address): {:?}", contract_address); - Ok(self.encryptor.encrypt(contract_address, &*self.accounts, initialisation_vector, data)?) + Ok(self.encryptor.encrypt(contract_address, initialisation_vector, data)?) } fn decrypt(&self, contract_address: &Address, data: &[u8]) -> Result { trace!(target: "privatetx", "Decrypt data using key(address): {:?}", contract_address); - Ok(self.encryptor.decrypt(contract_address, &*self.accounts, data)?) + Ok(self.encryptor.decrypt(contract_address, data)?) } fn get_decrypted_state(&self, address: &Address, block: BlockId) -> Result { let (data, decoder) = private_contract::functions::state::call(); let value = self.client.call_contract(block, *address, data)?; - let state = decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?; + let state = decoder.decode(&value).map_err(|e| Error::Call(format!("Contract call failed {:?}", e)))?; self.decrypt(address, &state) } fn get_decrypted_code(&self, address: &Address, block: BlockId) -> Result { let (data, decoder) = private_contract::functions::code::call(); let value = self.client.call_contract(block, *address, data)?; - let state = decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?; + let state = decoder.decode(&value).map_err(|e| Error::Call(format!("Contract call failed {:?}", e)))?; self.decrypt(address, &state) } pub fn get_contract_nonce(&self, address: &Address, block: BlockId) -> Result { let (data, decoder) = private_contract::functions::nonce::call(); let value = self.client.call_contract(block, *address, data)?; - decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into()) + decoder.decode(&value).map_err(|e| Error::Call(format!("Contract call failed {:?}", e)).into()) } fn snapshot_to_storage(raw: Bytes) -> HashMap { @@ -484,53 +518,68 @@ impl Provider where { raw } + fn patch_account_state(&self, contract_address: &Address, block: BlockId, state: &mut state::State) -> Result<(), Error> { + let contract_code = Arc::new(self.get_decrypted_code(contract_address, block)?); + let contract_state = self.get_decrypted_state(contract_address, block)?; + trace!(target: "privatetx", "Patching contract at {:?}, code: {:?}, state: {:?}", contract_address, contract_code, contract_state); + state.patch_account(contract_address, contract_code, Self::snapshot_to_storage(contract_state))?; + Ok(()) + } + pub fn execute_private(&self, transaction: &SignedTransaction, options: TransactOptions, block: BlockId) -> Result, Error> where T: Tracer, V: VMTracer, { - let mut env_info = self.client.env_info(block).ok_or(ErrorKind::StatePruned)?; + let mut env_info = self.client.env_info(block).ok_or(Error::StatePruned)?; env_info.gas_limit = transaction.gas; - let mut state = self.client.state_at(block).ok_or(ErrorKind::StatePruned)?; + let mut state = self.client.state_at(block).ok_or(Error::StatePruned)?; // TODO #9825 in case of BlockId::Latest these need to operate on the same state let contract_address = match transaction.action { Action::Call(ref contract_address) => { - let contract_code = Arc::new(self.get_decrypted_code(contract_address, block)?); - let contract_state = self.get_decrypted_state(contract_address, block)?; - trace!(target: "privatetx", "Patching contract at {:?}, code: {:?}, state: {:?}", contract_address, contract_code, contract_state); - state.patch_account(contract_address, contract_code, Self::snapshot_to_storage(contract_state))?; + // Patch current contract state + self.patch_account_state(contract_address, block, &mut state)?; Some(*contract_address) }, Action::Create => None, }; let engine = self.client.engine(); - let contract_address = contract_address.or({ - let sender = transaction.sender(); - let nonce = state.nonce(&sender)?; + let sender = transaction.sender(); + let nonce = state.nonce(&sender)?; + let contract_address = contract_address.unwrap_or_else(|| { let (new_address, _) = ethcore_contract_address(engine.create_address_scheme(env_info.number), &sender, &nonce, &transaction.data); - Some(new_address) + new_address }); + // Patch other available private contracts' states as well + // TODO: #10133 patch only required for the contract states + if let Some(key_server_account) = self.keys_provider.key_server_account() { + if let Some(available_contracts) = self.keys_provider.available_keys(block, &key_server_account) { + for private_contract in available_contracts { + if private_contract == contract_address { + continue; + } + self.patch_account_state(&private_contract, block, &mut state)?; + } + } + } let machine = engine.machine(); let schedule = machine.schedule(env_info.number); let result = Executive::new(&mut state, &env_info, &machine, &schedule).transact_virtual(transaction, options)?; - let (encrypted_code, encrypted_storage) = match contract_address { - None => bail!(ErrorKind::ContractDoesNotExist), - Some(address) => { - let (code, storage) = state.into_account(&address)?; - trace!(target: "privatetx", "Private contract executed. code: {:?}, state: {:?}, result: {:?}", code, storage, result.output); - let enc_code = match code { - Some(c) => Some(self.encrypt(&address, &Self::iv_from_address(&address), &c)?), - None => None, - }; - (enc_code, self.encrypt(&address, &Self::iv_from_transaction(transaction), &Self::snapshot_from_storage(&storage))?) - }, + let (encrypted_code, encrypted_storage) = { + let (code, storage) = state.into_account(&contract_address)?; + trace!(target: "privatetx", "Private contract executed. code: {:?}, state: {:?}, result: {:?}", code, storage, result.output); + let enc_code = match code { + Some(c) => Some(self.encrypt(&contract_address, &Self::iv_from_address(&contract_address), &c)?), + None => None, + }; + (enc_code, self.encrypt(&contract_address, &Self::iv_from_transaction(transaction), &Self::snapshot_from_storage(&storage))?) }; Ok(PrivateExecutionResult { code: encrypted_code, state: encrypted_storage, - contract_address, + contract_address: contract_address, result, }) } @@ -555,24 +604,21 @@ impl Provider where { /// Returns the key from the key server associated with the contract pub fn contract_key_id(&self, contract_address: &Address) -> Result { - // Current solution uses contract address extended with 0 as id - let contract_address_extended: H256 = contract_address.into(); - - Ok(H256::from_slice(&contract_address_extended)) + Ok(key_server_keys::address_to_key(contract_address)) } /// Create encrypted public contract deployment transaction. - pub fn public_creation_transaction(&self, block: BlockId, source: &SignedTransaction, validators: &[Address], gas_price: U256) -> Result<(Transaction, Option
), Error> { + pub fn public_creation_transaction(&self, block: BlockId, source: &SignedTransaction, validators: &[Address], gas_price: U256) -> Result<(Transaction, Address), Error> { if let Action::Call(_) = source.action { - bail!(ErrorKind::BadTransactonType); + return Err(Error::BadTransactionType); } let sender = source.sender(); - let state = self.client.state_at(block).ok_or(ErrorKind::StatePruned)?; + let state = self.client.state_at(block).ok_or(Error::StatePruned)?; let nonce = state.nonce(&sender)?; let executed = self.execute_private(source, TransactOptions::with_no_tracing(), block)?; let header = self.client.block_header(block) - .ok_or(ErrorKind::StatePruned) - .and_then(|h| h.decode().map_err(|_| ErrorKind::StateIncorrect).into())?; + .ok_or(Error::StatePruned) + .and_then(|h| h.decode().map_err(|_| Error::StateIncorrect).into())?; let (executed_code, executed_state) = (executed.code.unwrap_or_default(), executed.state); let tx_data = Self::generate_constructor(validators, executed_code.clone(), executed_state.clone()); let mut tx = Transaction { @@ -603,7 +649,7 @@ impl Provider where { /// Create encrypted public contract deployment transaction. Returns updated encrypted state. pub fn execute_private_transaction(&self, block: BlockId, source: &SignedTransaction) -> Result { if let Action::Create = source.action { - bail!(ErrorKind::BadTransactonType); + return Err(Error::BadTransactionType); } let result = self.execute_private(source, TransactOptions::with_no_tracing(), block)?; Ok(result.state) @@ -632,7 +678,7 @@ impl Provider where { pub fn get_validators(&self, block: BlockId, address: &Address) -> Result, Error> { let (data, decoder) = private_contract::functions::get_validators::call(); let value = self.client.call_contract(block, *address, data)?; - decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into()) + decoder.decode(&value).map_err(|e| Error::Call(format!("Contract call failed {:?}", e)).into()) } fn get_contract_version(&self, block: BlockId, address: &Address) -> usize { @@ -683,12 +729,13 @@ impl Importer for Arc { let transaction_bytes = self.decrypt(&contract, &encrypted_data)?; let original_tx: UnverifiedTransaction = Rlp::new(&transaction_bytes).as_val()?; let nonce_cache = NonceCache::new(NONCE_CACHE_SIZE); + let local_accounts = HashSet::new(); // Add to the queue for further verification self.transactions_for_verification.add_transaction( original_tx, validation_account.map(|&account| account), private_tx, - self.pool_client(&nonce_cache), + self.pool_client(&nonce_cache, &local_accounts), )?; let provider = Arc::downgrade(self); let result = self.channel.send(ClientIoMessage::execute(move |_| { @@ -723,16 +770,6 @@ impl Importer for Arc { } } -/// Try to unlock account using stored password, return found password if any -fn find_account_password(passwords: &Vec, account_provider: &AccountProvider, account: &Address) -> Option { - for password in passwords { - if let Ok(true) = account_provider.test_password(account, password) { - return Some(password.clone()); - } - } - None -} - impl ChainNotify for Provider { fn new_blocks(&self, new_blocks: NewBlocks) { if new_blocks.imported.is_empty() || new_blocks.has_more_blocks_to_import { return } @@ -740,5 +777,6 @@ impl ChainNotify for Provider { if let Err(err) = self.process_verification_queue() { warn!(target: "privatetx", "Cannot prune private transactions queue. error: {:?}", err); } + self.keys_provider.update_acl_contract(); } } diff --git a/ethcore/private-tx/src/private_transactions.rs b/ethcore/private-tx/src/private_transactions.rs index 21989025b1..d0456657b0 100644 --- a/ethcore/private-tx/src/private_transactions.rs +++ b/ethcore/private-tx/src/private_transactions.rs @@ -28,7 +28,7 @@ use parking_lot::RwLock; use types::transaction::{UnverifiedTransaction, SignedTransaction}; use txpool; use txpool::{VerifiedTransaction, Verifier}; -use error::{Error, ErrorKind}; +use error::Error; type Pool = txpool::Pool; @@ -154,7 +154,7 @@ impl Default for VerificationStore { impl VerificationStore { /// Adds private transaction for verification into the store - pub fn add_transaction( + pub fn add_transaction( &self, transaction: UnverifiedTransaction, validator_account: Option
, @@ -164,7 +164,7 @@ impl VerificationStore { let options = self.verification_options.clone(); // Use pool's verifying pipeline for original transaction's verification - let verifier = pool::verifier::Verifier::new(client, options, Default::default(), None); + let verifier = pool::verifier::Verifier::new(client.clone(), options, Default::default(), None); let unverified = pool::verifier::Transaction::Unverified(transaction); let verified_tx = verifier.verify_transaction(unverified)?; let signed_tx: SignedTransaction = verified_tx.signed().clone(); @@ -177,8 +177,9 @@ impl VerificationStore { transaction_hash: signed_hash, transaction_sender: signed_sender, }; - let mut pool = self.verification_pool.write(); - pool.import(verified)?; + let replace = pool::replace::ReplaceByScoreAndReadiness::new( + self.verification_pool.read().scoring().clone(), client); + self.verification_pool.write().import(verified, &replace)?; Ok(()) } @@ -228,7 +229,7 @@ impl SigningStore { contract_nonce: U256, ) -> Result<(), Error> { if self.transactions.len() > MAX_QUEUE_LEN { - bail!(ErrorKind::QueueIsFull); + return Err(Error::QueueIsFull); } self.transactions.insert(private_hash, PrivateTransactionSigningDesc { @@ -254,7 +255,7 @@ impl SigningStore { /// Adds received signature for the stored private transaction pub fn add_signature(&mut self, private_hash: &H256, signature: Signature) -> Result<(), Error> { - let desc = self.transactions.get_mut(private_hash).ok_or_else(|| ErrorKind::PrivateTransactionNotFound)?; + let desc = self.transactions.get_mut(private_hash).ok_or_else(|| Error::PrivateTransactionNotFound)?; if !desc.received_signatures.contains(&signature) { desc.received_signatures.push(signature); } diff --git a/ethcore/private-tx/tests/private_contract.rs b/ethcore/private-tx/tests/private_contract.rs index b681a03800..6365b10eec 100644 --- a/ethcore/private-tx/tests/private_contract.rs +++ b/ethcore/private-tx/tests/private_contract.rs @@ -29,12 +29,11 @@ extern crate rustc_hex; extern crate log; use std::sync::Arc; -use rustc_hex::FromHex; +use rustc_hex::{FromHex, ToHex}; use types::ids::BlockId; use types::transaction::{Transaction, Action}; use ethcore::CreateContractAddress; -use ethcore::account_provider::AccountProvider; use ethcore::client::BlockChainClient; use ethcore::executive::{contract_address}; use ethcore::miner::Miner; @@ -42,7 +41,7 @@ use ethcore::test_helpers::{generate_dummy_client, push_block_with_transactions} use ethkey::{Secret, KeyPair, Signature}; use hash::keccak; -use ethcore_private_tx::{NoopEncryptor, Provider, ProviderConfig}; +use ethcore_private_tx::{NoopEncryptor, Provider, ProviderConfig, StoringKeyProvider}; #[test] fn private_contract() { @@ -54,26 +53,25 @@ fn private_contract() { let _key2 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000012")).unwrap(); let key3 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000013")).unwrap(); let key4 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000014")).unwrap(); - let ap = Arc::new(AccountProvider::transient_provider()); - ap.insert_account(key1.secret().clone(), &"".into()).unwrap(); - ap.insert_account(key3.secret().clone(), &"".into()).unwrap(); - ap.insert_account(key4.secret().clone(), &"".into()).unwrap(); + + let signer = Arc::new(ethcore_private_tx::KeyPairSigner(vec![key1.clone(), key3.clone(), key4.clone()])); let config = ProviderConfig{ validator_accounts: vec![key3.address(), key4.address()], signer_account: None, - passwords: vec!["".into()], }; let io = ethcore_io::IoChannel::disconnected(); let miner = Arc::new(Miner::new_for_tests(&::ethcore::spec::Spec::new_test(), None)); + let private_keys = Arc::new(StoringKeyProvider::default()); let pm = Arc::new(Provider::new( client.clone(), miner, - ap.clone(), + signer.clone(), Box::new(NoopEncryptor::default()), config, io, + private_keys, )); let (address, _) = contract_address(CreateContractAddress::FromSenderAndNonce, &key1.address(), &0.into(), &[]); @@ -155,3 +153,123 @@ fn private_contract() { let result = pm.private_call(BlockId::Latest, &query_tx).unwrap(); assert_eq!(result.output, "2a00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap()); } + +#[test] +fn call_other_private_contract() { + // This test verifies calls private contract methods from another one + // Two contract will be deployed + // The same contract A: + // contract Test1 { + // bytes32 public x; + // function setX(bytes32 _x) { + // x = _x; + // } + // } + // And the following contract B: + // contract Deployed { + // function setX(uint) {} + // function x() returns (uint) {} + //} + // contract Existing { + // Deployed dc; + // function Existing(address t) { + // dc = Deployed(t); + // } + // function getX() returns (uint) { + // return dc.x(); + // } + // } + //ethcore_logger::init_log(); + + // Create client and provider + let client = generate_dummy_client(0); + let chain_id = client.signing_chain_id(); + let key1 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000011")).unwrap(); + let _key2 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000012")).unwrap(); + let key3 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000013")).unwrap(); + let key4 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000014")).unwrap(); + let signer = Arc::new(ethcore_private_tx::KeyPairSigner(vec![key1.clone(), key3.clone(), key4.clone()])); + + let config = ProviderConfig{ + validator_accounts: vec![key3.address(), key4.address()], + signer_account: None, + }; + + let io = ethcore_io::IoChannel::disconnected(); + let miner = Arc::new(Miner::new_for_tests(&::ethcore::spec::Spec::new_test(), None)); + let private_keys = Arc::new(StoringKeyProvider::default()); + let pm = Arc::new(Provider::new( + client.clone(), + miner, + signer.clone(), + Box::new(NoopEncryptor::default()), + config, + io, + private_keys.clone(), + )); + + // Deploy contract A + let (address_a, _) = contract_address(CreateContractAddress::FromSenderAndNonce, &key1.address(), &0.into(), &[]); + trace!("Creating private contract A"); + let private_contract_a_test = "6060604052341561000f57600080fd5b60d88061001d6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630c55699c146046578063bc64b76d14607457600080fd5b3415605057600080fd5b60566098565b60405180826000191660001916815260200191505060405180910390f35b3415607e57600080fd5b6096600480803560001916906020019091905050609e565b005b60005481565b8060008160001916905550505600a165627a7a723058206acbdf4b15ca4c2d43e1b1879b830451a34f1e9d02ff1f2f394d8d857e79d2080029".from_hex().unwrap(); + let mut private_create_tx1 = Transaction::default(); + private_create_tx1.action = Action::Create; + private_create_tx1.data = private_contract_a_test; + private_create_tx1.gas = 200000.into(); + private_create_tx1.nonce = 0.into(); + let private_create_tx_signed = private_create_tx1.sign(&key1.secret(), None); + let validators = vec![key3.address(), key4.address()]; + let (public_tx1, _) = pm.public_creation_transaction(BlockId::Latest, &private_create_tx_signed, &validators, 0.into()).unwrap(); + let public_tx1 = public_tx1.sign(&key1.secret(), chain_id); + trace!("Transaction created. Pushing block"); + push_block_with_transactions(&client, &[public_tx1]); + + // Deploy contract B + let (address_b, _) = contract_address(CreateContractAddress::FromSenderAndNonce, &key1.address(), &1.into(), &[]); + trace!("Creating private contract B"); + // Build constructor data + let mut deploy_data = "6060604052341561000f57600080fd5b6040516020806101c583398101604052808051906020019091905050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505061014a8061007b6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680635197c7aa14610046575b600080fd5b341561005157600080fd5b61005961006f565b6040518082815260200191505060405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630c55699c6000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15156100fe57600080fd5b6102c65a03f1151561010f57600080fd5b505050604051805190509050905600a165627a7a723058207f8994e02725b47d76ec73e5c54a338d27b306dd1c830276bff2d75fcd1a5c920029000000000000000000000000".to_string(); + deploy_data.push_str(&address_a.to_vec().to_hex()); + let private_contract_b_test = deploy_data.from_hex().unwrap(); + let mut private_create_tx2 = Transaction::default(); + private_create_tx2.action = Action::Create; + private_create_tx2.data = private_contract_b_test; + private_create_tx2.gas = 200000.into(); + private_create_tx2.nonce = 1.into(); + let private_create_tx_signed = private_create_tx2.sign(&key1.secret(), None); + let (public_tx2, _) = pm.public_creation_transaction(BlockId::Latest, &private_create_tx_signed, &validators, 0.into()).unwrap(); + let public_tx2 = public_tx2.sign(&key1.secret(), chain_id); + trace!("Transaction created. Pushing block"); + push_block_with_transactions(&client, &[public_tx2]); + + // Let provider know, that it has access to both keys for A and B + private_keys.set_available_keys(&vec![address_a, address_b]); + + // Call A.setx(42) + trace!("Modifying private state"); + let mut private_tx = Transaction::default(); + private_tx.action = Action::Call(address_a.clone()); + private_tx.data = "bc64b76d2a00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap(); //setX(42) + private_tx.gas = 120000.into(); + private_tx.nonce = 2.into(); + let private_tx = private_tx.sign(&key1.secret(), None); + let private_contract_nonce = pm.get_contract_nonce(&address_b, BlockId::Latest).unwrap(); + let private_state = pm.execute_private_transaction(BlockId::Latest, &private_tx).unwrap(); + let nonced_state_hash = pm.calculate_state_hash(&private_state, private_contract_nonce); + let signatures: Vec<_> = [&key3, &key4].iter().map(|k| + Signature::from(::ethkey::sign(&k.secret(), &nonced_state_hash).unwrap().into_electrum())).collect(); + let public_tx = pm.public_transaction(private_state, &private_tx, &signatures, 2.into(), 0.into()).unwrap(); + let public_tx = public_tx.sign(&key1.secret(), chain_id); + push_block_with_transactions(&client, &[public_tx]); + + // Call B.getX() + trace!("Querying private state"); + let mut query_tx = Transaction::default(); + query_tx.action = Action::Call(address_b.clone()); + query_tx.data = "5197c7aa".from_hex().unwrap(); // getX + query_tx.gas = 50000.into(); + query_tx.nonce = 3.into(); + let query_tx = query_tx.sign(&key1.secret(), chain_id); + let result = pm.private_call(BlockId::Latest, &query_tx).unwrap(); + assert_eq!(&result.output[..], &("2a00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap()[..])); +} diff --git a/ethcore/res/authority_round.json b/ethcore/res/authority_round.json index 8d54244379..33afa45871 100644 --- a/ethcore/res/authority_round.json +++ b/ethcore/res/authority_round.json @@ -46,9 +46,50 @@ "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, + "0000000000000000000000000000000000000006": { + "balance": "1", + "builtin": { + "name": "alt_bn128_add", + "activate_at": 0, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "balance": "1", + "builtin": { + "name": "alt_bn128_mul", + "activate_at": 0, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "balance": "1", + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": 0, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, "9cce34f7ab185c7aba1b7c8140d620b4bda941d6": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } } } diff --git a/ethcore/res/authority_round_block_reward_contract.json b/ethcore/res/authority_round_block_reward_contract.json index 3195773123..73893d44d1 100644 --- a/ethcore/res/authority_round_block_reward_contract.json +++ b/ethcore/res/authority_round_block_reward_contract.json @@ -49,9 +49,50 @@ "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, + "0000000000000000000000000000000000000006": { + "balance": "1", + "builtin": { + "name": "alt_bn128_add", + "activate_at": 0, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "balance": "1", + "builtin": { + "name": "alt_bn128_mul", + "activate_at": 0, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "balance": "1", + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": 0, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, "9cce34f7ab185c7aba1b7c8140d620b4bda941d6": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" }, "0000000000000000000000000000000000000042": { "balance": "1", diff --git a/ethcore/res/basic_authority.json b/ethcore/res/basic_authority.json index 35711be011..2d92355e3a 100644 --- a/ethcore/res/basic_authority.json +++ b/ethcore/res/basic_authority.json @@ -38,9 +38,50 @@ "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, + "0000000000000000000000000000000000000006": { + "balance": "1", + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "balance": "1", + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "balance": "1", + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, "9cce34f7ab185c7aba1b7c8140d620b4bda941d6": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } } } diff --git a/ethcore/res/constructor.json b/ethcore/res/constructor.json index f4e22ea2d8..1383337351 100644 --- a/ethcore/res/constructor.json +++ b/ethcore/res/constructor.json @@ -34,9 +34,50 @@ "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, + "0000000000000000000000000000000000000006": { + "balance": "1", + "builtin": { + "name": "alt_bn128_add", + "activate_at": 0, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "balance": "1", + "builtin": { + "name": "alt_bn128_mul", + "activate_at": 0, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "balance": "1", + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": 0, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, "0000000000000000000000000000000000001337": { "balance": "1", "constructor": "60606040526000805460ff19166001179055346000575b6075806100246000396000f300606060405263ffffffff60e060020a60003504166394b91deb81146022575b6000565b34600057602c6040565b604080519115158252519081900360200190f35b60005460ff16815600a165627a7a723058207882eb60ebce23178b3fa06d4cd8e5adc17711937ccddacb18a04abca2a2c9ee0029" } } } diff --git a/ethcore/res/ethereum/byzantium_test.json b/ethcore/res/ethereum/byzantium_test.json index 9fdde9d13e..b4df953739 100644 --- a/ethcore/res/ethereum/byzantium_test.json +++ b/ethcore/res/ethereum/byzantium_test.json @@ -54,8 +54,46 @@ "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x00", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x00", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x00", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + } } } diff --git a/ethcore/res/ethereum/callisto.json b/ethcore/res/ethereum/callisto.json index 3513e8bb76..02dc3d2763 100644 --- a/ethcore/res/ethereum/callisto.json +++ b/ethcore/res/ethereum/callisto.json @@ -72,9 +72,50 @@ "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 20, "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 20, "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 20, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 20, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, + "0000000000000000000000000000000000000006": { + "balance": "1", + "builtin": { + "name": "alt_bn128_add", + "activate_at": 20, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "balance": "1", + "builtin": { + "name": "alt_bn128_mul", + "activate_at": 20, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "balance": "1", + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": 20, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, "183394f52b2c8c034835edba3bcececa6f60b5a8": { "balance": "100491852286952719463755404" } diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index 898268901f..f824f7667d 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -8,11 +8,12 @@ "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", - "homesteadTransition": 1150000, - "ecip1010PauseTransition": 3000000, - "ecip1010ContinueTransition": 5000000, - "ecip1017EraRounds": 5000000, - "bombDefuseTransition": 5900000 + "homesteadTransition": "0x118c30", + "ecip1010PauseTransition": "0x2dc6c0", + "ecip1010ContinueTransition": "0x4c4b40", + "ecip1017EraRounds": "0x4c4b40", + "eip100bTransition": "0x85d9a0", + "bombDefuseTransition": "0x5a06e0" } } }, @@ -26,11 +27,17 @@ "chainID": "0x3d", "forkBlock": "0x1d4c00", "forkCanonHash": "0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f", - "eip150Transition": 2500000, - "eip160Transition": 3000000, - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff", - "eip155Transition": 3000000 + "eip150Transition": "0x2625a0", + "eip160Transition": "0x2dc6c0", + "eip161abcTransition": "0x85d9a0", + "eip161dTransition": "0x85d9a0", + "eip155Transition": "0x2dc6c0", + "maxCodeSize": "0x6000", + "maxCodeSizeTransition": "0x85d9a0", + "eip140Transition": "0x85d9a0", + "eip211Transition": "0x85d9a0", + "eip214Transition": "0x85d9a0", + "eip658Transition": "0x85d9a0" }, "genesis": { "seal": { @@ -48,8 +55,8 @@ "stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" }, "hardcodedSync": { - "header": "f90210a08eb792fdb134b57fffbdf19bd61d4c1cc351fc38a7fcf6609c82b35ea364208fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794df7d7e053933b5cc24372f878c90e62dadad5d42a0e29a2e741354b453139d244920f7d552f90a579f1dcb99ef6b470bcffc713ebaa04bb64c992b8cf56259177a192d6f0a1eddf192b8daa7dbf1ec8313428cccde20a0ee22efe3b124a0297503fd26e6f7b33c7a88aa75825259297f8e30bee3632a68b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000866a396ffc14908373480183797a1182f618845c7395609165746865726d696e652d6574632d757331a087f3616cc0ba3704e23702bf7461f8f7716f1f1ad3ac4c66391d45adc57d1dea886ecb8e800fe87049", - "totalDifficulty": "575603227549295900024", + "header": "f9021ba0a281d23475d3d5ff03df8636c9f528cdd91498af274a3b2f8989bbd51bfeb809a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794004730417cd2b1d19f6be2679906ded4fa8a64e2a0d5fdd62e7e29dc3da1cd3fe5ad549e000260bfdb55f523fde008f26390220d23a0370ff78457d6c7469ff333a13165f4bb8057d00cfa68365cb4d1a8c8a1da46d5a0dea37365a20f5bb5ad3766a24a9fe7b04b946e35aaba74f862467a7c5cdb7d67b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000004000000000040000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000100000000000000000000000080000000000000000020000000000000000000000000000000000000000000000000000000000000000000000020000000000001000000000000000000000000000000080010000000000000008000000000000000866fc181925a9783763801837a121d830c317c845c9d1efe9b457468657265756d436c6173736963534f4c4f2f326d696e657273a0bb6e626c7ee3d827da18e1b303d9552ba17e92cefcedfc58bdfc5bac6a8ebabe882d8c26402344c24b", + "totalDifficulty": "598584828374329723203", "CHTs": [ "0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc", "0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11", @@ -3739,9 +3746,103 @@ "0x362ca494021482f0d9dea4abd844ca11b71fbeb0a98e7db7bfb3bb6f864eb58c", "0x09ec27c856f50888e4634ffaca66f8185fd13e0bb2bbf522ce6209886502c7a5", "0x24996d2f96618887c1c5e61d5d7ce6948853ca35811d48f72155a4778308e255", - "0x4f199a8efc8615c623902b5c279dd995ac1df4654a07aab0423e070d14bd24d0" + "0x4f199a8efc8615c623902b5c279dd995ac1df4654a07aab0423e070d14bd24d0", + "0xe6875990cef0d2ce1f9d100654cdf522bbe345a462ebca769b1e288128c13201", + "0x36c141d47991e557f7226d8b1fe791c334f046f867d7865d663f99e2a337d915", + "0x337e59da56cde8e3f9e90fafff54d4fa240ba01aec855fd55626e4b3a45a9767", + "0x67672d3a29c49e3545d25422b6015a1eebe86596f55d4c9b8772e89c99ac9f8b", + "0x6d6e167641bcd2e5241ac2710951f7f0c47fb311e32e998831e6fe38f5bebb25", + "0x6dc4fa5ae3f281a90619216491284d951151f37be648694d1952314f43ffe05d", + "0x3c865ccee7900b39d671c43ae15df71fad294781d74815537de94d02b48dd8a0", + "0x10ba37d2ff46db181ff8a15f38bfeecfd9c21e28bf63cb5ab975a2d7c74c0aef", + "0xba265a598f3af5bf4c2b87bd8d28a55f963cfbd09108aaccd5b00294f662e8b9", + "0xaab422eb98f7b0ab9a01558069a3666efa2be2510097b0054bd5c8fceb1023df", + "0xdbff3ce1e6fb0388029f95bd091c95b88c6539fabfe6f1de8e44c47dab064ff8", + "0xb1aa0c7254f3aaa61b58c9d973f3d89f5f4dc6bfee011ad4c4a3e3ae76aaf7df", + "0x055e36325029db9e089808ca01b0ee3eae53703f3e91ee51e587e7b7dcaa8a3d", + "0x00ec5a25517cf0c0a1bf892e5209fd0185ff1ffc6b2523642bf86f6a3d0c10f3", + "0x7bc6a8d5017760f12ace9ebfcdf5a91abcfd6e4f4131df5c4dbe84d2d6a6add9", + "0xeb5da64c8d0cc93a44da96ee9c3c0a22054a2a2e87a7491a5618ade1f59a1b96", + "0xc0a937729678bb6aca27ae16c662ccd2dd0b53346c610d6e5d5b1655762fa4b3", + "0x55c732917d3894ffeb9844fcb1c690d0956c4e2a8eccb6552cdde4ea90c99db2", + "0xf1dfd2205daf748da9e8e98bc4ee94cd6b2db5560e4cead28910e14c576337aa", + "0x60a271fb20c017f90d99c57783ebb8b1a3233398c49f89d73db14b09adf2893b", + "0x8fbd97d55dc64f2124c79054765515f49d79a05f2962b17875f12b353c33f564", + "0x5afd5951c5e834fbf22071047f72619496e9a9dbc6073b661c44741b67fabf03", + "0x2d05a19223820f92e385d2c942b70cca32804546f3aa7058381ca3f6c1ecde11", + "0x267dab323804f2e7bdcc80dde83ccbff56d1aa0fffd0edc7c02ffd4a24bbe027", + "0xf4e9e580bbcc5a9be1f942c12d4b34eb1a4c07feffd0b95abe27ddff57a6cc8f", + "0x3f146ceffcd100ca9fc1af743fad74acd03a289f4038413acfcfd0eb87d14a56", + "0xef98171ed6b269c0ebd6bdbb1d98694316b639bae6a3ad01f4964c3d2eb3d2cf", + "0x510013a35d5c71863b3385176c794ad90e17af1fd271b933f9f7ab980311b27c", + "0x5eb181d22f30ed203c4d3fad610d31c2338dae6a88eee250af19ae0f58319ad1", + "0x50a28d65b51ff086dcf2110feca7d990db95f078394c56bfb850a3b8cfd7f1a2", + "0x4148b8f2136b84773b7ff71d73aa8ffb98f0f3952939849f324c28b9173efd70", + "0xa980bc7fa736bf6d6d794ffa5e035664c45117c21e40da7ba76de7c2ff8164d0", + "0x794a8ef17e48986df700d6e68799a50695086702d6224ae9a71663fd03f8a55e", + "0xf354c82e1c75d7d758099dcd4d0592363eef81e85cba773aa6d6b30e1900582a", + "0xbb4c8b990add1c4e43ddebf742eb605028ae2daa8b61db7d237386d81e4c3413", + "0x61470a53ef9757fa7c452bdbe26d448dd8bf6590fc11420ebeddf441fe56f381", + "0x603558b2f72405e9625ac561d62c2bbcdda84d8ef4b5510d06bdac0553025bf2", + "0xf52d9ba6ba149d0e4266a8d05b73e4a445e9583560024e0185d4b8b12bd55640", + "0x26ef211f77b4a67ddb0a24c4e63f7d247d6ce8635dd9862894bdc067633ff395", + "0xed4ce5eb08b63534c5de241513a996322d168f6b8bf5c75167e79dd7ca1cc817", + "0x9d5f39f494a36d17db609b7a7a62734ca7222426c3556132bf1e2241d6c45cd2", + "0xe664772da4521e1140cc2c5db744010f57c15374dfb78a97701904787846a8f6", + "0x93faea0d197923b1578ac190fe608203f637fe4991ad4954c15ea94e17ee948b", + "0x2b028c1aaae5217cabb97c46c20541c93e55a868f78e82740f9fb9a0a033d662", + "0x529103419484990ad11c05e0c4c696826f67fbcd491e19aaac461cc340747ec4", + "0xc1e773415513b7bf47340d7b0a29e5d49d1a88bb3d0ee2a79726169d32012378", + "0xf97c43bb4ae25524b180e59cb6cac75858d4a8a0772fcf4f3bd24dfad42169da", + "0x19fa7ad12455fd022cfd15897d553e031ca1adf80c963c770250d36f1810a5f0", + "0xe67ce6e2444b8318a01150952a537ee47b701555c79f60eb90d3c3cdf93fb6b1", + "0x1b49d232180b0922704ebd4e9fabca5dd8ae9cfc2a39ea07226ba903a15037e3", + "0x56540b02ffe1743468342b5664b6e51cb3ef6c48dd74d6cd74e0c0c513c13129", + "0xd4d9d67f352c7f54d68ce994b3765b032108a5bd0b5b62d14b893949b96008d4", + "0x44d1b765df81594fd37e7700019f19b1ebd6d9b50631455931b83ce35238cb6b", + "0x2b67aef7cecfec055853cd63e8519bf506d7a1ae69a768e4db9415bdff532c47", + "0xc30ac2a4acc33cec2cdc83e114fb8237c4900a2fc89dddb6af3a4dd5e4868e51", + "0xe0e7127e086e2011f30fcd0469b35769cae163acb8ee6db8a8e2c032c2b351c5", + "0xb46c428070d15ec926fdf1d7465a9168c56dbb959d5391e26480500a98e36047", + "0x8dab41ce167633da3c0b5332833dfad5d2c28ef30c94973e5f4647e312781676", + "0xc632d30657b39208c254cf4f899d00d7c3196cbdc31248798a760972bf399fec", + "0xb4eb2c6c656406a9bc6cc6176dbdfc0e878046530d830a51e04a4e22c4572370", + "0xadb48a02c9c87b246360edb45528ba23cceed736a2ee0cfd03177428e6243024", + "0x443ac2e63e6d629398e607d6689725dd68fd5254916c1b76c876885456a13338", + "0xb66c4d950a9304025654de37c7d0e9759b755d86226a816d1e3b4c7d654a1bc3", + "0xded624610c3493bc7806844342c37909c1c1d179025c215108a12a0428ae9e36", + "0x28c85177961714ce796f152dcd31c8b19db1c39deebfe383d6fdf2334d4261b6", + "0x6d342534c3a4a875c5455ed3ef546e876cedb5aee7b2ecf194c6e47c6a09d3a4", + "0x65a84879e014085b7a0de5bf604050bc6bffd8ab7748253203fff49573763558", + "0xcb0e4339dfbfc8b420c915149a0d352fda69c31668b32452c432f067462b4325", + "0x3466440e4c88895f2642f2986dea4be482c028592530224d73e67254b2bac69f", + "0xb7c325fec25c7b278724ebb91c64fc2ac37e91e44b136dd6c29bf48b80990888", + "0x7a9a2bd3ab5972c1a4ec5972f959a1e30eb678090ed76947e38d76fc3ed758a5", + "0x74deabf896026cb20e2f5f8a88828b265d6696883dab972fe1bc9a4ca98d68b5", + "0x195d2e25b1ec8deea095bcbaac5277f4586237e68bd9c9ad24e65a8e53d6d27a", + "0xcc343c21f7f18c1d507cc3cf12381d7bbe55d7355363361d05d972343fb4b7fe", + "0xd2637aaef2034203e549453225eb1d75633d2c66e8cad0419395250c1e369536", + "0x0f8052a87aa435deee2826e6dbc944128835264d5770dbb064373de05333f8c2", + "0x2091278a3d6a7ed1ab0458cc307903a51d75c6a1c549ebed1f0aed29ce6533b8", + "0x3f7d25feee0dcf39372ccbad55989442d9b7ce16ac93e4b1dca63bd92d5204e4", + "0xd0f866c38597038e360af960e3e84c79a0027576bf3fdf4358a9442f0c671b61", + "0xc527b3694dc6b46f0562cb36e2f766e5b75793ad2794258d8be5119bff4ea8b0", + "0x47f1d7d32904cb0945e97140c2412d12b1e0980c2f72c7878250170aae4124dd", + "0x57aa1ef2a7ec01ee7acd0c4baed5407f30d6c34f2bc6bce7fda6366517343199", + "0xd392127f856736dd74d16a24309a247682e2736f78fc92713c484a6f13edcdbf", + "0x595aa7e3eddba867389d63b2eaa6b16e4e5163076f03d2c8013e40c3b0fc98c0", + "0x50bb320d8bea03db548be3a3b619159e1993ba8eea83af6f022b9cd29ae4d0ff", + "0x53deeb64ee923912f76a233532f474d76d8f6b8cc42eedcce81bda8ad608294c", + "0x1af301b0eaf36d16a74b2d1f76e9e26659f047cd3466a765049260047c25bbee", + "0x05c1d40227ece15c55f06dc922f5a9be01cc147a96e070e7a81b696f0f40b6ee", + "0xa63ee877c70d8e51e795d153a34ce3bcc212f8fb8e77df52ff83084b9133a280", + "0x07ab3e2107db7ff479f5be0d7a57e3b76627cf6230cdeb61d78ebaa2c391d360", + "0xc893aee6d249c152f5db3d7763f34a3311345dff721ae9c71ab5fb3d2b3e2559", + "0x250caa98ea3e682be9c866990f19647f443d57690052229ac0ccfa0ab30a5a71", + "0xc32fd5318214071a41cd8e98499b2b65942c5837c686a06b536146fd0bf294bf", + "0xac390c012eecd83fa8f4cc77a59992914b5c95af36b28747e07adea13228acbc" ] - }, + }, "nodes": [ "enode://efd48ad0879eeb7f9cb5e50f33f7bc21e805a72e90361f145baaa22dd75d111e7cd9c93f1b7060dcb30aa1b3e620269336dbf32339fea4c18925a4c15fe642df@18.205.66.229:30303", "enode://5fbfb426fbb46f8b8c1bd3dd140f5b511da558cd37d60844b525909ab82e13a25ee722293c829e52cb65c2305b1637fa9a2ea4d6634a224d5f400bfe244ac0de@162.243.55.45:30303", @@ -3757,10 +3858,102 @@ "enode://5cd218959f8263bc3721d7789070806b0adff1a0ed3f95ec886fb469f9362c7507e3b32b256550b9a7964a23a938e8d42d45a0c34b332bfebc54b29081e83b93@35.187.57.94:30303" ], "accounts": { - "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, - "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, - "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0x0000000000000000000000000000000000000001": { + "builtin": { + "name": "ecrecover", + "pricing": { + "linear": { + "base": 3000, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000002": { + "builtin": { + "name": "sha256", + "pricing": { + "linear": { + "base": 60, + "word": 12 + } + } + } + }, + "0x0000000000000000000000000000000000000003": { + "builtin": { + "name": "ripemd160", + "pricing": { + "linear": { + "base": 600, + "word": 120 + } + } + } + }, + "0x0000000000000000000000000000000000000004": { + "builtin": { + "name": "identity", + "pricing": { + "linear": { + "base": 15, + "word": 3 + } + } + } + }, + "0x0000000000000000000000000000000000000005": { + "builtin": { + "name": "modexp", + "activate_at": "0x85d9a0", + "pricing": { + "modexp": { + "divisor": 20 + } + } + } + }, + "0x0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x85d9a0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0x0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x85d9a0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0x0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x85d9a0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, "3282791d6fd713f1e94f4bfd565eaa78b3a0599d": { "balance": "1337000000000000000000" }, diff --git a/ethcore/res/ethereum/constantinople_test.json b/ethcore/res/ethereum/constantinople_test.json index b6db5cddb9..c61711e7a7 100644 --- a/ethcore/res/ethereum/constantinople_test.json +++ b/ethcore/res/ethereum/constantinople_test.json @@ -58,8 +58,46 @@ "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x00", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x00", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x00", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + } } } diff --git a/ethcore/res/ethereum/easthub.json b/ethcore/res/ethereum/easthub.json deleted file mode 100644 index 51de695cd1..0000000000 --- a/ethcore/res/ethereum/easthub.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "name": "Easthub", - "dataDir": "easthub", - "engine": { - "Ethash": { - "params": { - "minimumDifficulty": "0x020000", - "difficultyBoundDivisor": "0x0800", - "durationLimit": "0x0d", - "blockReward": "0x2B5E3AF16B1880000", - "homesteadTransition": "0x0", - "bombDefuseTransition": "0x0", - "ecip1017EraRounds": 5000000 - } - } - }, - "params": { - "gasLimitBoundDivisor": "0x0400", - "registrar": "0x0000000000000000000000000000000000000000", - "accountStartNonce": "0x00", - "maximumExtraDataSize": "0x20", - "minGasLimit": "0x1388", - "networkID": "0x7", - "chainID": "0x7", - "eip150Transition": "0x0", - "eip160Transition": "0x0", - "eip155Transition": "0x0", - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" - }, - "genesis": { - "seal": { - "ethereum": { - "nonce": "0x0000000000000042", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "difficulty": "0x0400000000", - "author": "0x0000000000000000000000000000000000000000", - "timestamp": "0x00", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "extraData": "0x323031382045617374636f696e2050726f6a656374", - "gasLimit": "0x1388" - }, - "nodes": [ - "enode://ca57e40edb95a08a81b85a91e91099a0aaab777ad329ea7f3f772bc0fd511a276a5d84944725d181ff80f8c7dc1034814bff25b9723b03363d48617fed4b15f0@13.125.109.174:30303", - "enode://57254e23a7e5fe1e081ee5d1b236e37735a120660daeb4bf1fec6943a82c915c5b6fad23eeb1a43a27c23f236e084e8051aaa28f7d4139149f844747facb62bb@18.217.39.51:30303", - "enode://ef248f327c73c0318f4d51a62270b0612f3c4a4fd04b77d04854dc355980e137708d1e48811bc91387b0d7eb85cf447d8bbc095404f39bb7064e76751bda9cd4@52.221.160.236:30303", - "enode://bf6f0e37dd733cf04f2b079c753d2dea7cc7c59d8637eff9a8e63e17d08e2bfc91229fbb2dff08fe6ee12e51c1b6f8ed969d7042b89d77029e7ea02b05e17be3@18.197.47.177:30303" - ], - "accounts": { - "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, - "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, - "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "20c1252a8cb33a7a9a257b2a4cfeed8daf87c847": { - "balance": "100000000000000000000000000" - }, - "9dcd37c8e5aea3a0d37c5d0a2db683362d81febd": { - "balance": "100000000000000000000000000" - }, - "9eff080302333f44a60bfd8c33bd63015c6d921b": { - "balance": "100000000000000000000000000" - }, - "c1df2e5de98d5c41fec0642dc302971f5d3500bd": { - "balance": "100000000000000000000000000" - }, - "2e0fb67cd1d029cbaea4b74c361efcc06b3105fd": { - "balance": "100000000000000000000000000" - }, - "2b6425cc3cd90654f077889ef7262ac2f5846460": { - "balance": "100000000000000000000000000" - }, - "28562041230c6d575e233e4ed1b35c514884d964": { - "balance": "100000000000000000000000000" - }, - "16eb6896a5a83d39ac762d79d21f825f5f980d12": { - "balance": "100000000000000000000000000" - }, - "f09e3f1de27dd03a1ac0a021b2d9e45bde1b360c": { - "balance": "100000000000000000000000000" - }, - "2d87547819c6433f208ee3096161cdb2835a2333": { - "balance": "100000000000000000000000000" - } - } -} diff --git a/ethcore/res/ethereum/eip210_test.json b/ethcore/res/ethereum/eip210_test.json index adf7f2964e..782e99e5e9 100644 --- a/ethcore/res/ethereum/eip210_test.json +++ b/ethcore/res/ethereum/eip210_test.json @@ -46,8 +46,46 @@ "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 100 } } } }, - "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 2000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x00", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x00", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x00", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + } } } diff --git a/ethcore/res/ethereum/ellaism.json b/ethcore/res/ethereum/ellaism.json index 946b340f93..d1333fb7f3 100644 --- a/ethcore/res/ethereum/ellaism.json +++ b/ethcore/res/ethereum/ellaism.json @@ -66,8 +66,46 @@ "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 2000000, "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 2000000, "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 2000000, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 2000000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": 2000000, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": 2000000, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": 2000000, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + } } } diff --git a/ethcore/res/ethereum/ewc.json b/ethcore/res/ethereum/ewc.json new file mode 100644 index 0000000000..1290526504 --- /dev/null +++ b/ethcore/res/ethereum/ewc.json @@ -0,0 +1,213 @@ +{ + "name": "EnergyWebChain", + "engine": { + "authorityRound": { + "params": { + "stepDuration": "5", + "validators": { + "contract": "0x1204700000000000000000000000000000000000" + }, + "maximumUncleCountTransition": "0", + "maximumUncleCount": "0", + "blockRewardContractAddress": "0x1204700000000000000000000000000000000002", + "blockRewardContractTransition": "0" + } + } + }, + "params": { + "networkID": "0xF6", + "maximumExtraDataSize": "0x20", + "gasLimitBoundDivisor": "0x400", + "minGasLimit": "0x1388", + "maxCodeSize": "0x6000", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0", + "eip145Transition": "0x0", + "eip1014Transition": "0x0", + "eip1052Transition": "0x0", + "registrar": "0x1204700000000000000000000000000000000006" + }, + "genesis": { + "seal": { + "authorityRound": { + "step": "0x0", + "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x20000", + "gasLimit": "0x5B8D80" + }, + "accounts": { + "0x0000000000000000000000000000000000000001": { + "balance": "1", + "builtin": { + "name": "ecrecover", + "activate_at": "0", + "pricing": { + "linear": { + "base": 3000, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000002": { + "balance": "1", + "builtin": { + "name": "sha256", + "activate_at": "0", + "pricing": { + "linear": { + "base": 60, + "word": 12 + } + } + } + }, + "0x0000000000000000000000000000000000000003": { + "balance": "1", + "builtin": { + "name": "ripemd160", + "activate_at": "0", + "pricing": { + "linear": { + "base": 600, + "word": 120 + } + } + } + }, + "0x0000000000000000000000000000000000000004": { + "balance": "1", + "builtin": { + "name": "identity", + "activate_at": "0", + "pricing": { + "linear": { + "base": 15, + "word": 3 + } + } + } + }, + "0x0000000000000000000000000000000000000005": { + "balance": "1", + "builtin": { + "name": "modexp", + "activate_at": "0", + "pricing": { + "modexp": { + "divisor": 20 + } + } + } + }, + "0x0000000000000000000000000000000000000006": { + "balance": "1", + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0x0000000000000000000000000000000000000007": { + "balance": "1", + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0x0000000000000000000000000000000000000008": { + "balance": "1", + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, + "0x1204700000000000000000000000000000000005": { + "constructor": "0x60806040523480156200001157600080fd5b50604051620024c8380380620024c883398101806040528101908080518201929190602001805190602001909291905050506000825182603282111580156200005a5750818111155b801562000068575060008114155b801562000076575060008214155b15156200008257600080fd5b600092505b8451831015620001bd57600260008685815181101515620000a457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16158015620001335750600085848151811015156200011057fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1614155b15156200013f57600080fd5b60016002600087868151811015156200015457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550828060010193505062000087565b8460039080519060200190620001d5929190620001e8565b50836004819055505050505050620002bd565b82805482825590600052602060002090810192821562000264579160200282015b82811115620002635782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019062000209565b5b50905062000273919062000277565b5090565b620002ba91905b80821115620002b657600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016200027e565b5090565b90565b6121fb80620002cd6000396000f30060806040526004361061011d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063025e7c2714610177578063173825d9146101e457806320ea8d86146102275780632f54bf6e146102545780633411c81c146102af57806354741525146103145780637065cb4814610363578063784547a7146103a65780638b51d13f146103eb5780639ace38c21461042c578063a0e67e2b14610517578063a8abe69a14610583578063b5dc40c314610627578063b77bf600146106a9578063ba51a6df146106d4578063c01a8c8414610701578063c64274741461072e578063d74f8edd146107d5578063dc8452cd14610800578063e20056e61461082b578063ee22610b1461088e575b6000341115610175573373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a25b005b34801561018357600080fd5b506101a2600480360381019080803590602001909291905050506108bb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101f057600080fd5b50610225600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108f9565b005b34801561023357600080fd5b5061025260048036038101908080359060200190929190505050610b92565b005b34801561026057600080fd5b50610295600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d3a565b604051808215151515815260200191505060405180910390f35b3480156102bb57600080fd5b506102fa60048036038101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d5a565b604051808215151515815260200191505060405180910390f35b34801561032057600080fd5b5061034d600480360381019080803515159060200190929190803515159060200190929190505050610d89565b6040518082815260200191505060405180910390f35b34801561036f57600080fd5b506103a4600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e1b565b005b3480156103b257600080fd5b506103d160048036038101908080359060200190929190505050611020565b604051808215151515815260200191505060405180910390f35b3480156103f757600080fd5b5061041660048036038101908080359060200190929190505050611105565b6040518082815260200191505060405180910390f35b34801561043857600080fd5b50610457600480360381019080803590602001909291905050506111d0565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018060200183151515158152602001828103825284818151815260200191508051906020019080838360005b838110156104d95780820151818401526020810190506104be565b50505050905090810190601f1680156105065780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b34801561052357600080fd5b5061052c6112c5565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561056f578082015181840152602081019050610554565b505050509050019250505060405180910390f35b34801561058f57600080fd5b506105d06004803603810190808035906020019092919080359060200190929190803515159060200190929190803515159060200190929190505050611353565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156106135780820151818401526020810190506105f8565b505050509050019250505060405180910390f35b34801561063357600080fd5b50610652600480360381019080803590602001909291905050506114c4565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561069557808201518184015260208101905061067a565b505050509050019250505060405180910390f35b3480156106b557600080fd5b506106be611701565b6040518082815260200191505060405180910390f35b3480156106e057600080fd5b506106ff60048036038101908080359060200190929190505050611707565b005b34801561070d57600080fd5b5061072c600480360381019080803590602001909291905050506117c1565b005b34801561073a57600080fd5b506107bf600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061199e565b6040518082815260200191505060405180910390f35b3480156107e157600080fd5b506107ea6119bd565b6040518082815260200191505060405180910390f35b34801561080c57600080fd5b506108156119c2565b6040518082815260200191505060405180910390f35b34801561083757600080fd5b5061088c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506119c8565b005b34801561089a57600080fd5b506108b960048036038101908080359060200190929190505050611cdd565b005b6003818154811015156108ca57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561093557600080fd5b81600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561098e57600080fd5b6000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600091505b600160038054905003821015610b13578273ffffffffffffffffffffffffffffffffffffffff16600383815481101515610a2157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610b06576003600160038054905003815481101515610a7f57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600383815481101515610ab957fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610b13565b81806001019250506109eb565b6001600381818054905003915081610b2b91906120fe565b506003805490506004541115610b4a57610b49600380549050611707565b5b8273ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a2505050565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610beb57600080fd5b81336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610c5657600080fd5b8360008082815260200190815260200160002060030160009054906101000a900460ff16151515610c8657600080fd5b60006001600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e960405160405180910390a35050505050565b60026020528060005260406000206000915054906101000a900460ff1681565b60016020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600080600090505b600554811015610e1457838015610dc8575060008082815260200190815260200160002060030160009054906101000a900460ff16155b80610dfb5750828015610dfa575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b15610e07576001820191505b8080600101915050610d91565b5092915050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610e5557600080fd5b80600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515610eaf57600080fd5b8160008173ffffffffffffffffffffffffffffffffffffffff1614151515610ed657600080fd5b60016003805490500160045460328211158015610ef35750818111155b8015610f00575060008114155b8015610f0d575060008214155b1515610f1857600080fd5b6001600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060038590806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508473ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b6000806000809150600090505b6003805490508110156110fd5760016000858152602001908152602001600020600060038381548110151561105e57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156110dd576001820191505b6004548214156110f057600192506110fe565b808060010191505061102d565b5b5050919050565b600080600090505b6003805490508110156111ca5760016000848152602001908152602001600020600060038381548110151561113e57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156111bd576001820191505b808060010191505061110d565b50919050565b60006020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806001015490806002018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156112a85780601f1061127d576101008083540402835291602001916112a8565b820191906000526020600020905b81548152906001019060200180831161128b57829003601f168201915b5050505050908060030160009054906101000a900460ff16905084565b6060600380548060200260200160405190810160405280929190818152602001828054801561134957602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116112ff575b5050505050905090565b60608060008060055460405190808252806020026020018201604052801561138a5781602001602082028038833980820191505090505b50925060009150600090505b600554811015611436578580156113cd575060008082815260200190815260200160002060030160009054906101000a900460ff16155b8061140057508480156113ff575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b156114295780838381518110151561141457fe5b90602001906020020181815250506001820191505b8080600101915050611396565b8787036040519080825280602002602001820160405280156114675781602001602082028038833980820191505090505b5093508790505b868110156114b957828181518110151561148457fe5b906020019060200201518489830381518110151561149e57fe5b9060200190602002018181525050808060010191505061146e565b505050949350505050565b6060806000806003805490506040519080825280602002602001820160405280156114fe5781602001602082028038833980820191505090505b50925060009150600090505b60038054905081101561164b5760016000868152602001908152602001600020600060038381548110151561153b57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561163e576003818154811015156115c257fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811015156115fb57fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506001820191505b808060010191505061150a565b8160405190808252806020026020018201604052801561167a5781602001602082028038833980820191505090505b509350600090505b818110156116f957828181518110151561169857fe5b9060200190602002015184828151811015156116b057fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611682565b505050919050565b60055481565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561174157600080fd5b60038054905081603282111580156117595750818111155b8015611766575060008114155b8015611773575060008214155b151561177e57600080fd5b826004819055507fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a836040518082815260200191505060405180910390a1505050565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561181a57600080fd5b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151561187657600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515156118e257600080fd5b600180600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef60405160405180910390a361199785611cdd565b5050505050565b60006119ab848484611f85565b90506119b6816117c1565b9392505050565b603281565b60045481565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611a0457600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611a5d57600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515611ab757600080fd5b600092505b600380549050831015611ba0578473ffffffffffffffffffffffffffffffffffffffff16600384815481101515611aef57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611b935783600384815481101515611b4657fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611ba0565b8280600101935050611abc565b6000600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508473ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a28373ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b600033600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611d3857600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611da357600080fd5b8460008082815260200190815260200160002060030160009054906101000a900460ff16151515611dd357600080fd5b611ddc86611020565b15611f7d57600080878152602001908152602001600020945060018560030160006101000a81548160ff021916908315150217905550611efa8560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866001015487600201805460018160011615610100020316600290049050886002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611ef05780601f10611ec557610100808354040283529160200191611ef0565b820191906000526020600020905b815481529060010190602001808311611ed357829003601f168201915b50505050506120d7565b15611f3157857f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7560405160405180910390a2611f7c565b857f526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b7923660405160405180910390a260008560030160006101000a81548160ff0219169083151502179055505b5b505050505050565b60008360008173ffffffffffffffffffffffffffffffffffffffff1614151515611fae57600080fd5b60055491506080604051908101604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018481526020016000151581525060008084815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010155604082015181600201908051906020019061206d92919061212a565b5060608201518160030160006101000a81548160ff0219169083151502179055509050506001600560008282540192505081905550817fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5160405160405180910390a2509392505050565b6000806040516020840160008287838a8c6187965a03f19250505080915050949350505050565b8154818355818111156121255781836000526020600020918201910161212491906121aa565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061216b57805160ff1916838001178555612199565b82800160010185558215612199579182015b8281111561219857825182559160200191906001019061217d565b5b5090506121a691906121aa565b5090565b6121cc91905b808211156121c85760008160009055506001016121b0565b5090565b905600a165627a7a72305820b0d992f257e70d565448b927a3ae764342039a864112d5d5bb1ac1bd52e4104e00290000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000060000000000000000000000000cb1437200aea736788f1fc56f327c0456c3598d00000000000000000000000074dd76e24b2cfb43c1b1a4498295d553d0843746000000000000000000000000eeb4ceee443f9e0d17bdbd6daa241681ee5e51c2000000000000000000000000a005caea55375ae20e3aaef746113535503abc1900000000000000000000000090ae948bb410838bff9d024ed849df6a7267dacf000000000000000000000000740a5c5742833bed72489fe6bf7efc9b79428989" + }, + "0x1204700000000000000000000000000000000003": { + "constructor": "0x60806040523480156200001157600080fd5b50604051620024c8380380620024c883398101806040528101908080518201929190602001805190602001909291905050506000825182603282111580156200005a5750818111155b801562000068575060008114155b801562000076575060008214155b15156200008257600080fd5b600092505b8451831015620001bd57600260008685815181101515620000a457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16158015620001335750600085848151811015156200011057fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1614155b15156200013f57600080fd5b60016002600087868151811015156200015457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550828060010193505062000087565b8460039080519060200190620001d5929190620001e8565b50836004819055505050505050620002bd565b82805482825590600052602060002090810192821562000264579160200282015b82811115620002635782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019062000209565b5b50905062000273919062000277565b5090565b620002ba91905b80821115620002b657600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016200027e565b5090565b90565b6121fb80620002cd6000396000f30060806040526004361061011d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063025e7c2714610177578063173825d9146101e457806320ea8d86146102275780632f54bf6e146102545780633411c81c146102af57806354741525146103145780637065cb4814610363578063784547a7146103a65780638b51d13f146103eb5780639ace38c21461042c578063a0e67e2b14610517578063a8abe69a14610583578063b5dc40c314610627578063b77bf600146106a9578063ba51a6df146106d4578063c01a8c8414610701578063c64274741461072e578063d74f8edd146107d5578063dc8452cd14610800578063e20056e61461082b578063ee22610b1461088e575b6000341115610175573373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a25b005b34801561018357600080fd5b506101a2600480360381019080803590602001909291905050506108bb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101f057600080fd5b50610225600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108f9565b005b34801561023357600080fd5b5061025260048036038101908080359060200190929190505050610b92565b005b34801561026057600080fd5b50610295600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d3a565b604051808215151515815260200191505060405180910390f35b3480156102bb57600080fd5b506102fa60048036038101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d5a565b604051808215151515815260200191505060405180910390f35b34801561032057600080fd5b5061034d600480360381019080803515159060200190929190803515159060200190929190505050610d89565b6040518082815260200191505060405180910390f35b34801561036f57600080fd5b506103a4600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e1b565b005b3480156103b257600080fd5b506103d160048036038101908080359060200190929190505050611020565b604051808215151515815260200191505060405180910390f35b3480156103f757600080fd5b5061041660048036038101908080359060200190929190505050611105565b6040518082815260200191505060405180910390f35b34801561043857600080fd5b50610457600480360381019080803590602001909291905050506111d0565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018060200183151515158152602001828103825284818151815260200191508051906020019080838360005b838110156104d95780820151818401526020810190506104be565b50505050905090810190601f1680156105065780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b34801561052357600080fd5b5061052c6112c5565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561056f578082015181840152602081019050610554565b505050509050019250505060405180910390f35b34801561058f57600080fd5b506105d06004803603810190808035906020019092919080359060200190929190803515159060200190929190803515159060200190929190505050611353565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156106135780820151818401526020810190506105f8565b505050509050019250505060405180910390f35b34801561063357600080fd5b50610652600480360381019080803590602001909291905050506114c4565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561069557808201518184015260208101905061067a565b505050509050019250505060405180910390f35b3480156106b557600080fd5b506106be611701565b6040518082815260200191505060405180910390f35b3480156106e057600080fd5b506106ff60048036038101908080359060200190929190505050611707565b005b34801561070d57600080fd5b5061072c600480360381019080803590602001909291905050506117c1565b005b34801561073a57600080fd5b506107bf600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061199e565b6040518082815260200191505060405180910390f35b3480156107e157600080fd5b506107ea6119bd565b6040518082815260200191505060405180910390f35b34801561080c57600080fd5b506108156119c2565b6040518082815260200191505060405180910390f35b34801561083757600080fd5b5061088c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506119c8565b005b34801561089a57600080fd5b506108b960048036038101908080359060200190929190505050611cdd565b005b6003818154811015156108ca57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561093557600080fd5b81600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561098e57600080fd5b6000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600091505b600160038054905003821015610b13578273ffffffffffffffffffffffffffffffffffffffff16600383815481101515610a2157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610b06576003600160038054905003815481101515610a7f57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600383815481101515610ab957fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610b13565b81806001019250506109eb565b6001600381818054905003915081610b2b91906120fe565b506003805490506004541115610b4a57610b49600380549050611707565b5b8273ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a2505050565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610beb57600080fd5b81336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610c5657600080fd5b8360008082815260200190815260200160002060030160009054906101000a900460ff16151515610c8657600080fd5b60006001600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e960405160405180910390a35050505050565b60026020528060005260406000206000915054906101000a900460ff1681565b60016020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600080600090505b600554811015610e1457838015610dc8575060008082815260200190815260200160002060030160009054906101000a900460ff16155b80610dfb5750828015610dfa575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b15610e07576001820191505b8080600101915050610d91565b5092915050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610e5557600080fd5b80600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515610eaf57600080fd5b8160008173ffffffffffffffffffffffffffffffffffffffff1614151515610ed657600080fd5b60016003805490500160045460328211158015610ef35750818111155b8015610f00575060008114155b8015610f0d575060008214155b1515610f1857600080fd5b6001600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060038590806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508473ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b6000806000809150600090505b6003805490508110156110fd5760016000858152602001908152602001600020600060038381548110151561105e57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156110dd576001820191505b6004548214156110f057600192506110fe565b808060010191505061102d565b5b5050919050565b600080600090505b6003805490508110156111ca5760016000848152602001908152602001600020600060038381548110151561113e57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156111bd576001820191505b808060010191505061110d565b50919050565b60006020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806001015490806002018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156112a85780601f1061127d576101008083540402835291602001916112a8565b820191906000526020600020905b81548152906001019060200180831161128b57829003601f168201915b5050505050908060030160009054906101000a900460ff16905084565b6060600380548060200260200160405190810160405280929190818152602001828054801561134957602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116112ff575b5050505050905090565b60608060008060055460405190808252806020026020018201604052801561138a5781602001602082028038833980820191505090505b50925060009150600090505b600554811015611436578580156113cd575060008082815260200190815260200160002060030160009054906101000a900460ff16155b8061140057508480156113ff575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b156114295780838381518110151561141457fe5b90602001906020020181815250506001820191505b8080600101915050611396565b8787036040519080825280602002602001820160405280156114675781602001602082028038833980820191505090505b5093508790505b868110156114b957828181518110151561148457fe5b906020019060200201518489830381518110151561149e57fe5b9060200190602002018181525050808060010191505061146e565b505050949350505050565b6060806000806003805490506040519080825280602002602001820160405280156114fe5781602001602082028038833980820191505090505b50925060009150600090505b60038054905081101561164b5760016000868152602001908152602001600020600060038381548110151561153b57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561163e576003818154811015156115c257fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811015156115fb57fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506001820191505b808060010191505061150a565b8160405190808252806020026020018201604052801561167a5781602001602082028038833980820191505090505b509350600090505b818110156116f957828181518110151561169857fe5b9060200190602002015184828151811015156116b057fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611682565b505050919050565b60055481565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561174157600080fd5b60038054905081603282111580156117595750818111155b8015611766575060008114155b8015611773575060008214155b151561177e57600080fd5b826004819055507fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a836040518082815260200191505060405180910390a1505050565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561181a57600080fd5b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151561187657600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515156118e257600080fd5b600180600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef60405160405180910390a361199785611cdd565b5050505050565b60006119ab848484611f85565b90506119b6816117c1565b9392505050565b603281565b60045481565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611a0457600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611a5d57600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515611ab757600080fd5b600092505b600380549050831015611ba0578473ffffffffffffffffffffffffffffffffffffffff16600384815481101515611aef57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611b935783600384815481101515611b4657fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611ba0565b8280600101935050611abc565b6000600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508473ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a28373ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b600033600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611d3857600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611da357600080fd5b8460008082815260200190815260200160002060030160009054906101000a900460ff16151515611dd357600080fd5b611ddc86611020565b15611f7d57600080878152602001908152602001600020945060018560030160006101000a81548160ff021916908315150217905550611efa8560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866001015487600201805460018160011615610100020316600290049050886002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611ef05780601f10611ec557610100808354040283529160200191611ef0565b820191906000526020600020905b815481529060010190602001808311611ed357829003601f168201915b50505050506120d7565b15611f3157857f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7560405160405180910390a2611f7c565b857f526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b7923660405160405180910390a260008560030160006101000a81548160ff0219169083151502179055505b5b505050505050565b60008360008173ffffffffffffffffffffffffffffffffffffffff1614151515611fae57600080fd5b60055491506080604051908101604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018481526020016000151581525060008084815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010155604082015181600201908051906020019061206d92919061212a565b5060608201518160030160006101000a81548160ff0219169083151502179055509050506001600560008282540192505081905550817fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5160405160405180910390a2509392505050565b6000806040516020840160008287838a8c6187965a03f19250505080915050949350505050565b8154818355818111156121255781836000526020600020918201910161212491906121aa565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061216b57805160ff1916838001178555612199565b82800160010185558215612199579182015b8281111561219857825182559160200191906001019061217d565b5b5090506121a691906121aa565b5090565b6121cc91905b808211156121c85760008160009055506001016121b0565b5090565b905600a165627a7a72305820b0d992f257e70d565448b927a3ae764342039a864112d5d5bb1ac1bd52e4104e00290000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000060000000000000000000000000cb1437200aea736788f1fc56f327c0456c3598d00000000000000000000000074dd76e24b2cfb43c1b1a4498295d553d0843746000000000000000000000000eeb4ceee443f9e0d17bdbd6daa241681ee5e51c2000000000000000000000000a005caea55375ae20e3aaef746113535503abc1900000000000000000000000090ae948bb410838bff9d024ed849df6a7267dacf000000000000000000000000740a5c5742833bed72489fe6bf7efc9b79428989" + }, + "0x120470000000000000000000000000000000000a": { + "balance": "10901790566666700000000000", + "constructor": "0x60806040523480156200001157600080fd5b50604051620024c8380380620024c883398101806040528101908080518201929190602001805190602001909291905050506000825182603282111580156200005a5750818111155b801562000068575060008114155b801562000076575060008214155b15156200008257600080fd5b600092505b8451831015620001bd57600260008685815181101515620000a457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16158015620001335750600085848151811015156200011057fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1614155b15156200013f57600080fd5b60016002600087868151811015156200015457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550828060010193505062000087565b8460039080519060200190620001d5929190620001e8565b50836004819055505050505050620002bd565b82805482825590600052602060002090810192821562000264579160200282015b82811115620002635782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019062000209565b5b50905062000273919062000277565b5090565b620002ba91905b80821115620002b657600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016200027e565b5090565b90565b6121fb80620002cd6000396000f30060806040526004361061011d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063025e7c2714610177578063173825d9146101e457806320ea8d86146102275780632f54bf6e146102545780633411c81c146102af57806354741525146103145780637065cb4814610363578063784547a7146103a65780638b51d13f146103eb5780639ace38c21461042c578063a0e67e2b14610517578063a8abe69a14610583578063b5dc40c314610627578063b77bf600146106a9578063ba51a6df146106d4578063c01a8c8414610701578063c64274741461072e578063d74f8edd146107d5578063dc8452cd14610800578063e20056e61461082b578063ee22610b1461088e575b6000341115610175573373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a25b005b34801561018357600080fd5b506101a2600480360381019080803590602001909291905050506108bb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101f057600080fd5b50610225600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108f9565b005b34801561023357600080fd5b5061025260048036038101908080359060200190929190505050610b92565b005b34801561026057600080fd5b50610295600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d3a565b604051808215151515815260200191505060405180910390f35b3480156102bb57600080fd5b506102fa60048036038101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d5a565b604051808215151515815260200191505060405180910390f35b34801561032057600080fd5b5061034d600480360381019080803515159060200190929190803515159060200190929190505050610d89565b6040518082815260200191505060405180910390f35b34801561036f57600080fd5b506103a4600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e1b565b005b3480156103b257600080fd5b506103d160048036038101908080359060200190929190505050611020565b604051808215151515815260200191505060405180910390f35b3480156103f757600080fd5b5061041660048036038101908080359060200190929190505050611105565b6040518082815260200191505060405180910390f35b34801561043857600080fd5b50610457600480360381019080803590602001909291905050506111d0565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018060200183151515158152602001828103825284818151815260200191508051906020019080838360005b838110156104d95780820151818401526020810190506104be565b50505050905090810190601f1680156105065780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b34801561052357600080fd5b5061052c6112c5565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561056f578082015181840152602081019050610554565b505050509050019250505060405180910390f35b34801561058f57600080fd5b506105d06004803603810190808035906020019092919080359060200190929190803515159060200190929190803515159060200190929190505050611353565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156106135780820151818401526020810190506105f8565b505050509050019250505060405180910390f35b34801561063357600080fd5b50610652600480360381019080803590602001909291905050506114c4565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561069557808201518184015260208101905061067a565b505050509050019250505060405180910390f35b3480156106b557600080fd5b506106be611701565b6040518082815260200191505060405180910390f35b3480156106e057600080fd5b506106ff60048036038101908080359060200190929190505050611707565b005b34801561070d57600080fd5b5061072c600480360381019080803590602001909291905050506117c1565b005b34801561073a57600080fd5b506107bf600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061199e565b6040518082815260200191505060405180910390f35b3480156107e157600080fd5b506107ea6119bd565b6040518082815260200191505060405180910390f35b34801561080c57600080fd5b506108156119c2565b6040518082815260200191505060405180910390f35b34801561083757600080fd5b5061088c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506119c8565b005b34801561089a57600080fd5b506108b960048036038101908080359060200190929190505050611cdd565b005b6003818154811015156108ca57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561093557600080fd5b81600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561098e57600080fd5b6000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600091505b600160038054905003821015610b13578273ffffffffffffffffffffffffffffffffffffffff16600383815481101515610a2157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610b06576003600160038054905003815481101515610a7f57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600383815481101515610ab957fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610b13565b81806001019250506109eb565b6001600381818054905003915081610b2b91906120fe565b506003805490506004541115610b4a57610b49600380549050611707565b5b8273ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a2505050565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610beb57600080fd5b81336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610c5657600080fd5b8360008082815260200190815260200160002060030160009054906101000a900460ff16151515610c8657600080fd5b60006001600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e960405160405180910390a35050505050565b60026020528060005260406000206000915054906101000a900460ff1681565b60016020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600080600090505b600554811015610e1457838015610dc8575060008082815260200190815260200160002060030160009054906101000a900460ff16155b80610dfb5750828015610dfa575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b15610e07576001820191505b8080600101915050610d91565b5092915050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610e5557600080fd5b80600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515610eaf57600080fd5b8160008173ffffffffffffffffffffffffffffffffffffffff1614151515610ed657600080fd5b60016003805490500160045460328211158015610ef35750818111155b8015610f00575060008114155b8015610f0d575060008214155b1515610f1857600080fd5b6001600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060038590806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508473ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b6000806000809150600090505b6003805490508110156110fd5760016000858152602001908152602001600020600060038381548110151561105e57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156110dd576001820191505b6004548214156110f057600192506110fe565b808060010191505061102d565b5b5050919050565b600080600090505b6003805490508110156111ca5760016000848152602001908152602001600020600060038381548110151561113e57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156111bd576001820191505b808060010191505061110d565b50919050565b60006020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806001015490806002018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156112a85780601f1061127d576101008083540402835291602001916112a8565b820191906000526020600020905b81548152906001019060200180831161128b57829003601f168201915b5050505050908060030160009054906101000a900460ff16905084565b6060600380548060200260200160405190810160405280929190818152602001828054801561134957602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116112ff575b5050505050905090565b60608060008060055460405190808252806020026020018201604052801561138a5781602001602082028038833980820191505090505b50925060009150600090505b600554811015611436578580156113cd575060008082815260200190815260200160002060030160009054906101000a900460ff16155b8061140057508480156113ff575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b156114295780838381518110151561141457fe5b90602001906020020181815250506001820191505b8080600101915050611396565b8787036040519080825280602002602001820160405280156114675781602001602082028038833980820191505090505b5093508790505b868110156114b957828181518110151561148457fe5b906020019060200201518489830381518110151561149e57fe5b9060200190602002018181525050808060010191505061146e565b505050949350505050565b6060806000806003805490506040519080825280602002602001820160405280156114fe5781602001602082028038833980820191505090505b50925060009150600090505b60038054905081101561164b5760016000868152602001908152602001600020600060038381548110151561153b57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561163e576003818154811015156115c257fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811015156115fb57fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506001820191505b808060010191505061150a565b8160405190808252806020026020018201604052801561167a5781602001602082028038833980820191505090505b509350600090505b818110156116f957828181518110151561169857fe5b9060200190602002015184828151811015156116b057fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611682565b505050919050565b60055481565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561174157600080fd5b60038054905081603282111580156117595750818111155b8015611766575060008114155b8015611773575060008214155b151561177e57600080fd5b826004819055507fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a836040518082815260200191505060405180910390a1505050565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561181a57600080fd5b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151561187657600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515156118e257600080fd5b600180600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef60405160405180910390a361199785611cdd565b5050505050565b60006119ab848484611f85565b90506119b6816117c1565b9392505050565b603281565b60045481565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611a0457600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611a5d57600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515611ab757600080fd5b600092505b600380549050831015611ba0578473ffffffffffffffffffffffffffffffffffffffff16600384815481101515611aef57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611b935783600384815481101515611b4657fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611ba0565b8280600101935050611abc565b6000600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508473ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a28373ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b600033600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611d3857600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611da357600080fd5b8460008082815260200190815260200160002060030160009054906101000a900460ff16151515611dd357600080fd5b611ddc86611020565b15611f7d57600080878152602001908152602001600020945060018560030160006101000a81548160ff021916908315150217905550611efa8560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866001015487600201805460018160011615610100020316600290049050886002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611ef05780601f10611ec557610100808354040283529160200191611ef0565b820191906000526020600020905b815481529060010190602001808311611ed357829003601f168201915b50505050506120d7565b15611f3157857f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7560405160405180910390a2611f7c565b857f526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b7923660405160405180910390a260008560030160006101000a81548160ff0219169083151502179055505b5b505050505050565b60008360008173ffffffffffffffffffffffffffffffffffffffff1614151515611fae57600080fd5b60055491506080604051908101604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018481526020016000151581525060008084815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010155604082015181600201908051906020019061206d92919061212a565b5060608201518160030160006101000a81548160ff0219169083151502179055509050506001600560008282540192505081905550817fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5160405160405180910390a2509392505050565b6000806040516020840160008287838a8c6187965a03f19250505080915050949350505050565b8154818355818111156121255781836000526020600020918201910161212491906121aa565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061216b57805160ff1916838001178555612199565b82800160010185558215612199579182015b8281111561219857825182559160200191906001019061217d565b5b5090506121a691906121aa565b5090565b6121cc91905b808211156121c85760008160009055506001016121b0565b5090565b905600a165627a7a72305820b0d992f257e70d565448b927a3ae764342039a864112d5d5bb1ac1bd52e4104e00290000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000060000000000000000000000000cb1437200aea736788f1fc56f327c0456c3598d00000000000000000000000074dd76e24b2cfb43c1b1a4498295d553d0843746000000000000000000000000eeb4ceee443f9e0d17bdbd6daa241681ee5e51c2000000000000000000000000a005caea55375ae20e3aaef746113535503abc1900000000000000000000000090ae948bb410838bff9d024ed849df6a7267dacf000000000000000000000000740a5c5742833bed72489fe6bf7efc9b79428989" + }, + "0x0cB1437200aea736788f1Fc56F327c0456c3598D": { + "balance": "250000000000000000" + }, + "0x74dd76E24B2CFB43C1b1a4498295d553D0843746": { + "balance": "250000000000000000" + }, + "0xeeB4CEEe443F9e0D17BdBD6Daa241681EE5E51c2": { + "balance": "250000000000000000" + }, + "0xA005caEa55375ae20e3aAEF746113535503ABC19": { + "balance": "250000000000000000" + }, + "0x90ae948bB410838bff9D024ed849dF6A7267Dacf": { + "balance": "250000000000000000" + }, + "0x740a5C5742833bEd72489fE6bf7EFc9B79428989": { + "balance": "250000000000000000" + }, + "0x1204700000000000000000000000000000000001": { + "constructor": "0x60806040523480156200001157600080fd5b5060405162002d7138038062002d71833981018060405260608110156200003757600080fd5b81019080805190602001909291908051906020019092919080516401000000008111156200006457600080fd5b828101905060208101848111156200007b57600080fd5b81518560208202830111640100000000821117156200009957600080fd5b5050929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018062002d216024913960400191505060405180910390fd5b60018151101562000242576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018062002d45602c913960400191505060405180910390fd5b62000253836200046160201b60201c565b6200026482620005c360201b60201c565b60008090505b81518110156200040e57600073ffffffffffffffffffffffffffffffffffffffff168282815181106200029957fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614156200032c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f56616c696461746f7220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b6001600360008484815181106200033f57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff02191690836003811115620003a057fe5b02179055508060036000848481518110620003b757fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018190555080806001019150506200026a565b508060029080519060200190620004279291906200064a565b50600260019080546200043c929190620006d9565b506001600060146101000a81548160ff02191690831515021790555050505062000776565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141562000505576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6577206f776e657220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b80600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fe8ec518081a7aa1fc5d586a5443a858ab130be8b8e39b545172c879a7e242c6b60405160405180910390a250565b828054828255906000526020600020908101928215620006c6579160200282015b82811115620006c55782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906200066b565b5b509050620006d5919062000730565b5090565b8280548282559060005260206000209081019282156200071d5760005260206000209182015b828111156200071c578254825591600101919060010190620006ff565b5b5090506200072c919062000730565b5090565b6200077391905b808211156200076f57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555060010162000737565b5090565b90565b61259b80620007866000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c80639f723637116100b8578063b98049091161007c578063b980490914610562578063bd21442a146105be578063c805f68b14610681578063d826b7f1146106c5578063f2fde38b14610733578063f3aeac021461077757610137565b80639f723637146103dc578063a00745b61461043b578063a6940b0714610497578063b3f05b97146104e1578063b7ab4db51461050357610137565b8063455701d6116100ff578063455701d6146102c35780634d238c8e1461032257806375286211146103665780638da5cb5b146103705780638f32d59b146103ba57610137565b8063267fa41d1461013c57806334ba3c1b1461019857806340550a1c146101b657806340a141ff146102125780634183495514610256575b600080fd5b61017e6004803603602081101561015257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107d3565b604051808215151515815260200191505060405180910390f35b6101a0610845565b6040518082815260200191505060405180910390f35b6101f8600480360360208110156101cc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610852565b604051808215151515815260200191505060405180910390f35b6102546004803603602081101561022857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610933565b005b6102986004803603602081101561026c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610a7e565b604051808360038111156102a857fe5b60ff1681526020018281526020019250505060405180910390f35b6102cb610aaf565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561030e5780820151818401526020810190506102f3565b505050509050019250505060405180910390f35b6103646004803603602081101561033857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b3d565b005b61036e610d47565b005b6103786111b2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103c26111db565b604051808215151515815260200191505060405180910390f35b6103e4611232565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561042757808201518184015260208101905061040c565b505050509050019250505060405180910390f35b61047d6004803603602081101561045157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611361565b604051808215151515815260200191505060405180910390f35b61049f611442565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104e9611468565b604051808215151515815260200191505060405180910390f35b61050b61147b565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561054e578082015181840152602081019050610533565b505050509050019250505060405180910390f35b6105a46004803603602081101561057857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611509565b604051808215151515815260200191505060405180910390f35b61067f600480360360808110156105d457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561063b57600080fd5b82018360208201111561064d57600080fd5b8035906020019184600183028401116401000000008311171561066f57600080fd5b909192939192939050505061157a565b005b6106c36004803603602081101561069757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506117d6565b005b610731600480360360608110156106db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611989565b005b6107756004803603602081101561074957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611be3565b005b6107b96004803603602081101561078d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611c69565b604051808215151515815260200191505060405180910390f35b6000600160038111156107e257fe5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16600381111561083d57fe5b149050919050565b6000600180549050905090565b60006001600381111561086157fe5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1660038111156108bc57fe5b148061092c57506003808111156108cf57fe5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16600381111561092a57fe5b145b9050919050565b61093b6111db565b6109ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b600060149054906101000a900460ff16610a12576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806124e16022913960400191505060405180910390fd5b80610a1c81610852565b610a71576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806124bf6022913960400191505060405180910390fd5b610a7a82611cdb565b5050565b60036020528060005260406000206000915090508060000160009054906101000a900460ff16908060010154905082565b60606002805480602002602001604051908101604052809291908181526020018280548015610b3357602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610ae9575b5050505050905090565b610b456111db565b610bb7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b600060149054906101000a900460ff16610c1c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806124e16022913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610cbf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f56616c696461746f7220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b610cc881610852565b15610d3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f546869732076616c696461746f7220697320616c72656164792061637469766581525060200191505060405180910390fd5b610d4481611f2e565b50565b600060149054906101000a900460ff1615610dca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f56616c696461746f72207365742069732066696e616c697a656400000000000081525060200191505060405180910390fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e8d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616c6c6572206973206e6f74207468652052656c617920636f6e747261637481525060200191505060405180910390fd5b6001600060146101000a81548160ff021916908315150217905550600073ffffffffffffffffffffffffffffffffffffffff16600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610fbe57600060036000600260016002805490500381548110610f1a57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060018160000160006101000a81548160ff02191690836003811115610fa257fe5b02179055506001600280549050038160010181905550506110f1565b600060036000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083600381111561103f57fe5b0217905550600060036000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b6002600190805461110392919061238d565b507f8564cd629b15f47dc310d45bcbfc9bcf5420b0d51bf0659a16c67f91d27632536001604051808060200182810382528381815481526020019150805480156111a257602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611158575b50509250505060405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b606060018054905060028054905011156112d45760028054806020026020016040519081016040528092919081815260200182805480156112c857602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161127e575b5050505050905061135e565b600180548060200260200160405190810160405280929190818152602001828054801561135657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161130c575b505050505090505b90565b60006002600381111561137057fe5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1660038111156113cb57fe5b148061143b57506003808111156113de57fe5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16600381111561143957fe5b145b9050919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060149054906101000a900460ff1681565b606060018054806020026020016040519081016040528092919081815260200182805480156114ff57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116114b5575b5050505050905090565b600060038081111561151757fe5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16600381111561157257fe5b149050919050565b8461158481610852565b6115d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806124bf6022913960400191505060405180910390fd5b846115e381610852565b611638576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806124bf6022913960400191505060405180910390fd5b844381106116ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f426c6f636b206e756d626572206973206e6f742076616c69640000000000000081525060200191505060405180910390fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611771576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616c6c6572206973206e6f74207468652052656c617920636f6e747261637481525060200191505060405180910390fd5b858773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff167f729a19138e072a5a8d3a56d74ae0b5c84530f09aacd6e12b24c5b2fdc3f8a3d060405160405180910390a45050505050505050565b6117de6111db565b611850576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156118d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806124746024913960400191505060405180910390fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561197d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260408152602001806125036040913960400191505060405180910390fd5b61198681612003565b50565b8261199381610852565b6119e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806124bf6022913960400191505060405180910390fd5b826119f281610852565b611a47576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806124bf6022913960400191505060405180910390fd5b82438110611abd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f426c6f636b206e756d626572206973206e6f742076616c69640000000000000081525060200191505060405180910390fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b80576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616c6c6572206973206e6f74207468652052656c617920636f6e747261637481525060200191505060405180910390fd5b838573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fbc459bd9db54016b1966d0fe812bbe0a82cd627ae3eacd01727dc63a432ca41b60405160405180910390a4505050505050565b611beb6111db565b611c5d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b611c668161208a565b50565b600060026003811115611c7857fe5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff166003811115611cd357fe5b149050919050565b600160028054905011611d39576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806124986027913960400191505060405180910390fd5b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154905060006001600280549050039050600060028281548110611d9c57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508060028481548110611dd757fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506002805480919060019003611e7b91906123df565b5060038060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff02191690836003811115611eda57fe5b021790555083600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611f286121eb565b50505050565b6002600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff02191690836003811115611f8d57fe5b021790555060028190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506120006121eb565b50565b80600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fe8ec518081a7aa1fc5d586a5443a858ab130be8b8e39b545172c879a7e242c6b60405160405180910390a250565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561212d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6577206f776e657220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008060146101000a81548160ff021916908315150217905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a084718a600143034060026040518363ffffffff1660e01b8152600401808381526020018060200182810382528381815481526020019150805480156122da57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311612290575b50509350505050602060405180830381600087803b1580156122fb57600080fd5b505af115801561230f573d6000803e3d6000fd5b505050506040513d602081101561232557600080fd5b810190808051906020019092919050505061238b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180612543602d913960400191505060405180910390fd5b565b8280548282559060005260206000209081019282156123ce5760005260206000209182015b828111156123cd5782548255916001019190600101906123b2565b5b5090506123db919061240b565b5090565b81548183558181111561240657818360005260206000209182019101612405919061244e565b5b505050565b61244b91905b8082111561244757600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550600101612411565b5090565b90565b61247091905b8082111561246c576000816000905550600101612454565b5090565b9056fe52656c617920636f6e747261637420616464726573732063616e6e6f74206265203078305468657265206d757374206265206174206c6561737420312076616c696461746f72206c65667441646472657373206973206e6f7420616e206163746976652076616c696461746f7256616c696461746f7220736574206973206e6f742066696e616c697a6564207965744e65772072656c617920636f6e747261637420616464726573732063616e6e6f74206265207468652073616d65206173207468652063757272656e74206f6e6552656c617920636f6e747261637420496e6974696174654368616e67652063616c6c6261636b206661696c6564a165627a7a72305820f9ae418c0431b0892a4b904426be15d82d8486d433a3d6b9814bd5d1a377bb30002952656c617920636f6e747261637420616464726573732063616e6e6f74206265203078305468657265206d757374206265206174206c6561737420312076616c696461746f7220696e697469616c6c790000000000000000000000001204700000000000000000000000000000000005000000000000000000000000120470000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000003000000000000000000000000d65b4c25a4ce1e024ff13425df1e0e574a1a0e9b00000000000000000000000083329c3fd90d7ee2efd546e0dc6453e9172a0643000000000000000000000000de15831ac319dab5eae5fd1fd9d52876c5e50f20" + }, + "0x1204700000000000000000000000000000000000": { + "constructor": "0x608060405273fffffffffffffffffffffffffffffffffffffffe600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561006557600080fd5b506040516040806114d48339810180604052604081101561008557600080fd5b810190808051906020019092919080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a361016b8261018160201b60201c565b61017a816102e260201b60201c565b50506104f4565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610224576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6577206f776e657220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610386576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416464726573732063616e6e6f7420626520307830000000000000000000000081525060200191505060405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561042d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260428152602001806114926042913960600191505060405180910390fd5b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f4fea88aaf04c303804bb211ecc32a00ac8e5f0656bb854cad8a4a2e438256b7460405160405180910390a3505050565b610f8f806105036000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063b7ab4db511610071578063b7ab4db514610209578063bd96567714610268578063c476dd40146102ac578063d3e848f11461034f578063d69f13bb14610399578063f2fde38b146103e7576100a9565b806375286211146100ae5780638da5cb5b146100b85780638f32d59b14610102578063a084718a14610124578063ae3783d6146101bf575b600080fd5b6100b661042b565b005b6100c0610572565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61010a61059b565b604051808215151515815260200191505060405180910390f35b6101a56004803603604081101561013a57600080fd5b81019080803590602001909291908035906020019064010000000081111561016157600080fd5b82018360208201111561017357600080fd5b8035906020019184602083028401116401000000008311171561019557600080fd5b90919293919293905050506105f2565b604051808215151515815260200191505060405180910390f35b6101c761070c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610211610732565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610254578082015181840152602081019050610239565b505050509050019250505060405180910390f35b6102aa6004803603602081101561027e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610832565b005b61034d600480360360608110156102c257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561030957600080fd5b82018360208201111561031b57600080fd5b8035906020019184600183028401116401000000008311171561033d57600080fd5b90919293919293905050506108b8565b005b6103576109e7565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103e5600480360360408110156103af57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610a0d565b005b610429600480360360208110156103fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b06565b005b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f53656e646572206973206e6f742073797374656d00000000000000000000000081525060200191505060405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663752862116040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561055857600080fd5b505af115801561056c573d6000803e3d6000fd5b50505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461069a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610f426022913960400191505060405180910390fd5b837f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89848460405180806020018281038252848482818152602001925060200280828437600081840152601f19601f820116905080830192505050935050505060405180910390a2600190509392505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b7ab4db56040518163ffffffff1660e01b815260040160006040518083038186803b15801561079c57600080fd5b505afa1580156107b0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156107da57600080fd5b8101908080516401000000008111156107f257600080fd5b8281019050602081018481111561080857600080fd5b815185602082028301116401000000008211171561082557600080fd5b5050929190505050905090565b61083a61059b565b6108ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b6108b581610b8c565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bd21442a33868686866040518663ffffffff1660e01b8152600401808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509650505050505050600060405180830381600087803b1580156109c957600080fd5b505af11580156109dd573d6000803e3d6000fd5b5050505050505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d826b7f13384846040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050600060405180830381600087803b158015610aea57600080fd5b505af1158015610afe573d6000803e3d6000fd5b505050505050565b610b0e61059b565b610b80576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b610b8981610d9e565b50565b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610c30576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416464726573732063616e6e6f7420626520307830000000000000000000000081525060200191505060405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526042815260200180610f006042913960600191505060405180910390fd5b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f4fea88aaf04c303804bb211ecc32a00ac8e5f0656bb854cad8a4a2e438256b7460405160405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610e41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6577206f776e657220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fe4e65772072656c6179656420636f6e747261637420616464726573732063616e6e6f74206265207468652073616d65206173207468652063757272656e74206f6e6553656e646572206973206e6f74207468652052656c6179656420636f6e7472616374a165627a7a723058204045b88d4bc25183a0d657cfec6f8f8b976fd6aca20ab02e07cc6d76f43e7bd100294e65772072656c6179656420636f6e747261637420616464726573732063616e6e6f74206265207468652073616d65206173207468652063757272656e74206f6e6500000000000000000000000012047000000000000000000000000000000000050000000000000000000000001204700000000000000000000000000000000001" + }, + "0x1204700000000000000000000000000000000002": { + "constructor": "0x608060405273fffffffffffffffffffffffffffffffffffffffe600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200006657600080fd5b5060405160408062001bad833981018060405260408110156200008857600080fd5b810190808051906020019092919080519060200190929190505050620000b36200016360201b60201c565b60786000805490501462000113576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018062001b866027913960400191505060405180910390fd5b81600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600a81905550505062000878565b60405180610f0001604052806704398372e97bae8081526020016704398372e97bae8081526020016704398372e97bae8081526020016704398372e97bae8081526020016704398372e97bae8081526020016704398372e97bae8081526020016704398372e97bae8081526020016704395680a6af46808152602001670438cfa9de4a0e808152602001670437eeee904c06808152602001670436b44ebcb52e8081526020016704351fca638586808152602001670433316184bd0e808152602001670430e914205bc680815260200167042e46e23661ae80815260200167042b4acbc6cec6808152602001670427f4d0d1a30e80815260200167042444f156de868081526020016704203b2d56812e80815260200167041bd784d08b0680815260200167041719f7c4fc0e808152602001670412028633d44680815260200167040c91301d13ae808152602001670406c5f580ba46808152602001670400a0d65ec80e8081526020016703fa21d2b73d068081526020016703f348ea8a192e8081526020016703ec161dd75c868081526020016703e4896c9f070e8081526020016703dca2d6e118c68081526020016703d4625c9d91ae8081526020016703cbc7fdd471c68081526020016703c2d3ba85b90e8081526020016703b98592b167868081526020016703afdd86577d2e8081526020016703a5db9577fa0680815260200167039b7fc012de0e808152602001670390ca06282946808152602001670385ba67b7dbae80815260200167037a50e4c1f54680815260200167036e8d7d46760e8081526020016703627031455e06808152602001670355f900bead2e80815260200167034927ebb2638680815260200167033bfcf220810e80815260200167032e78140905c680815260200167032099516bf1ae80815260200167031260aa4944c6808152602001670303ce1ea0ff0e8081526020016702f4e1ae7320868081526020016702e59b59bfa92e8081526020016702d5fb208699068081526020016702c60102c7f00e8081526020016702b5ad0083ae468081526020016702a4ff19b9d3ae808152602001670293f74e6a6046808152602001670282959e95540e808152602001670270da0a3aaf0680815260200167025ec4915a712e80815260200167024c5533f49a86808152602001670238da1d6b04400081526020016702260c5cdf4d240081526020016702138f83989f90008152602001670201639196fb840081526020016701ef8886da61000081526020016701ddfe6362d0040081526020016701ccc5273048900081526020016701bbdcd242caa40081526020016701ab45649a564000815260200167019afede36eb6400815260200167018b093f188a1000815260200167017b64873f324400815260200167016c10b6aae40000815260200167015d0dcd5b9f4400815260200167014e5bcb51641000815260200167013ffab08c3264008152602001670131ea7d0c0a400081526020016701242b30d0eba4008152602001670116bccbdad6900081526020016701099f4e29cb0400815260200166fcd2b7bdc90000815260200166f0570896d08400815260200166e42c40b4e19000815260200166d8526017fc2400815260200166ccc966c0204000815260200166c19154ad4de400815260200166b6aa29df851000815260200166ac13e656c5c400815260200166a1ce8a1310000081526020016697da151463c4008152602001668e36875ac1100081526020016684e3e0e627e4008152602001667be221b6984000815260200166733149cc1224008152602001666ad1592695900081526020016662c24fc62284008152602001665b042daab900008152602001665396f2d45904008152602001664c7a9f4302900081526020016645af32f6b5a4008152602001663f34adef724000815260200166390b102d386400815260200166333259b00810008152602001662daa8a77e144008152602001662873a284c40000815260200166238da1d6b044008152602001661ef8886da610008152602001661ab45649a5640081526020016616c10b6aae4000815260200166131ea7d0c0a4008152602001660fcd2b7bdc90008152602001660ccc966c0204008152602001660a1ce8a131000081526020016607be221b69840081526020016605b042daab900081526020016603f34adef7240081526020016602873a284c4000815260200166016c10b6aae400815260200165a1ce8a1310008152602001652873a284c4008152506000906078620007e5929190620007fe565b5062080520600181905550607860015402600281905550565b8280548282559060005260206000209081019282156200083d579160200282015b828111156200083c5782518255916020019190600101906200081f565b5b5090506200084c919062000850565b5090565b6200087591905b808211156200087157600081600090555060010162000857565b5090565b90565b6112fe80620008886000396000f3fe608060405234801561001057600080fd5b50600436106101205760003560e01c80634476d66a116100ad57806394f7f62b1161007157806394f7f62b1461045d578063df6a50301461049f578063e6e100db146104bd578063f91c289814610515578063fb1ac5251461068057610120565b80634476d66a146103515780634f4013fb14610393578063553a5c85146103b157806358ceb672146103cf57806360d4b8be146103d957610120565b80631a488047116100f45780631a488047146101f157806330f6eb161461020f57806333ea51a81461027157806337339a16146102b55780633d84b8c1146102f957610120565b8062f380f414610125578063078d8e7a1461016f5780630f411cdb1461019157806318129375146101af575b600080fd5b61012d61069e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101776106c4565b604051808215151515815260200191505060405180910390f35b6101996106d4565b6040518082815260200191505060405180910390f35b6101db600480360360208110156101c557600080fd5b81019080803590602001909291905050506106da565b6040518082815260200191505060405180910390f35b6101f96106fb565b6040518082815260200191505060405180910390f35b61025b6004803603604081101561022557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610701565b6040518082815260200191505060405180910390f35b6102b36004803603602081101561028757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610726565b005b6102f7600480360360208110156102cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107a7565b005b61033b6004803603602081101561030f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108ae565b6040518082815260200191505060405180910390f35b61037d6004803603602081101561036757600080fd5b81019080803590602001909291905050506108c6565b6040518082815260200191505060405180910390f35b61039b6108de565b6040518082815260200191505060405180910390f35b6103b96108e3565b6040518082815260200191505060405180910390f35b6103d76108e9565b005b61041b600480360360208110156103ef57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061094d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104896004803603602081101561047357600080fd5b8101908080359060200190929190505050610980565b6040518082815260200191505060405180910390f35b6104a76109c4565b6040518082815260200191505060405180910390f35b6104ff600480360360208110156104d357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506109ca565b6040518082815260200191505060405180910390f35b6105e16004803603604081101561052b57600080fd5b810190808035906020019064010000000081111561054857600080fd5b82018360208201111561055a57600080fd5b8035906020019184602083028401116401000000008311171561057c57600080fd5b90919293919293908035906020019064010000000081111561059d57600080fd5b8201836020820111156105af57600080fd5b803590602001918460208302840111640100000000831117156105d157600080fd5b90919293919293905050506109e2565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561062857808201518184015260208101905061060d565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561066a57808201518184015260208101905061064f565b5050505090500194505050505060405180910390f35b610688610edb565b6040518082815260200191505060405180910390f35b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006106cf43610ee1565b905090565b60025481565b600081815481106106e757fe5b906000526020600020016000915090505481565b600a5481565b6008602052816000526040600020602052806000526040600020600091509150505481565b80600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461086a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616c6c6572206973206e6f742074686520636f6d6d756e6974792066756e6481525060200191505060405180910390fd5b80600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60066020528060005260406000206000915090505481565b60076020528060005260406000206000915090505481565b607881565b60035481565b600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055565b600c6020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061098b82610ee1565b1561099957600090506109bf565b600060015483816109a657fe5b04815481106109b157fe5b906000526020600020015490505b919050565b60045481565b60056020528060005260406000206000915090505481565b606080600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610aa8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f43616c6c6572206973206e6f74207468652073797374656d000000000000000081525060200191505060405180910390fd5b838390508686905014610b06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806112ae6025913960400191505060405180910390fd5b60018686905014610b7f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f42656e65666163746f7273206c697374206c656e677468206973206e6f74203181525060200191505060405180910390fd5b600084846000818110610b8e57fe5b9050602002013561ffff1661ffff1614610bf3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061128c6022913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1686866000818110610c1857fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161480610c5c5750610c5b43610ee1565b5b15610cd2576000604051908082528060200260200182016040528015610c915781602001602082028038833980820191505090505b506000604051908082528060200260200182016040528015610cc25781602001602082028038833980820191505090505b5081915080905091509150610ed2565b60606002604051908082528060200260200182016040528015610d045781602001602082028038833980820191505090505b50905060608151604051908082528060200260200182016040528015610d395781602001602082028038833980820191505090505b509050610d6e88886000818110610d4c57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff16610ef0565b82600081518110610d7b57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610dbe43610980565b81600081518110610dcb57fe5b602002602001018181525050610e02600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16610ef0565b82600181518110610e0f57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600a5481600181518110610e5957fe5b602002602001018181525050610e9782600081518110610e7557fe5b602002602001015182600081518110610e8a57fe5b6020026020010151610f9d565b610ec982600181518110610ea757fe5b602002602001015182600181518110610ebc57fe5b6020026020010151611145565b81819350935050505b94509492505050565b60015481565b60006002548210159050919050565b600080600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610f935782915050610f98565b809150505b919050565b61100081600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060004381526020019081526020016000205461120390919063ffffffff16565b600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000438152602001908152602001600020819055506110a681600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461120390919063ffffffff16565b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061110f81600760004381526020019081526020016000205461120390919063ffffffff16565b600760004381526020019081526020016000208190555061113b8160035461120390919063ffffffff16565b6003819055505050565b61115a8160045461120390919063ffffffff16565b6004819055506111b281600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461120390919063ffffffff16565b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506111ff8282610f9d565b5050565b600080828401905083811015611281576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f4f766572666c6f77206572726f7200000000000000000000000000000000000081525060200191505060405180910390fd5b809150509291505056fe42656e65666163746f72206973206e6f742074686520626c6f636b20617574686f7242656e65666163746f72732f7479706573206c697374206c656e6774682064696666657273a165627a7a72305820ef1c2590551666e2ac227034529ee69c33ec91868d23c0a0a887d514094ec6030029526577617264206375727665206973206e6f7420746865207265717569726564206c656e67746800000000000000000000000012047000000000000000000000000000000000030000000000000000000000000000000000000000000000000856d3dfb6e26d00" + }, + "0x1204700000000000000000000000000000000004": { + "balance": "41198207933333333690000000", + "constructor": "0x608060405260006001556a22140f53c2d216263ba2803073ffffffffffffffffffffffffffffffffffffffff16311462000085576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806200150b6023913960400191505060405180910390fd5b620000956200010260201b60201c565b6a22140f53c2d216263ba28060015414620000fc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180620014ba6028913960400191505060405180910390fd5b62001133565b62000136722d4606b65c033769968bcdc63881b90b0853f569264876ff9c85a7a8ee00635df22bc06200105960201b60201c565b6200016a726e371c454a2d081f3966c180ba2c6165d87de66901c3c03b52c63f027880635df22bc06200105960201b60201c565b6200019e72c2f65230815d30eaa1a4d057bcf0b72fe3cc4e6902a5a058fc295ed00000635df22bc06200105960201b60201c565b620001d37303cccdc799d4dc37d56e3f9dba7f9c210fa1086f6902a5a058fc295ed00000635df22bc06200105960201b60201c565b6200020873047d955877a55fbdac768573a9259f29b103a0666902a5a058fc295ed00000635df22bc06200105960201b60201c565b6200023d7306920bb91f7027176cf373996d39b539ba436d876969e10de76676d0800000635d79dee06200105960201b60201c565b620002727306fdb93aa64f33a8fb40a36c462a3f7a074d632c6901c3c03b52c63f027880635df22bc06200105960201b60201c565b620002a7730ad7ba4af33b485e6f2505c417554631a3e5643f6902a5a058fc295ed00000635df22bc06200105960201b60201c565b620002dc730dd959deb4c458cc2ac379898bf2c99f7a8f399b6901c3c03b52c63f027880635df22bc06200105960201b60201c565b62000311731153818a2eb49f0a71b27313c32814fc02e4db50694220bb939da668600000635df22bc06200105960201b60201c565b6200034773120470000000000000000000000000000000000a6a084595161401484a000000635d79dee06200105960201b60201c565b6200037c7315696134ebeed360dc90dc97ddd00bd07e1c11e96934f086f3b33b68400000635df22bc06200105960201b60201c565b620003b1731f0c30b1aa4c468b5beb02bac8df8f27617a2296692346646590efbaf71200635df22bc06200105960201b60201c565b620003e6732540ded041b6fedc0ff6f0cf26b891ec97c954006901c3c03b52c63f027880635df22bc06200105960201b60201c565b6200041b7325ae7b45d8646580dfcae403d29164729eb8642f691a784379d99db4200000635df22bc06200105960201b60201c565b6200045073349ebc5a6e853df121c84e999081e5992928e64f6934f086f3b33b68400000635df22bc06200105960201b60201c565b62000485733885d15573e45228dd54cd4fde9bfac64d702ed46901c3c03b52c63f027880635df22bc06200105960201b60201c565b620004ba733a9d83766c03c465851a38daa364ef7deccd1ece6934f086f3b33b68400000635df22bc06200105960201b60201c565b620004ef733abaa3f24428d6028f5a7fc5b18ce9d04ccec2296902a5a058fc295ed00000635df22bc06200105960201b60201c565b62000524733c9f867d9b3a595987e198786fa9ab722e5c2f9b6934f086f3b33b68400000635df22bc06200105960201b60201c565b62000559733f11b4ad17fde4695cad64e109ae92a679d87bfc6969e10de76676d0800000635d79dee06200105960201b60201c565b6200058e733f12af735238c6e2fa45efb5b2f3fae82df4c9226901c3c03b52c63f027880635df22bc06200105960201b60201c565b620005c373404bb9c13364522133b363d5c4adb7a88056b19d6902d2cd2bb7a39658b500635df22bc06200105960201b60201c565b620005f873428ab4b019ee3a9b9863b2b4bf1885ce6dff9a736902a5a058fc295ed00000635df22bc06200105960201b60201c565b6200062d7347428fc08e56388372e7c81ad4a1140d932d10966969e10de76676d0800000635d79dee06200105960201b60201c565b620006627348ee57faf61c0b963113e7921e6173629e6bc4436902a5a058fc295ed00000635df22bc06200105960201b60201c565b62000697734d0aa1c3459bf41e3ad4e4f40bbf029cb5723d836934f086f3b33b68400000635df22bc06200105960201b60201c565b620006cc7357f33efad76d4b783cf42c9e6cb08f4425dfe96e6902a5a058fc295ed00000635df22bc06200105960201b60201c565b62000701735b3fb4e1d6040615f3e681bec4c80b5d7c9580716901c3c03b52c63f027880635df22bc06200105960201b60201c565b62000736735fbb9c482034d287c5b3848fc2f9272abdd5bfa26903878076a58c80674b00635df22bc06200105960201b60201c565b6200076b73656e5569bef7781bf0db199d32027766053501ff69438ec266600555e00000635df22bc06200105960201b60201c565b620007a073664f991cdb2ffe6b6a568ede65b0208dbcce6f72691a784379d99db4200000635df22bc06200105960201b60201c565b620007d67369af0912dd44dce2b2373db4021788cbad84ff356a0422ca8b0a00a4250000006360c3f9006200105960201b60201c565b6200080b736a0a5da2a48ea87c2a906c53b3373642c29a4b6c6934f086f3b33b68400000635df22bc06200105960201b60201c565b62000840736cf32cc52e220c023c2d92b1d62310f46a6e2a136901c3c03b52c63f027880635df22bc06200105960201b60201c565b62000875736d516767e4068fc331bdb331fba7578bdb07a68c69234b04a2777d0408ee00635df22bc06200105960201b60201c565b620008aa736dd10e41a7a84fe23ab35fefa2f46c9895f87a2d693c8c4bde2deef1680000635df22bc06200105960201b60201c565b620008df737030892dbf9c2048e796296dda597f145754a1856969e10de76676d0800000635d79dee06200105960201b60201c565b62000914737ed62cf71d519d3bf293ef90829508f92f4ccccb6902a5a058fc295ed00000635df22bc06200105960201b60201c565b6200094a73871ba4266793ad11da537d4857de7ad49eab662b6a017293b0a9e69fd9c00000635df22bc06200105960201b60201c565b6200097f73880e8b0ece0171edd0247f8d13d348d77a6b9b296903878076a58c80674b00635df22bc06200105960201b60201c565b620009b373887f2b16847248bc757b69f3c695f24ff344daf268e9062e03b5c2908780635df22bc06200105960201b60201c565b620009e8738c994ada51d35b8519424368807fb99c103366866969e10de76676d0800000635d79dee06200105960201b60201c565b62000a1d739196e46d664ceda55cb45a2cc5ab5bd1b7e614e26902a5a058fc295ed00000635df22bc06200105960201b60201c565b62000a5273943c85b13f24083ec73815f7ba763b7c42ae02886902a5a058fc295ed00000635df22bc06200105960201b60201c565b62000a87739467b762550673f08b14423f8562048d5e3694226902a5a058fc295ed00000635df22bc06200105960201b60201c565b62000abc73949423db1bfee1ddec99c9d24a12a6ea27cb34896901c3c03b52c63f027880635df22bc06200105960201b60201c565b62000af17396a5eb172efdf262ed6beaaf0e20c6af71831fc96934f086f3b33b68400000635df22bc06200105960201b60201c565b62000b2673a69dca0814eaadc89b6dbe94c5e2110497690f6c6903878076a58c80674b00635df22bc06200105960201b60201c565b62000b5b73a720a8ee90f5013cae9bf7bcac1d153e42815454691a784379d99db4200000635df22bc06200105960201b60201c565b62000b9073b080454f190e76eb8e719560fa8cae50c71bcea96901c3c03b52c63f027880635df22bc06200105960201b60201c565b62000bc573b476ee7d610dae7b23b671ebc7bd6112e97729696902a5a058fc295ed00000635df22bc06200105960201b60201c565b62000bfb73b561618a3ea959a5e363643b267c4cb8fe4b1df76a0422ca8b0a00a4250000006360c3f9006200105960201b60201c565b62000c3073b5b6d8885fbf28f843cc7886de242b811d6952056901c3c03b52c63f027880635df22bc06200105960201b60201c565b62000c6573b61c11b6e42d459efaee8995c44db08507e468e169477d5529f68a63000000635df22bc06200105960201b60201c565b62000c9a73b999004b49c6b907d4278067da5c85195dcd7fc769081e0dddaff653f8b500635df22bc06200105960201b60201c565b62000ccf73be4888c5b021e5f16cd254de2d4eaf17625685c46934f086f3b33b68400000635df22bc06200105960201b60201c565b62000d0473c1d441a2ad43af7b4a3d8e3200d2ceb3a973099d6934f086f3b33b68400000635df22bc06200105960201b60201c565b62000d3973c58a20e290e858542d8e8bb07b600aeb9195fe306903878076a58c80674b00635df22bc06200105960201b60201c565b62000d6f73cfe7964b0b6412b013dc019bdf3afef58be565936a055084cc99f0bdbadd0000635df22bc06200105960201b60201c565b62000da473d33d4f83e85c92e0b53ffe4fc0e18b0e3632c0976901c3c03b52c63f027880635df22bc06200105960201b60201c565b62000dd973d44fb8de580d34f44789408cc9335c9a9ce0ce4d691ad0235eb930a0540000635df22bc06200105960201b60201c565b62000e0e73dacd80d8e1d4f117515caa477ee7599cdfc766196902a5a058fc295ed00000635df22bc06200105960201b60201c565b62000e4373db6cc57168c07b83a00f1f8871538446068824fc691a784379d99db4200000635df22bc06200105960201b60201c565b62000e7873de6b493d368316b9078454e37dce4968482dfbe96969e10de76676d0800000635d79dee06200105960201b60201c565b62000ead73e23c7cb60189bb2fd60625d2c2747b1e68f107766934f086f3b33b68400000635df22bc06200105960201b60201c565b62000ee273e6e8a111c89b05337049de9349c7c4880a396ef1691a784379d99db4200000635df22bc06200105960201b60201c565b62000f1773ebbddf28bf3224791b0510a2ab8813f182fe4e2b6901c3c03b52c63f027880635df22bc06200105960201b60201c565b62000f4c73f4e31018a926f64cb780cb9f5f027377bcfb26fc6907f0e10af47c1c700000635df22bc06200105960201b60201c565b62000f8173f8e6ecb4b0f17576525749bdf85524652cbf002e6901c3c03b52c63f027880635df22bc06200105960201b60201c565b62000fb773fd679097fe0f914642af9857e5799332fe2efa296a01a784379d99db42000000635d79dee06200105960201b60201c565b62000fed73fd7a30d3c2bd017a458610274c275059d308b2e76a01ff1675f219f5a8780000635df22bc06200105960201b60201c565b6200102273ffcf98c62c1bad480ab6846717b173a72e2dd090691a784379d99db4200000635df22bc06200105960201b60201c565b6200105773ffd9b871df6e93803c0877e98fc1722b39c00d786902a5a058fc295ed00000635df22bc06200105960201b60201c565b565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000154148015620010b4575060008160010154145b6200110b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180620014e26029913960400191505060405180910390fd5b8260016000828254019250508190555082816000018190555081816001018190555050505050565b61037780620011436000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c806318a5bbdc14610051578063192e7a7b146100b057806330f0dbe0146100f45780639976e12f14610112575b600080fd5b6100936004803603602081101561006757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610130565b604051808381526020018281526020019250505060405180910390f35b6100f2600480360360208110156100c657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610154565b005b6100fc610336565b6040518082815260200191505060405180910390f35b61011a610345565b6040518082815260200191505060405180910390f35b60006020528060005260406000206000915090508060000154908060010154905082565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816000015411610210576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f417661696c61626c6520616d6f756e742069732030000000000000000000000081525060200191505060405180910390fd5b80600101544211610289576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f486f6c64696e6720706572696f64206973206e6f74206f76657200000000000081525060200191505060405180910390fd5b600081600001549050600082600001819055508273ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156102e2573d6000803e3d6000fd5b508273ffffffffffffffffffffffffffffffffffffffff167f221c08a06b07a64803b3787861a3f276212fcccb51c2e6234077a9b8cb13047a826040518082815260200191505060405180910390a2505050565b6a22140f53c2d216263ba28081565b6001548156fea165627a7a72305820b0165b18a29fae78ec1f58bf69134a67ab02e21d059e757412318d8362284866002954617267657420616d6f756e742073686f756c6420657175616c2061637475616c20616d6f756e74486f6c64696e6720666f72207468697320616464726573732077617320616c7265616479207365742e42616c616e63652073686f756c6420657175616c2074617267657420616d6f756e742e" + }, + "0x1204700000000000000000000000000000000006": { + "constructor": "0x60806040523480156200001157600080fd5b5060405160208062003ed2833981018060405260208110156200003357600080fd5b8101908080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a362000111816200011860201b60201c565b506200027a565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620001bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6577206f776e657220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b613c48806200028a6000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c806392698814116100c3578063e30bd7401161007c578063e30bd740146109b5578063eadf976014610a72578063ef5454d614610b17578063f25eb5c114610bc8578063f2fde38b14610bd2578063f6d339e414610c1657610158565b80639269881414610705578063ac4e73f91461074b578063ac72c120146107fc578063c3a3582514610842578063deb931a2146108d9578063df57b7421461094757610158565b80636795dbcd116101155780636795dbcd1461041c5780636a1acc3f146104df57806379ce9fac1461059c5780638da5cb5b146106025780638f32d59b1461064c57806390b97fc11461066e57610158565b806306b2ff471461015d57806319362a28146101b9578063267b69221461025e5780633f3935d1146102ff578063432ced04146103905780634f39ca59146103d6575b600080fd5b61019f6004803603602081101561017357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610cd1565b604051808215151515815260200191505060405180910390f35b610244600480360360608110156101cf57600080fd5b8101908080359060200190929190803590602001906401000000008111156101f657600080fd5b82018360208201111561020857600080fd5b8035906020019184600183028401116401000000008311171561022a57600080fd5b909192939192939080359060200190929190505050610d31565b604051808215151515815260200191505060405180910390f35b61028a6004803603602081101561027457600080fd5b8101908080359060200190929190505050610fcb565b604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390f35b6103766004803603602081101561031557600080fd5b810190808035906020019064010000000081111561033257600080fd5b82018360208201111561034457600080fd5b8035906020019184600183028401116401000000008311171561036657600080fd5b909192939192939050505061102f565b604051808215151515815260200191505060405180910390f35b6103bc600480360360208110156103a657600080fd5b810190808035906020019092919050505061134e565b604051808215151515815260200191505060405180910390f35b610402600480360360208110156103ec57600080fd5b8101908080359060200190929190505050611546565b604051808215151515815260200191505060405180910390f35b61049d6004803603604081101561043257600080fd5b81019080803590602001909291908035906020019064010000000081111561045957600080fd5b82018360208201111561046b57600080fd5b8035906020019184600183028401116401000000008311171561048d57600080fd5b9091929391929390505050611a8d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610521600480360360208110156104f557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611bb2565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610561578082015181840152602081019050610546565b50505050905090810190601f16801561058e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6105e8600480360360408110156105b257600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611c62565b604051808215151515815260200191505060405180910390f35b61060a611f58565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610654611f81565b604051808215151515815260200191505060405180910390f35b6106ef6004803603604081101561068457600080fd5b8101908080359060200190929190803590602001906401000000008111156106ab57600080fd5b8201836020820111156106bd57600080fd5b803590602001918460018302840111640100000000831117156106df57600080fd5b9091929391929390505050611fd8565b6040518082815260200191505060405180910390f35b6107316004803603602081101561071b57600080fd5b81019080803590602001909291905050506120fa565b604051808215151515815260200191505060405180910390f35b6107e26004803603604081101561076157600080fd5b810190808035906020019064010000000081111561077e57600080fd5b82018360208201111561079057600080fd5b803590602001918460018302840111640100000000831117156107b257600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612245565b604051808215151515815260200191505060405180910390f35b6108286004803603602081101561081257600080fd5b81019080803590602001909291905050506127e7565b604051808215151515815260200191505060405180910390f35b6108c36004803603604081101561085857600080fd5b81019080803590602001909291908035906020019064010000000081111561087f57600080fd5b82018360208201111561089157600080fd5b803590602001918460018302840111640100000000831117156108b357600080fd5b9091929391929390505050612932565b6040518082815260200191505060405180910390f35b610905600480360360208110156108ef57600080fd5b8101908080359060200190929190505050612a57565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6109736004803603602081101561095d57600080fd5b8101908080359060200190929190505050612b72565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6109f7600480360360208110156109cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612c8d565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610a37578082015181840152602081019050610a1c565b50505050905090810190601f168015610a645780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610afd60048036036060811015610a8857600080fd5b810190808035906020019092919080359060200190640100000000811115610aaf57600080fd5b820183602082011115610ac157600080fd5b80359060200191846001830284011164010000000083111715610ae357600080fd5b909192939192939080359060200190929190505050612d6e565b604051808215151515815260200191505060405180910390f35b610bae60048036036040811015610b2d57600080fd5b8101908080359060200190640100000000811115610b4a57600080fd5b820183602082011115610b5c57600080fd5b80359060200191846001830284011164010000000083111715610b7e57600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061300b565b604051808215151515815260200191505060405180910390f35b610bd0613281565b005b610c1460048036036020811015610be857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613674565b005b610cb760048036036060811015610c2c57600080fd5b810190808035906020019092919080359060200190640100000000811115610c5357600080fd5b820183602082011115610c6557600080fd5b80359060200191846001830284011164010000000083111715610c8757600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506136fa565b604051808215151515815260200191505060405180910390f35b600080600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080546001816001161561010002031660029004905014159050919050565b600084600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610e0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b853373ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610ee5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4572726f723a204f6e6c79206f776e6572206f6600000000000000000000000081525060200191505060405180910390fd5b83600160008981526020019081526020016000206002018787604051808383808284378083019250505092505050908152602001604051809103902081905550867fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea878789896040518080602001806020018381038352878782818152602001925080828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925080828437600081840152601f19601f820116905080830192505050965050505050505060405180910390a2600192505050949350505050565b60016020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082565b600082828080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050600073ffffffffffffffffffffffffffffffffffffffff16600160008380519060200120815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611156576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f4572726f723a204f6e6c79207768656e20656e7472790000000000000000000081525060200191505060405180910390fd5b83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050503373ffffffffffffffffffffffffffffffffffffffff16600160008380519060200120815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611279576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f4572726f723a204f6e6c79207768656e2070726f706f7365640000000000000081525060200191505060405180910390fd5b8484600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002091906112c7929190613b0e565b503373ffffffffffffffffffffffffffffffffffffffff167f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c91920868660405180806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050935050505060405180910390a260019250505092915050565b600081600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611429576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f4572726f723a204f6e6c79207768656e20756e7265736572766564000000000081525060200191505060405180910390fd5b611431611f81565b6114a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b336001600085815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16837f4963513eca575aba66fdcd25f267aae85958fe6fb97e75fa25d783f1a091a22160405160405180910390a36001915050919050565b600081600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611622576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b823373ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146116fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4572726f723a204f6e6c79206f776e6572206f6600000000000000000000000081525060200191505060405180910390fd5b83600260006001600088815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180828054600181600116156101000203166002900480156117cb5780601f106117a95761010080835404028352918201916117cb565b820191906000526020600020905b8154815290600101906020018083116117b7575b5050915050604051809103902014156119da576001600085815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd600260006001600089815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020604051808060200182810382528381815460018160011615610100020316600290048152602001915080546001816001161561010002031660029004801561194a5780601f1061191f5761010080835404028352916020019161194a565b820191906000526020600020905b81548152906001019060200180831161192d57829003601f168201915b50509250505060405180910390a2600260006001600087815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006119d99190613b8e565b5b60016000858152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550503373ffffffffffffffffffffffffffffffffffffffff16847fef1961b4d2909dc23643b309bfe5c3e5646842d98c3a58517037ef3871185af360405160405180910390a3600192505050919050565b600083600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611b69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b60016000868152602001908152602001600020600201848460405180838380828437808301925050509250505090815260200160405180910390205460001c9150509392505050565b60026020528060005260406000206000915090508054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611c5a5780601f10611c2f57610100808354040283529160200191611c5a565b820191906000526020600020905b815481529060010190602001808311611c3d57829003601f168201915b505050505081565b600082600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611d3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b833373ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611e16576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4572726f723a204f6e6c79206f776e6572206f6600000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415611e9c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613bfc6021913960400191505060405180910390fd5b836001600087815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16867f7b97c62130aa09acbbcbf7482630e756592496f1759eaf702f469cf64dfb779460405160405180910390a460019250505092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b600083600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156120b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b6001600086815260200190815260200160002060020184846040518083838082843780830192505050925050509081526020016040518091039020549150509392505050565b600081600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156121d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166001600085815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415915050919050565b600083838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050600073ffffffffffffffffffffffffffffffffffffffff16600160008380519060200120815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561236c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f4572726f723a204f6e6c79207768656e20656e7472790000000000000000000081525060200191505060405180910390fd5b848460405180838380828437808301925050509250505060405180910390203373ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612462576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4572726f723a204f6e6c79206f776e6572206f6600000000000000000000000081525060200191505060405180910390fd5b6000868660405180838380828437808301925050509250505060405180910390209050600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580156125d3575080600260006001600085815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180828054600181600116156101000203166002900480156125c45780601f106125a25761010080835404028352918201916125c4565b820191906000526020600020905b8154815290600101906020018083116125b0575b50509150506040518091039020145b1561270a57600260006001600084815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006126599190613b8e565b6001600082815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd888860405180806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050935050505060405180910390a25b846001600083815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508473ffffffffffffffffffffffffffffffffffffffff167f728435a0031f6a04538fcdd24922a7e06bc7bc945db03e83d22122d1bc5f28df888860405180806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050935050505060405180910390a2600193505050509392505050565b600081600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156128c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166001600085815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415915050919050565b600083600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415612a0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b60016000868152602001908152602001600020600201848460405180838380828437808301925050509250505090815260200160405180910390205460001c9150509392505050565b600081600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415612b33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b6001600084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b600081600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415612c4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b6001600084815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b6060600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015612d625780601f10612d3757610100808354040283529160200191612d62565b820191906000526020600020905b815481529060010190602001808311612d4557829003601f168201915b50505050509050919050565b600084600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415612e4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b853373ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612f22576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4572726f723a204f6e6c79206f776e6572206f6600000000000000000000000081525060200191505060405180910390fd5b8360001b600160008981526020019081526020016000206002018787604051808383808284378083019250505092505050908152602001604051809103902081905550867fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea878789896040518080602001806020018381038352878782818152602001925080828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925080828437600081840152601f19601f820116905080830192505050965050505050505060405180910390a2600192505050949350505050565b600083838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050600073ffffffffffffffffffffffffffffffffffffffff16600160008380519060200120815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415613132576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f4572726f723a204f6e6c79207768656e20656e7472790000000000000000000081525060200191505060405180910390fd5b61313a611f81565b6131ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b8484600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002091906131fa929190613b0e565b508273ffffffffffffffffffffffffffffffffffffffff167f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c91920868660405180806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050935050505060405180910390a260019150509392505050565b600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156133545780601f1061332957610100808354040283529160200191613354565b820191906000526020600020905b81548152906001019060200180831161333757829003601f168201915b5050505050600073ffffffffffffffffffffffffffffffffffffffff16600160008380519060200120815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415613439576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f4572726f723a204f6e6c79207768656e20656e7472790000000000000000000081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180806020018281038252838181546001816001161561010002031660029004815260200191508054600181600116156101000203166002900480156135395780601f1061350e57610100808354040283529160200191613539565b820191906000526020600020905b81548152906001019060200180831161351c57829003601f168201915b50509250505060405180910390a260016000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180828054600181600116156101000203166002900480156135e55780601f106135c35761010080835404028352918201916135e5565b820191906000526020600020905b8154815290600101906020018083116135d1575b50509150506040518091039020815260200190815260200160002060010160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006136719190613b8e565b50565b61367c611f81565b6136ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b6136f7816139ad565b50565b600084600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156137d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b853373ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146138ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4572726f723a204f6e6c79206f776e6572206f6600000000000000000000000081525060200191505060405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff1660001b600160008981526020019081526020016000206002018787604051808383808284378083019250505092505050908152602001604051809103902081905550867fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea878789896040518080602001806020018381038352878782818152602001925080828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925080828437600081840152601f19601f820116905080830192505050965050505050505060405180910390a2600192505050949350505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613a50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6577206f776e657220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613b4f57803560ff1916838001178555613b7d565b82800160010185558215613b7d579182015b82811115613b7c578235825591602001919060010190613b61565b5b509050613b8a9190613bd6565b5090565b50805460018160011615610100020316600290046000825580601f10613bb45750613bd3565b601f016020900490600052602060002090810190613bd29190613bd6565b5b50565b613bf891905b80821115613bf4576000816000905550600101613bdc565b5090565b9056fe4572726f723a206e6f207472616e7366657220746f206164647265737320307830a165627a7a72305820fe186a600f547c59523f333a7eb66cd1de74492306acaa3db2cd4c8a1b426b5a00290000000000000000000000001204700000000000000000000000000000000005" + }, + "0x1204700000000000000000000000000000000007": { + "constructor": "0x608060405234801561001057600080fd5b506040516040806108658339810180604052604081101561003057600080fd5b810190808051906020019092919080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3610116816101a160201b60201c565b81600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167fcc57a97257d7703be97e9d538cb08b3fa1ff2784b776d505942d49a95dc2891460405160405180910390a25050610302565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610244576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6577206f776e657220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b610554806103116000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80636ddc4a071461005c5780638da5cb5b146100a65780638f32d59b146100f0578063f2fde38b14610112578063fe64d6ff14610156575b600080fd5b61006461019a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100ae6101c0565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100f86101e9565b604051808215151515815260200191505060405180910390f35b6101546004803603602081101561012857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610240565b005b6101986004803603602081101561016c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506102c6565b005b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6102486101e9565b6102ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b6102c3816103c7565b50565b6102ce6101e9565b610340576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fcc57a97257d7703be97e9d538cb08b3fa1ff2784b776d505942d49a95dc2891460405160405180910390a250565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561046a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6577206f776e657220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fea165627a7a723058204d73401a5cbb107ba765457948a3c2a2612436446f9125c3696f0f4cc7e06980002900000000000000000000000012047000000000000000000000000000000000090000000000000000000000001204700000000000000000000000000000000005" + }, + "0x1204700000000000000000000000000000000008": { + "constructor": "0x60806040523480156200001157600080fd5b506040516040806200298b8339810180604052620000339190810190620002a8565b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a381600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062000141816200014960201b60201c565b5050620003da565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620001bc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001b3906200032b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000815190506200028b81620003a6565b92915050565b600081519050620002a281620003c0565b92915050565b60008060408385031215620002bc57600080fd5b6000620002cc8582860162000291565b9250506020620002df858286016200027a565b9150509250929050565b6000620002f8601f836200034d565b91507f4e6577206f776e657220616464726573732063616e6e6f7420626520307830006000830152602082019050919050565b600060208201905081810360008301526200034681620002e9565b9050919050565b600082825260208201905092915050565b60006200036b8262000386565b9050919050565b60006200037f826200035e565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b620003b1816200035e565b8114620003bd57600080fd5b50565b620003cb8162000372565b8114620003d757600080fd5b50565b6125a180620003ea6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c8063954029c911610097578063eab7ad9211610066578063eab7ad92146102b2578063ee7ee0fd146102ce578063f2fde38b146102fe578063fbd74f841461031a576100f5565b8063954029c91461021a578063a999809f14610236578063b71da0d114610266578063da5393d514610296576100f5565b80636a564261116100d35780636a5642611461017857806370a05b18146101ae5780638da5cb5b146101de5780638f32d59b146101fc576100f5565b80631bab58f5146100fa5780632c5653e21461012a57806332d91c0e14610148575b600080fd5b610114600480360361010f9190810190611d82565b61034a565b60405161012191906123f7565b60405180910390f35b610132610767565b60405161013f919061233a565b60405180910390f35b610162600480360361015d9190810190611d82565b61078d565b60405161016f9190612355565b60405180910390f35b610192600480360361018d9190810190611d82565b61097e565b6040516101a597969594939291906122af565b60405180910390f35b6101c860048036036101c39190810190611d82565b610c2d565b6040516101d5919061228d565b60405180910390f35b6101e6610e1e565b6040516101f39190612257565b60405180910390f35b610204610e47565b6040516102119190612272565b60405180910390f35b610234600480360361022f9190810190611d82565b610e9e565b005b610250600480360361024b9190810190611d82565b610ff5565b60405161025d9190612355565b60405180910390f35b610280600480360361027b9190810190611d82565b6111e6565b60405161028d9190612272565b60405180910390f35b6102b060048036036102ab9190810190611d82565b611276565b005b6102cc60048036036102c79190810190611dd4565b611371565b005b6102e860048036036102e39190810190611d82565b611673565b6040516102f59190612272565b60405180910390f35b61031860048036036103139190810190611d82565b6117d9565b005b610334600480360361032f9190810190611d82565b61182c565b604051610341919061228d565b60405180910390f35b610352611b4b565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff1660e01b815260040160206040518083038186803b1580156103ba57600080fd5b505afa1580156103ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506103f29190810190611dab565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461045f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045690612377565b60405180910390fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060e0016040529081600082018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105425780601f1061051757610100808354040283529160200191610542565b820191906000526020600020905b81548152906001019060200180831161052557829003601f168201915b50505050508152602001600182018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105e45780601f106105b9576101008083540402835291602001916105e4565b820191906000526020600020905b8154815290600101906020018083116105c757829003601f168201915b50505050508152602001600282018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106865780601f1061065b57610100808354040283529160200191610686565b820191906000526020600020905b81548152906001019060200180831161066957829003601f168201915b50505050508152602001600382018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107285780601f106106fd57610100808354040283529160200191610728565b820191906000526020600020905b81548152906001019060200180831161070b57829003601f168201915b505050505081526020016004820160009054906101000a900460ff16151515158152602001600582015481526020016006820154815250509050919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff1660e01b815260040160206040518083038186803b1580156107f757600080fd5b505afa15801561080b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061082f9190810190611dab565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461089c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161089390612377565b60405180910390fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206003018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109725780601f1061094757610100808354040283529160200191610972565b820191906000526020600020905b81548152906001019060200180831161095557829003601f168201915b50505050509050919050565b6001602052806000526040600020600091509050806000018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a2a5780601f106109ff57610100808354040283529160200191610a2a565b820191906000526020600020905b815481529060010190602001808311610a0d57829003601f168201915b505050505090806001018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610ac85780601f10610a9d57610100808354040283529160200191610ac8565b820191906000526020600020905b815481529060010190602001808311610aab57829003601f168201915b505050505090806002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b665780601f10610b3b57610100808354040283529160200191610b66565b820191906000526020600020905b815481529060010190602001808311610b4957829003601f168201915b505050505090806003018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c045780601f10610bd957610100808354040283529160200191610c04565b820191906000526020600020905b815481529060010190602001808311610be757829003601f168201915b5050505050908060040160009054906101000a900460ff16908060050154908060060154905087565b6060600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff1660e01b815260040160206040518083038186803b158015610c9757600080fd5b505afa158015610cab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ccf9190810190611dab565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3390612377565b60405180910390fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e125780601f10610de757610100808354040283529160200191610e12565b820191906000526020600020905b815481529060010190602001808311610df557829003601f168201915b50505050509050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff1660e01b815260040160206040518083038186803b158015610f0657600080fd5b505afa158015610f1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f3e9190810190611dab565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610fab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fa290612377565b60405180910390fd5b43600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206006018190555050565b6060600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff1660e01b815260040160206040518083038186803b15801561105f57600080fd5b505afa158015611073573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506110979190810190611dab565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611104576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110fb90612377565b60405180910390fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156111da5780601f106111af576101008083540402835291602001916111da565b820191906000526020600020905b8154815290600101906020018083116111bd57829003601f168201915b50505050509050919050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060154600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050154109050919050565b61127e610e47565b6112bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112b4906123d7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561132d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161132490612397565b60405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff1660e01b815260040160206040518083038186803b1580156113d957600080fd5b505afa1580156113ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114119190810190611dab565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461147e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161147590612377565b60405180910390fd5b8888600160008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000191906114cf929190611b8a565b508686600160008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001019190611521929190611c0a565b508484600160008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002019190611573929190611b8a565b508282600160008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030191906115c5929190611c0a565b5080600160008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160006101000a81548160ff02191690831515021790555043600160008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005018190555050505050505050505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff1660e01b815260040160206040518083038186803b1580156116dd57600080fd5b505afa1580156116f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506117159190810190611dab565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611782576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161177990612377565b60405180910390fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900460ff169050919050565b6117e1610e47565b611820576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611817906123d7565b60405180910390fd5b61182981611a1d565b50565b6060600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff1660e01b815260040160206040518083038186803b15801561189657600080fd5b505afa1580156118aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506118ce9190810190611dab565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461193b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193290612377565b60405180910390fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611a115780601f106119e657610100808354040283529160200191611a11565b820191906000526020600020905b8154815290600101906020018083116119f457829003601f168201915b50505050509050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611a8d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a84906123b7565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6040518060e001604052806060815260200160608152602001606081526020016060815260200160001515815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611bcb57803560ff1916838001178555611bf9565b82800160010185558215611bf9579182015b82811115611bf8578235825591602001919060010190611bdd565b5b509050611c069190611c8a565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611c4b57803560ff1916838001178555611c79565b82800160010185558215611c79579182015b82811115611c78578235825591602001919060010190611c5d565b5b509050611c869190611c8a565b5090565b611cac91905b80821115611ca8576000816000905550600101611c90565b5090565b90565b600081359050611cbe81612539565b92915050565b600081519050611cd381612539565b92915050565b600081359050611ce881612550565b92915050565b60008083601f840112611d0057600080fd5b8235905067ffffffffffffffff811115611d1957600080fd5b602083019150836001820283011115611d3157600080fd5b9250929050565b60008083601f840112611d4a57600080fd5b8235905067ffffffffffffffff811115611d6357600080fd5b602083019150836001820283011115611d7b57600080fd5b9250929050565b600060208284031215611d9457600080fd5b6000611da284828501611caf565b91505092915050565b600060208284031215611dbd57600080fd5b6000611dcb84828501611cc4565b91505092915050565b60008060008060008060008060008060c08b8d031215611df357600080fd5b6000611e018d828e01611caf565b9a505060208b013567ffffffffffffffff811115611e1e57600080fd5b611e2a8d828e01611cee565b995099505060408b013567ffffffffffffffff811115611e4957600080fd5b611e558d828e01611d38565b975097505060608b013567ffffffffffffffff811115611e7457600080fd5b611e808d828e01611cee565b955095505060808b013567ffffffffffffffff811115611e9f57600080fd5b611eab8d828e01611d38565b935093505060a0611ebe8d828e01611cd9565b9150509295989b9194979a5092959850565b611ed981612489565b82525050565b611ee88161249b565b82525050565b611ef78161249b565b82525050565b6000611f0882612424565b611f128185612456565b9350611f228185602086016124f5565b611f2b81612528565b840191505092915050565b6000611f4182612419565b611f4b8185612445565b9350611f5b8185602086016124f5565b611f6481612528565b840191505092915050565b6000611f7a82612419565b611f848185612456565b9350611f948185602086016124f5565b611f9d81612528565b840191505092915050565b611fb1816124d1565b82525050565b6000611fc28261243a565b611fcc8185612478565b9350611fdc8185602086016124f5565b611fe581612528565b840191505092915050565b6000611ffb8261242f565b6120058185612467565b93506120158185602086016124f5565b61201e81612528565b840191505092915050565b60006120348261242f565b61203e8185612478565b935061204e8185602086016124f5565b61205781612528565b840191505092915050565b600061206f601383612478565b91507f4572726f723a206f6e6c794c6f676963204462000000000000000000000000006000830152602082019050919050565b60006120af602983612478565b91507f4572726f723a206e65774c6f6f6b5570206973206e6f7420616c6c6f7765642060008301527f746f2062652030783000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612115601f83612478565b91507f4e6577206f776e657220616464726573732063616e6e6f7420626520307830006000830152602082019050919050565b6000612155601383612478565b91507f53656e646572206973206e6f74206f776e6572000000000000000000000000006000830152602082019050919050565b600060e08301600083015184820360008601526121a58282611f36565b915050602083015184820360208601526121bf8282611ff0565b915050604083015184820360408601526121d98282611f36565b915050606083015184820360608601526121f38282611ff0565b91505060808301516122086080860182611edf565b5060a083015161221b60a0860182612239565b5060c083015161222e60c0860182612239565b508091505092915050565b612242816124c7565b82525050565b612251816124c7565b82525050565b600060208201905061226c6000830184611ed0565b92915050565b60006020820190506122876000830184611eee565b92915050565b600060208201905081810360008301526122a78184611efd565b905092915050565b600060e08201905081810360008301526122c9818a611f6f565b905081810360208301526122dd8189612029565b905081810360408301526122f18188611f6f565b905081810360608301526123058187612029565b90506123146080830186611eee565b61232160a0830185612248565b61232e60c0830184612248565b98975050505050505050565b600060208201905061234f6000830184611fa8565b92915050565b6000602082019050818103600083015261236f8184611fb7565b905092915050565b6000602082019050818103600083015261239081612062565b9050919050565b600060208201905081810360008301526123b0816120a2565b9050919050565b600060208201905081810360008301526123d081612108565b9050919050565b600060208201905081810360008301526123f081612148565b9050919050565b600060208201905081810360008301526124118184612188565b905092915050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b6000612494826124a7565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006124dc826124e3565b9050919050565b60006124ee826124a7565b9050919050565b60005b838110156125135780820151818401526020810190506124f8565b83811115612522576000848401525b50505050565b6000601f19601f8301169050919050565b61254281612489565b811461254d57600080fd5b50565b6125598161249b565b811461256457600080fd5b5056fea265627a7a7230582045fea88fa096a11a15a5bb8e9f5993ca3ab8a38132e6c7a04eb7cd5458378c906c6578706572696d656e74616cf5003700000000000000000000000012047000000000000000000000000000000000070000000000000000000000001204700000000000000000000000000000000005" + }, + "0x1204700000000000000000000000000000000009": { + "constructor": "0x60806040523480156200001157600080fd5b506040516040806200208d8339810180604052620000339190810190620002a8565b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a381600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062000141816200014960201b60201c565b5050620003da565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620001bc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001b3906200032b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000815190506200028b81620003a6565b92915050565b600081519050620002a281620003c0565b92915050565b60008060408385031215620002bc57600080fd5b6000620002cc8582860162000291565b9250506020620002df858286016200027a565b9150509250929050565b6000620002f8601f836200034d565b91507f4e6577206f776e657220616464726573732063616e6e6f7420626520307830006000830152602082019050919050565b600060208201905081810360008301526200034681620002e9565b9050919050565b600082825260208201905092915050565b60006200036b8262000386565b9050919050565b60006200037f826200035e565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b620003b1816200035e565b8114620003bd57600080fd5b50565b620003cb8162000372565b8114620003d757600080fd5b50565b611ca380620003ea6000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638f32d59b1161005b5780638f32d59b14610101578063b71da0d11461011f578063ec2626111461014f578063f2fde38b1461016d57610088565b806312127ed71461008d5780633f67c333146100a957806389c3ce1e146100b35780638da5cb5b146100e3575b600080fd5b6100a760048036036100a2919081019061118d565b610189565b005b6100b16107d7565b005b6100cd60048036036100c89190810190611164565b610a23565b6040516100da91906119c0565b60405180910390f35b6100eb610aee565b6040516100f891906117b7565b60405180910390f35b610109610b17565b604051610116919061186a565b60405180910390f35b61013960048036036101349190810190611164565b610b6e565b604051610146919061186a565b60405180910390f35b610157610c22565b6040516101649190611885565b60405180910390f35b61018760048036036101829190810190611164565b610c48565b005b610191610b17565b6101d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101c790611940565b60405180910390fd5b600085511415610215576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161020c906118e0565b60405180910390fd5b60008451141561025a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161025190611980565b60405180910390fd5b60008351141561029f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610296906118a0565b60405180910390fd5b6000825114156102e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102db906118c0565b60405180910390fd5b8480519060200120600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fbd74f84886040518263ffffffff1660e01b815260040161034791906117b7565b60006040518083038186803b15801561035f57600080fd5b505afa158015610373573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525061039c919081019061129f565b8051906020012014801561046c57508380519060200120600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a999809f886040518263ffffffff1660e01b815260040161040e91906117b7565b60006040518083038186803b15801561042657600080fd5b505afa15801561043a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525061046391908101906112e0565b80519060200120145b801561053457508280519060200120600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a05b18886040518263ffffffff1660e01b81526004016104d691906117b7565b60006040518083038186803b1580156104ee57600080fd5b505afa158015610502573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525061052b919081019061129f565b80519060200120145b80156105fc57508180519060200120600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166332d91c0e886040518263ffffffff1660e01b815260040161059e91906117b7565b60006040518083038186803b1580156105b657600080fd5b505afa1580156105ca573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052506105f391908101906112e0565b80519060200120145b80156106b55750801515600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ee7ee0fd886040518263ffffffff1660e01b815260040161066191906117b7565b60206040518083038186803b15801561067957600080fd5b505afa15801561068d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506106b19190810190611276565b1515145b156106f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106ec90611960565b60405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663eab7ad928787878787876040518763ffffffff1660e01b815260040161075a969594939291906117ed565b600060405180830381600087803b15801561077457600080fd5b505af1158015610788573d6000803e3d6000fd5b505050508573ffffffffffffffffffffffffffffffffffffffff167fc9e49a024d50440c73d2d12d0ae05064094dca76b46dc95e99ea6848eb8f27e960405160405180910390a2505050505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fbd74f84336040518263ffffffff1660e01b815260040161083491906117d2565b60006040518083038186803b15801561084c57600080fd5b505afa158015610860573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250610889919081019061129f565b5114156108cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c2906119a0565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff1663b71da0d1336040518263ffffffff1660e01b815260040161090491906117d2565b60206040518083038186803b15801561091c57600080fd5b505afa158015610930573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506109549190810190611276565b15610994576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90611900565b60405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663954029c9336040518263ffffffff1660e01b81526004016109ef91906117d2565b600060405180830381600087803b158015610a0957600080fd5b505af1158015610a1d573d6000803e3d6000fd5b50505050565b610a2b610dc9565b610a33610dc9565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631bab58f5846040518263ffffffff1660e01b8152600401610a8e91906117b7565b60006040518083038186803b158015610aa657600080fd5b505afa158015610aba573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250610ae39190810190611321565b905080915050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b71da0d1836040518263ffffffff1660e01b8152600401610bcb91906117b7565b60206040518083038186803b158015610be357600080fd5b505afa158015610bf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610c1b9190810190611276565b9050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610c50610b17565b610c8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8690611940565b60405180910390fd5b610c9881610c9b565b50565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610d0b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0290611920565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6040518060e001604052806060815260200160608152602001606081526020016060815260200160001515815260200160008152602001600081525090565b600081359050610e1781611c24565b92915050565b600081359050610e2c81611c3b565b92915050565b600081519050610e4181611c3b565b92915050565b600082601f830112610e5857600080fd5b8151610e6b610e6682611a0f565b6119e2565b91508082526020830160208301858383011115610e8757600080fd5b610e92838284611be0565b50505092915050565b600082601f830112610eac57600080fd5b8135610ebf610eba82611a3b565b6119e2565b91508082526020830160208301858383011115610edb57600080fd5b610ee6838284611bd1565b50505092915050565b600082601f830112610f0057600080fd5b8151610f13610f0e82611a3b565b6119e2565b91508082526020830160208301858383011115610f2f57600080fd5b610f3a838284611be0565b50505092915050565b600082601f830112610f5457600080fd5b8151610f67610f6282611a67565b6119e2565b91508082526020830160208301858383011115610f8357600080fd5b610f8e838284611be0565b50505092915050565b600082601f830112610fa857600080fd5b8135610fbb610fb682611a93565b6119e2565b91508082526020830160208301858383011115610fd757600080fd5b610fe2838284611bd1565b50505092915050565b600082601f830112610ffc57600080fd5b815161100f61100a82611a93565b6119e2565b9150808252602083016020830185838301111561102b57600080fd5b611036838284611be0565b50505092915050565b600060e0828403121561105157600080fd5b61105b60e06119e2565b9050600082015167ffffffffffffffff81111561107757600080fd5b61108384828501610e47565b600083015250602082015167ffffffffffffffff8111156110a357600080fd5b6110af84828501610f43565b602083015250604082015167ffffffffffffffff8111156110cf57600080fd5b6110db84828501610e47565b604083015250606082015167ffffffffffffffff8111156110fb57600080fd5b61110784828501610f43565b606083015250608061111b84828501610e32565b60808301525060a061112f8482850161114f565b60a08301525060c06111438482850161114f565b60c08301525092915050565b60008151905061115e81611c52565b92915050565b60006020828403121561117657600080fd5b600061118484828501610e08565b91505092915050565b60008060008060008060c087890312156111a657600080fd5b60006111b489828a01610e08565b965050602087013567ffffffffffffffff8111156111d157600080fd5b6111dd89828a01610e9b565b955050604087013567ffffffffffffffff8111156111fa57600080fd5b61120689828a01610f97565b945050606087013567ffffffffffffffff81111561122357600080fd5b61122f89828a01610e9b565b935050608087013567ffffffffffffffff81111561124c57600080fd5b61125889828a01610f97565b92505060a061126989828a01610e1d565b9150509295509295509295565b60006020828403121561128857600080fd5b600061129684828501610e32565b91505092915050565b6000602082840312156112b157600080fd5b600082015167ffffffffffffffff8111156112cb57600080fd5b6112d784828501610eef565b91505092915050565b6000602082840312156112f257600080fd5b600082015167ffffffffffffffff81111561130c57600080fd5b61131884828501610feb565b91505092915050565b60006020828403121561133357600080fd5b600082015167ffffffffffffffff81111561134d57600080fd5b6113598482850161103f565b91505092915050565b61136b81611b77565b82525050565b61137a81611b2f565b82525050565b61138981611b41565b82525050565b61139881611b41565b82525050565b60006113a982611aca565b6113b38185611afc565b93506113c3818560208601611be0565b6113cc81611c13565b840191505092915050565b60006113e282611abf565b6113ec8185611aeb565b93506113fc818560208601611be0565b61140581611c13565b840191505092915050565b61141981611b89565b82525050565b600061142a82611ae0565b6114348185611b1e565b9350611444818560208601611be0565b61144d81611c13565b840191505092915050565b600061146382611ad5565b61146d8185611b0d565b935061147d818560208601611be0565b61148681611c13565b840191505092915050565b600061149e602083611b1e565b91507f436861696e537065635368612073686f756c64206e6f7420626520656d7074796000830152602082019050919050565b60006114de602083611b1e565b91507f436861696e5370656355726c2073686f756c64206e6f7420626520656d7074796000830152602082019050919050565b600061151e601d83611b1e565b91507f446f636b65725368612073686f756c64206e6f7420626520656d7074790000006000830152602082019050919050565b600061155e601883611b1e565b91507f4572726f723a20416c726561647920436f6e6669726d656400000000000000006000830152602082019050919050565b600061159e601f83611b1e565b91507f4e6577206f776e657220616464726573732063616e6e6f7420626520307830006000830152602082019050919050565b60006115de601383611b1e565b91507f53656e646572206973206e6f74206f776e6572000000000000000000000000006000830152602082019050919050565b600061161e602583611b1e565b91507f4572726f723a204e6f206368616e67657320696e20746865207061737365642060008301527f53746174650000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611684601e83611b1e565b91507f446f636b65724e616d652073686f756c64206e6f7420626520656d70747900006000830152602082019050919050565b60006116c4601f83611b1e565b91507f4572726f723a20596f7520617265206e6f7420612076616c696461746f7221006000830152602082019050919050565b600060e083016000830151848203600086015261171482826113d7565b9150506020830151848203602086015261172e8282611458565b9150506040830151848203604086015261174882826113d7565b915050606083015184820360608601526117628282611458565b91505060808301516117776080860182611380565b5060a083015161178a60a08601826117a8565b5060c083015161179d60c08601826117a8565b508091505092915050565b6117b181611b6d565b82525050565b60006020820190506117cc6000830184611371565b92915050565b60006020820190506117e76000830184611362565b92915050565b600060c0820190506118026000830189611371565b8181036020830152611814818861139e565b90508181036040830152611828818761141f565b9050818103606083015261183c818661139e565b90508181036080830152611850818561141f565b905061185f60a083018461138f565b979650505050505050565b600060208201905061187f600083018461138f565b92915050565b600060208201905061189a6000830184611410565b92915050565b600060208201905081810360008301526118b981611491565b9050919050565b600060208201905081810360008301526118d9816114d1565b9050919050565b600060208201905081810360008301526118f981611511565b9050919050565b6000602082019050818103600083015261191981611551565b9050919050565b6000602082019050818103600083015261193981611591565b9050919050565b60006020820190508181036000830152611959816115d1565b9050919050565b6000602082019050818103600083015261197981611611565b9050919050565b6000602082019050818103600083015261199981611677565b9050919050565b600060208201905081810360008301526119b9816116b7565b9050919050565b600060208201905081810360008301526119da81846116f7565b905092915050565b6000604051905081810181811067ffffffffffffffff82111715611a0557600080fd5b8060405250919050565b600067ffffffffffffffff821115611a2657600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff821115611a5257600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff821115611a7e57600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff821115611aaa57600080fd5b601f19601f8301169050602081019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b6000611b3a82611b4d565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000611b8282611bad565b9050919050565b6000611b9482611b9b565b9050919050565b6000611ba682611b4d565b9050919050565b6000611bb882611bbf565b9050919050565b6000611bca82611b4d565b9050919050565b82818337600083830152505050565b60005b83811015611bfe578082015181840152602081019050611be3565b83811115611c0d576000848401525b50505050565b6000601f19601f8301169050919050565b611c2d81611b2f565b8114611c3857600080fd5b50565b611c4481611b41565b8114611c4f57600080fd5b50565b611c5b81611b6d565b8114611c6657600080fd5b5056fea265627a7a7230582070f7a284b1ab092d7cf8a14ca7bf4b7a68d6e2cb8441f82436e624a898b0ebd46c6578706572696d656e74616cf5003700000000000000000000000012047000000000000000000000000000000000080000000000000000000000001204700000000000000000000000000000000005" + } + }, + "nodes": [ + "enode://cc67008e850c4b64702f1664f18704dd23980fb574138588904270739dca3a9c417ac3f97077b0f4e4872a5db109195f7137c156314dbcc724eabd809044553e@ewc-bootnode-02.energyweb.org:30303", + "enode://34f97743b9c07fac84c2db921337f006b5932e14c29df496951bdcfe3fce71e3d1504c25d66156dae01065623849b4fe940168c7e3f21c49b538af0cabb5805f@ewc-bootnode-03.energyweb.org:30303", + "enode://80e49825bb6bdfbf69576fd4a5f7bb173db98c08439bd7a019e2d42548afbb1f70232b74ede42dbd99cc0de3990a0101d49543c1b299027d2fd6f5a2c81eff75@ewc-bootnode-05.energyweb.org:30303", + "enode://1cd00f54ddaa41793d32500f0cb123d43e95f5ed18220c367d5a4db7d111e5fb59f250c397e40977562881875827f022d88a51e51171daaebf916beaa60e2139@ewc-bootnode-06.energyweb.org:30303", + "enode://3a8588bd883ea3bce606b08e7ca71d55717077cb3d25d3c00421ac371fbae286b94f58ba2e739b17b64c4d0d3e19f1b0ae2e47962703b42d7f36f1b9a448d4ea@ewc-bootnode-09.energyweb.org:30303", + "enode://69749dbe7e6f5fceaeb0a16f60353b3ec04825a12400e6d581fe980275e96fecb464276e61d79fc1628e448f1f74da2985d778ea54e0e8e7c64d980f2b3b6a94@ewc-bootnode-10.energyweb.org:30303" + ] +} diff --git a/ethcore/res/ethereum/expanse.json b/ethcore/res/ethereum/expanse.json index 073d8fe483..5b950e28b0 100644 --- a/ethcore/res/ethereum/expanse.json +++ b/ethcore/res/ethereum/expanse.json @@ -76,9 +76,47 @@ "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0xC3500", "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0xC3500", "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0xC3500", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0xC3500", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0xC3500", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0xC3500", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0xC3500", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, "bb94f0ceb32257275b2a7a9c094c13e469b4563e": { "balance": "10000000000000000000000000" }, diff --git a/ethcore/res/ethereum/foundation.json b/ethcore/res/ethereum/foundation.json index 8f96a842a7..f55e5492b8 100644 --- a/ethcore/res/ethereum/foundation.json +++ b/ethcore/res/ethereum/foundation.json @@ -181,8 +181,8 @@ "stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" }, "hardcodedSync": { - "header": "f90215a0ea51746efaaede944c3397e41ae72b7908c8ce25967c1edcd02618b068486feba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794829bd824b016326a401d083b33d092293333a830a0aee38c1032f191c3d42cc581f53d31adb1f0d91f463e6a8c12fc35fd1db58d5aa0568149713d45e959d5d07624917617d0d7865124c25c28eb9b798013096ddeafa0847bb20a0b62d1d8e2b467c33b28ded6796c556cd2b2a169b640b40e58fd2340b9010048c03883204a1ef0204300012248c8841814900c04362858000450c8927a22a88d5b471c4869c00001d8641080695910c20801022c2910408829a8002620115dc8200ec2851300611284301c3243e091030706068c8160505403250d03f44437410080072a69048082b43070805d08424a021328221500101418463040904ca094a189c801e50000c41402603426c4701a6302e1023040080d8380e21d600a2083003a2604082001b183068d1470840a49008a514148800a08030a8002c821b24010f20ea31c55060582801c14483ec29d4081c7152d2244840016c123da6f42249b6002c8401618a0000a8c8df892954d8080800c160244453086480d8264b6870ae8321581e6cb836ed001837a30a08379e5a2845c72b9c0947070796520e4b883e5bda9e7a59ee4bb99e9b1bca06883c088b374f7c667ed0fda0f1ec7c18890c892b88f14b41f03e7d927bcca82880db92c004f0313a8", - "totalDifficulty": "9242028122621986440675", + "header": "f90212a0113ba3b1153987fc483b01ccfe9ecadbdc36a7b264be75d6486cb6b694cc38a1a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452bc44d5378309ee2abf1539bf71de1b7d7be3b5a0d91db5900e312a1ba8d39505406a95dc0ea20393b723c4bf488ade4e3c4ee4c3a05e63ab076852043b1c2fe010e2f14ab13dcc8e1c546ac497a24ce88c4abf3056a0b72e4a776f895459b6bf0937040990d868b1f45889aeaa26684e07472263fc31b90100b00200000063664554889124822ce2001022840543085d5810042382888542ca3816801780384384cd6851081cdc4d4b2b205a814b049198110a6869d60f4009a79c3854c9000581044889080000611c09142200106552000044027024004038092102814ed6c48040a8715851088a20108e80165f8c0c514019037a0000121304b2343416800b029000024404248238a06818414cb8690244879491855405026bc8250220520992c2380099d10024411c6048424083d1307822442d8444700405147883c4c041300aaa2408bb61084012983825a22830040a180106b5e27182088060b111515832902903a8f1d432a48004d0250437106a503491000048a91587067a897789f4d78371d801837a309c8379ffd7845c9d879e9150505945206e616e6f706f6f6c2e6f7267a0db22736cb3f06f9c86804902731fa6841eaaa1cd6326ea2a30e9c304d48bdd04880323b06837344cb8", + "totalDifficulty": "9633968582330911261986", "CHTs": [ "0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc", "0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11", @@ -3729,7 +3729,104 @@ "0x8ed199e2fd654bfc9dfd5e7ea7dc82bea9f4535eb480c95984a5a6bc1533bf8e", "0x4e5475dae57c548460d4ddd15583223bf2a4a2046c2ee56ca670892794a37d90", "0x80409971b3e59ec71deb1a158a92ab6fe8318cb9adebcf583586e23e42d370c4", - "0xeb35d7c78965874110f67b77307deae4bb29dc98c01fbac3737409ede61df7c6" + "0xeb35d7c78965874110f67b77307deae4bb29dc98c01fbac3737409ede61df7c6", + "0xd358b672db99b007ac54ef3ea7c77c0eb0b4e9cc1437ca4eb70d71aaaf84b6f2", + "0x0ca4c79c1709b947794ae73dd3b73b357273c4e5cfc83ec85c4c2b649e10740f", + "0x704635b2335b5ad2be0e586e60770dc1e0548794ee2c1670cbfbc2ed0c1f64ae", + "0x6a6f2425c865216b49e7e73026fd2e9cc02f131c0050ce849f274c37828909f0", + "0xce31e62ac098db0fef0823941009b826d4e5b8e11f2e01208ee6abccb160c0cc", + "0x5669c0e6ccaa8abff08e944fe8bdcf0001dce9c10ef8b90d7f821819e028dcb6", + "0x37b59281d4eec501ed45d68c2bfac450d336ee5a18ecb7d2d812763d2cfd4321", + "0xfb52f084a5ffd63001f47acdb2ea62e91714af63f896c151100350d83bd2c7e4", + "0x67bfc4a94fde6e81b54ebe52914c0d73a053bbac22d6d64862e987e53c78ed61", + "0x49c141a8ac1124f40d06c569f49363a8af092d0028b02d8f4c895af2f86d0f28", + "0x5c81c85021692d5dd1bdbd3a4543ec86d49e674380a0e5f59d4400902d7e753b", + "0x9b46d19b0cee63461453a487bbf855fb4a7d70933ce2b7445d1dce8dbbc11cf9", + "0x50fe5cb0ddf34ed2ee8341848bc00df89fda05fbf0ebb1b34d12afe9e5ae4d1a", + "0xd56b4c4880798175c2db50c5c5d6845b5c1e7b6b33172ba107f5de075ed09def", + "0xe0928a4092e5ab5b9a34a8748c3ddf86a6a9ab50e85777c4e1e8088ac7b44ae7", + "0xfcde6d53ff8286afecafa27d608e94c07a4d78813edeccb73a1076772d1f7e83", + "0x1bff0dc76b0d8877a9ea133a023a5dc0f88559f16f0adffbf7b4d58b6be487a1", + "0x5252a71f6c9784b538ecd810bded0520f349f5aa748657a9b4422474eee08388", + "0xc4cccd5ae51babfe8e9f76af2c64227b0fd63bc2f4336b7820a32846516d9835", + "0xd07bc360f06a492a13047247448ba37fc9a167bd81ee63607976be269d245e14", + "0x9499022a6b509dd05eae2a7c799c332382b810843065e82ec72891b771cc3a8a", + "0x0ba258fb2666908035e53ec37a96ee13719779de43f14a57223b704961ef667a", + "0x4dec79cac5e3b414aa835c69bb2c580ccc03eaed675b61070f37b606ff4715bd", + "0xac640ffa67870bd91b1ff36450256fb1e5f59e65f4ef844875185c38f7f986b5", + "0x0af93eccdfbb75dc353ff31949329b3c96ffa93f63e9ae4a515f6e177e201d35", + "0x5a2d5ba9defce6db1bff0bbbe4eee170fe3b9c0ecb4a1ec6e16f904b55c07beb", + "0xd92f1c26de95255b1e0926341c35b5bfd106820dbdcb381400516d247062f3fd", + "0x447ec0cf1a32e8201cb92d0ad13adc6e664a07612bf38ce9c598c799cd947fb1", + "0x28460192df35aec41fe3992efc94da904d69e4b65e518fd2c530b38c1ec88819", + "0x6b0557132b0efe568a96f77fad4f1e18cf05670c007488052f347cf3461ee98c", + "0xb82f3f400a0edc100ddd6e82c2ea587eb5d56ea0f8faa379f8fa259f31ea0838", + "0x370b650e0bd14d9e5d749f628fca91ff47184473b6cba948e9ad3492a68bed5e", + "0x794e423feca451babc044923a79ceab62ff3a9a7e8947dcadd0d91f78a11cff6", + "0x7fe410432bfc7048e6685eb6bf0b4ae9808864a2e09ed1d373dc211f40c59da7", + "0x9f53d260f145de7b48c04829abd97989bc11d748af7d119ebf56948ca438913a", + "0xad5ad5cd5ff452e16c07bba12f0b34bb1c3c8c33d54db45b515cf6761d6a1cc8", + "0xcc6e322ea2c52af09d720524c85629019eac5ca01dcec5da887ad4b32157b9e4", + "0x5d3ddb9fa275898453e8430b26270e2812709717898683f0a3291291b29d688a", + "0xeff621bef47694a862a320a661b691b491e4a5c44e1d2026c9756f84903a6375", + "0x110e7059d20e4531323dcf981ad6cb9d67d56815c54394ab1b0b7af4235aa218", + "0xe44d27931b9429204cd2e9cba838f0ed707d5668ab55ecf2c906b2748fa1f16d", + "0x9d7166683764cde8445c58697df637cd48e35b3ad00f6e6d4bbf12844ba217c5", + "0xf5f6625754100a91cd7283d47e72cca73c39e5fa2e0405d427430bccd49cc2bb", + "0xd6b27ee81a557ff5d8947225c19f3ba023af18415a413acdf438548b24902427", + "0xccc665895dbabf0d8775c5fddf167b41579b0e6bff8fe99c8da00622334c8861", + "0x1986e5fd526af0a0e74ab83cb82c18dbd5a73fe72b94c8ca10318f8f6bd2d98a", + "0xd3f245d6f37b0c47506fc4a2b12d85ff87eb35c2f45f82c3e5bebdc7362d8cd6", + "0x53b97494c77ef9a843ce61b2a58231bc145b492b710fc3dcf79c297187993bbf", + "0x00d4cd1f9460a8625ed0a539257e58a9ab8051ff239172f0a9437cb9f0d1a11f", + "0x1c3d92f1e67b04c24db2eb04184ca7ccd5533540aca4dcbe084a70648c347ee5", + "0x200e39cb704bcda42f547c0cae54c0dd4c0b1aaf17469d69deaa67d3ef0d95c5", + "0x5aa208366dc50c2e9f0075b0e8aad396851f54a42c9ec1114c2994da0c2fcace", + "0xbea70811c324fb1553c4fc492521ce062756da0a469d8f98cd6c0f7a3a7b5e3a", + "0x79aa191ef9975049a5f2b8b7e2921a3f78d045b99b7a569a93680c5ee2600a18", + "0x233fd477509141aed423948a0c5c5b8f0ab8cc3c4836c0f44c8cd6c0811b419c", + "0x1737e144530678804416cd7c3c8200f54f395bf7712c9ade8340988e1e123af5", + "0xbdad2ae32cbfc13446adfe9e4101f32fb52b1e336c165a1125c917d6c1a1fceb", + "0xc20dedeedd63be4c10d92d9d0e7b47e20d503f331cb31d47ec9e99b915305ba0", + "0x262281f50e2892d8cfca3b8f8a6645b5931fb4601755f02fb863d719cd690381", + "0xb0a717f11ff1e3f1a4bd775792c7e5a75af6e56967ab1615be6b4941ca9315e3", + "0xe8f45b1aee0fb0e87148b316ee0ce662ae3bb2abd05e9666429fcf30893641b1", + "0xe7a439e2577c4f892921f798efa19353d236146b849c20253b07f03194b36286", + "0xf4eda704d4864d8fccefecc246fb683dbdeee5468a53dd11d71d71477d170422", + "0x308d977f739b7a8cb4810242fb447a8f6cad45389a127f5822ca2df48fa9df86", + "0x3115d6d0f174e00bf3e5704f57e44b62f7e279894ce62f39568ffe4367fc5a44", + "0x6b6e6354b8d1e1ab0430fe2a5068b2b2263ff453676dbfdce5da60a6d625f20f", + "0x9b8a7b122572f459d946e67a1c78973040bcf67a64327f689d4016c53afcc4cf", + "0xa367c0bc2e6029afec518db94fa79288801f5ebf2cba50980fc9754a40784d19", + "0xc1a017142eac944b5fda4cd66a9b6b6dc64551c3ce958e8811797433b96ec5d8", + "0xc9e3999a3f162d42ae52644ce4f765b5ccc7fe2a4c91cc59048eeb8c8086718e", + "0x67c135523c9703aa1f1b653d9279804af4cd81cd3de99e10a853b42d78143914", + "0x9af2390bb01b245c65f76454f1c80102871131417cc8fbff4b1ada056d04dd47", + "0xf4cec7d4f4a76c769021ab0dab848d668fd36e910259e45094d88defabd13448", + "0xe2a224fd4510ac5f8a6782d2eed14ee164e6bb92d3f0a7e5e71497046fe9f30c", + "0x9884ca2b5533c36e03fecf28470fd3c45292dc623fb220c5eb0a580781fbe724", + "0x078b1365c5dc77fdea6bb010fab6c4dede06e27386d4d5f205bf7e7857b03865", + "0x8f930fa645409fc1d7fb28637360489a5e5eaa6554857441c3fd8990243d9972", + "0x2e21ac485ed90007e8b69cf247c28b25361729bcc7501a3296f9c06dd0742888", + "0x46c3ea9e86ad55d87b6f5d50fd9c145bcb6ca90a4d570c1f86b5532b0762d8c0", + "0x87edc87f5ac353d64b0f157ce3e3180ce73fdd1f0ae9db1406e49581f1780de7", + "0xc940108991c82f871c3eea33ec93951c9bc33cd0aba1c77262cb6fc6ea16f4eb", + "0xba2f1d37cebd9bcde635bee4c0f260af8fddb43a84508f244b562dd1f7bdbe92", + "0x738e8d02870cf37ba27db2eb621d5f7b32a225010de41e3983ed389ebaa0e364", + "0x84af8e6e7ceb53e068bdf16091bfe966458bb5d3e4a925360411a213aaf46a5c", + "0x548302ac8a0af1ef5bb91d469f66f8669cdb2a07c432e7504a806e00487adb63", + "0x35bc3a284170d090e6fe053d3bd2a8fc3aa299d113b69b90340ca4c7e019016d", + "0xfe7b61c4388f2615642f9ffb44279f31a98c0f0d2f3f37b5f77ba09a67c12737", + "0x864581a4e526055847c252f6169bc54b5a1615de8e1cb7e80c649315b04a9aab", + "0xb8b4c67301cf9d3e91ae59a0394c8085737358bde297c58688b48a9d33c04205", + "0xa1ee0d1c7d50d37f96505ed06b166722f47fdd784b71bb3d47539ae40be96262", + "0x63b2658609397ec6a9e9d9d0a5b318b79b1e39348606ca53e0f84f6466d3aad4", + "0x2211abc4f8bbd6784aa191805465b10520a6c505d6257063aa9b911d5781fb89", + "0xefed35d1327328deece22922f08d3c3931c80c1ea9a8bc719b8226f38823bb6d", + "0x64b862e2d5a6c24d569f3352b8524ebfecfd5a3205a3200ec78df72d79a66838", + "0x6da8edf169a9c78307258a723c1ac1d96db20a7131018efad16f0606683c0f07", + "0xbae1427beab8c3e71cea57e5f9cdd55bc278c6d6073ae2628f0d3efbf9894a42", + "0x389bbd1b3fa390e8d3339cf5b018ec64d9cfc02bbcb801acad0857fe377ed83b" ] }, "nodes": [ @@ -3824,10 +3921,11 @@ "builtin": { "name": "alt_bn128_add", "activate_at": "0x42ae50", + "eip1108_transition": "0x7fffffffffffff", "pricing": { - "linear": { - "base": 500, - "word": 0 + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 } } } @@ -3836,10 +3934,11 @@ "builtin": { "name": "alt_bn128_mul", "activate_at": "0x42ae50", + "eip1108_transition": "0x7fffffffffffff", "pricing": { - "linear": { - "base": 40000, - "word": 0 + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 } } } @@ -3848,10 +3947,13 @@ "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x42ae50", + "eip1108_transition": "0x7fffffffffffff", "pricing": { "alt_bn128_pairing": { "base": 100000, - "pair": 80000 + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 } } } diff --git a/ethcore/res/ethereum/goerli.json b/ethcore/res/ethereum/goerli.json new file mode 100644 index 0000000000..e7aaa4c485 --- /dev/null +++ b/ethcore/res/ethereum/goerli.json @@ -0,0 +1,936 @@ +{ + "name": "Görli Testnet", + "dataDir": "goerli", + "engine": { + "clique": { + "params": { + "period": 15, + "epoch": 30000 + } + } + }, + "params": { + "accountStartNonce": "0x0", + "chainID": "0x5", + "eip140Transition": "0x0", + "eip145Transition": "0x0", + "eip150Transition": "0x0", + "eip155Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0", + "eip1014Transition": "0x0", + "eip1052Transition": "0x0", + "eip1283Transition": "0x0", + "eip1283DisableTransition": "0x0", + "eip1283ReenableTransition": "0x17d433", + "eip1344Transition": "0x17d433", + "eip1706Transition": "0x17d433", + "eip1884Transition": "0x17d433", + "eip2028Transition": "0x17d433", + "gasLimitBoundDivisor": "0x400", + "maxCodeSize": "0x6000", + "maxCodeSizeTransition": "0x0", + "maximumExtraDataSize": "0xffff", + "minGasLimit": "0x1388", + "networkID": "0x5" + }, + "genesis": { + "author": "0x0000000000000000000000000000000000000000", + "difficulty": "0x1", + "extraData": "0x22466c6578692069732061207468696e6722202d204166726900000000000000e0a2bd4258d2768837baa26a28fe71dc079f84c70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0xa00000", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "seal": { + "ethereum": { + "nonce": "0x0000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "timestamp": "0x5c51a607" + }, + "nodes": [ + "enode://06333009fc9ef3c9e174768e495722a7f98fe7afd4660542e983005f85e556028410fd03278944f44cfe5437b1750b5e6bd1738f700fe7da3626d52010d2954c@51.141.15.254:30303", + "enode://176b9417f511d05b6b2cf3e34b756cf0a7096b3094572a8f6ef4cdcb9d1f9d00683bf0f83347eebdf3b81c3521c2332086d9592802230bf528eaf606a1d9677b@13.93.54.137:30303", + "enode://573b6607cd59f241e30e4c4943fd50e99e2b6f42f9bd5ca111659d309c06741247f4f1e93843ad3e8c8c18b6e2d94c161b7ef67479b3938780a97134b618b5ce@52.56.136.200:30303", + "enode://67913271d14f445689e8310270c304d42f268428f2de7a4ac0275bea97690e021df6f549f462503ff4c7a81d9dd27288867bbfa2271477d0911378b8944fae55@157.230.239.163:30303", + "enode://a87685902a0622e9cf18c68e73a0ea45156ec53e857ef049b185a9db2296ca04d776417bf1901c0b4eacb5b26271d8694e88e3f17c20d49eb77e1a41ab26b5b3@51.141.78.53:30303", + "enode://ae8658da8d255d1992c3ec6e62e11d6e1c5899aa1566504bc1ff96a0c9c8bd44838372be643342553817f5cc7d78f1c83a8093dee13d77b3b0a583c050c81940@18.232.185.151:30303", + "enode://ae8658da8d255d1992c3ec6e62e11d6e1c5899aa1566504bc1ff96a0c9c8bd44838372be643342553817f5cc7d78f1c83a8093dee13d77b3b0a583c050c81940@18.232.185.151:30303", + "enode://b477ca6d507a3f57070783eb62ba838847635f8b1a0cbffb8b7f8173f5894cf550f0225a5c279341e2d862a606e778b57180a4f1db3db78c51eadcfa4fdc6963@40.68.240.160:30303" + ], + "accounts": { + "0x0000000000000000000000000000000000000000": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000001": { + "balance": "0x1", + "builtin": { + "name": "ecrecover", + "pricing": { + "linear": { + "base": 3000, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000002": { + "balance": "0x1", + "builtin": { + "name": "sha256", + "pricing": { + "linear": { + "base": 60, + "word": 12 + } + } + } + }, + "0x0000000000000000000000000000000000000003": { + "balance": "0x1", + "builtin": { + "name": "ripemd160", + "pricing": { + "linear": { + "base": 600, + "word": 120 + } + } + } + }, + "0x0000000000000000000000000000000000000004": { + "balance": "0x1", + "builtin": { + "name": "identity", + "pricing": { + "linear": { + "base": 15, + "word": 3 + } + } + } + }, + "0x0000000000000000000000000000000000000005": { + "balance": "0x1", + "builtin": { + "name": "modexp", + "activate_at": "0x0", + "pricing": { + "modexp": { + "divisor": 20 + } + } + } + }, + "0x0000000000000000000000000000000000000006": { + "balance": "0x1", + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x00", + "eip1108_transition": "0x17d433", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0x0000000000000000000000000000000000000007": { + "balance": "0x1", + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x00", + "eip1108_transition": "0x17d433", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0x0000000000000000000000000000000000000008": { + "balance": "0x1", + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x00", + "eip1108_transition": "0x17d433", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, + "0x0000000000000000000000000000000000000009": { + "balance": "0x1", + "builtin": { + "name": "blake2_f", + "activate_at": "0x17d433", + "pricing": { + "blake2_f": { + "gas_per_round": 1 + } + } + } + }, + "0x000000000000000000000000000000000000000a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000010": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000011": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000012": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000013": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000014": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000015": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000016": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000017": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000018": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000019": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000020": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000021": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000022": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000023": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000024": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000025": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000026": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000027": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000028": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000029": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000030": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000031": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000032": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000033": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000034": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000035": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000036": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000037": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000038": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000039": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000040": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000041": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000042": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000043": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000044": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000045": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000046": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000047": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000048": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000049": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000050": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000051": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000052": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000053": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000054": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000055": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000056": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000057": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000058": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000059": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000060": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000061": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000062": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000063": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000064": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000065": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000066": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000067": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000068": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000069": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000070": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000071": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000072": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000073": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000074": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000075": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000076": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000077": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000078": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000079": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000080": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000081": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000082": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000083": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000084": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000085": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000086": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000087": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000088": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000089": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000090": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000091": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000092": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000093": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000094": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000095": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000096": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000097": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000098": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000099": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009f": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000aa": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ab": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ac": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ad": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ae": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000af": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ba": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000be": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bf": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ca": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ce": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cf": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000da": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000db": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000dc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000dd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000de": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000df": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ea": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000eb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ec": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ed": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ee": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ef": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fa": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fe": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ff": { + "balance": "0x1" + }, + "0x4c2ae482593505f0163cdefc073e81c63cda4107": { + "balance": "0x152d02c7e14af6800000" + }, + "0xa8e8f14732658e4b51e8711931053a8a69baf2b1": { + "balance": "0x152d02c7e14af6800000" + }, + "0xd9a5179f091d85051d3c982785efd1455cec8699": { + "balance": "0x84595161401484a000000" + }, + "0xe0a2bd4258d2768837baa26a28fe71dc079f84c7": { + "balance": "0x4a47e3c12448f4ad000000" + } + } +} diff --git a/ethcore/res/ethereum/istanbul_test.json b/ethcore/res/ethereum/istanbul_test.json new file mode 100644 index 0000000000..1276dc4c53 --- /dev/null +++ b/ethcore/res/ethereum/istanbul_test.json @@ -0,0 +1,120 @@ +{ + "name": "Istanbul (test)", + "engine": { + "Ethash": { + "params": { + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x1BC16D674EC80000", + "homesteadTransition": "0x0", + "eip100bTransition": "0x0", + "difficultyBombDelays": { + "0": 5000000 + } + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "accountStartNonce": "0x00", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x1", + "maxCodeSize": 24576, + "maxCodeSizeTransition": "0x0", + "eip150Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip155Transition": "0x0", + "eip658Transition": "0x0", + "eip145Transition": "0x0", + "eip1014Transition": "0x0", + "eip1052Transition": "0x0", + "eip1283Transition": "0x0", + "eip1283DisableTransition": "0x0", + "eip1283ReenableTransition": "0x0", + "eip1344Transition": "0x0", + "eip1706Transition": "0x0", + "eip1884Transition": "0x0", + "eip2028Transition": "0x0" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000042", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x400000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x1388" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x00", + "eip1108_transition": "0x0", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x00", + "eip1108_transition": "0x0", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x00", + "eip1108_transition": "0x0", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, + "0000000000000000000000000000000000000009": { + "builtin": { + "name": "blake2_f", + "activate_at": "0x00", + "pricing": { + "blake2_f": { + "gas_per_round": 1 + } + } + } + } + } +} diff --git a/ethcore/res/ethereum/kotti.json b/ethcore/res/ethereum/kotti.json new file mode 100644 index 0000000000..bc696a7db5 --- /dev/null +++ b/ethcore/res/ethereum/kotti.json @@ -0,0 +1,907 @@ +{ + "name": "Kotti Testnet", + "dataDir": "kotti", + "engine": { + "clique": { + "params": { + "period": 15, + "epoch": 30000 + } + } + }, + "params": { + "accountStartNonce": "0x0", + "chainID": "0x6", + "eip140Transition": "0xaef49", + "eip150Transition": "0x0", + "eip155Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0xaef49", + "eip161dTransition": "0xaef49", + "eip211Transition": "0xaef49", + "eip214Transition": "0xaef49", + "eip658Transition": "0xaef49", + "gasLimitBoundDivisor": "0x400", + "maxCodeSize": "0x6000", + "maxCodeSizeTransition": "0xaef49", + "maximumExtraDataSize": "0xffff", + "minGasLimit": "0x1388", + "networkID": "0x6" + }, + "genesis": { + "author": "0x0000000000000000000000000000000000000000", + "difficulty": "0x1", + "extraData": "0x000000000000000000000000000000000000000000000000000000000000000025b7955e43adf9c2a01a9475908702cce67f302a6aaf8cba3c9255a2b863415d4db7bae4f4bbca020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0xa00000", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "seal": { + "ethereum": { + "nonce": "0x0000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "timestamp": "0x5c2d2287" + }, + "nodes": [ + "enode://06333009fc9ef3c9e174768e495722a7f98fe7afd4660542e983005f85e556028410fd03278944f44cfe5437b1750b5e6bd1738f700fe7da3626d52010d2954c@51.141.15.254:30303", + "enode://93c94e999be5dd854c5d82a7cf5c14822973b5d9badb56ad4974586ec4d4f1995c815af795c20bb6e0a6226d3ee55808435c4dc89baf94ee581141b064d19dfc@80.187.116.161:25720", + "enode://ae8658da8d255d1992c3ec6e62e11d6e1c5899aa1566504bc1ff96a0c9c8bd44838372be643342553817f5cc7d78f1c83a8093dee13d77b3b0a583c050c81940@18.232.185.151:30303", + "enode://b477ca6d507a3f57070783eb62ba838847635f8b1a0cbffb8b7f8173f5894cf550f0225a5c279341e2d862a606e778b57180a4f1db3db78c51eadcfa4fdc6963@40.68.240.160:30303" + ], + "accounts": { + "0x0000000000000000000000000000000000000000": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000001": { + "balance": "0x1", + "builtin": { + "name": "ecrecover", + "pricing": { + "linear": { + "base": 3000, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000002": { + "balance": "0x1", + "builtin": { + "name": "sha256", + "pricing": { + "linear": { + "base": 60, + "word": 12 + } + } + } + }, + "0x0000000000000000000000000000000000000003": { + "balance": "0x1", + "builtin": { + "name": "ripemd160", + "pricing": { + "linear": { + "base": 600, + "word": 120 + } + } + } + }, + "0x0000000000000000000000000000000000000004": { + "balance": "0x1", + "builtin": { + "name": "identity", + "pricing": { + "linear": { + "base": 15, + "word": 3 + } + } + } + }, + "0x0000000000000000000000000000000000000005": { + "balance": "0x1", + "builtin": { + "name": "modexp", + "activate_at": "0xaef49", + "pricing": { + "modexp": { + "divisor": 20 + } + } + } + }, + "0x0000000000000000000000000000000000000006": { + "balance": "0x1", + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0xaef49", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0x0000000000000000000000000000000000000007": { + "balance": "0x1", + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0xaef49", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0x0000000000000000000000000000000000000008": { + "balance": "0x1", + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0xaef49", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, + "0x0000000000000000000000000000000000000009": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000010": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000011": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000012": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000013": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000014": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000015": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000016": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000017": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000018": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000019": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000020": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000021": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000022": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000023": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000024": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000025": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000026": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000027": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000028": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000029": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000030": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000031": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000032": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000033": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000034": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000035": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000036": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000037": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000038": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000039": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000040": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000041": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000042": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000043": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000044": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000045": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000046": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000047": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000048": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000049": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000050": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000051": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000052": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000053": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000054": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000055": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000056": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000057": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000058": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000059": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000060": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000061": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000062": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000063": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000064": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000065": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000066": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000067": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000068": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000069": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000070": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000071": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000072": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000073": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000074": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000075": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000076": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000077": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000078": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000079": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000080": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000081": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000082": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000083": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000084": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000085": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000086": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000087": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000088": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000089": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000090": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000091": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000092": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000093": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000094": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000095": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000096": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000097": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000098": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000099": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009f": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000aa": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ab": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ac": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ad": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ae": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000af": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ba": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000be": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bf": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ca": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ce": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cf": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000da": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000db": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000dc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000dd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000de": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000df": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ea": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000eb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ec": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ed": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ee": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ef": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fa": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fe": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ff": { + "balance": "0x1" + }, + "0x25b7955e43adf9c2a01a9475908702cce67f302a": { + "balance": "0x84595161401484a000000" + }, + "0x6aaf8cba3c9255a2b863415d4db7bae4f4bbca02": { + "balance": "0x4a723dc6b40b8a9a000000" + } + } +} diff --git a/ethcore/res/ethereum/kovan.json b/ethcore/res/ethereum/kovan.json index ac86ebe7aa..34755e3ec2 100644 --- a/ethcore/res/ethereum/kovan.json +++ b/ethcore/res/ethereum/kovan.json @@ -7,17 +7,31 @@ "stepDuration": "0x4", "blockReward": "0x4563918244F40000", "validators": { - "list": [ - "0x00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED", - "0x00427feae2419c15b89d1c21af10d1b6650a4d3d", - "0x4Ed9B08e6354C70fE6F8CB0411b0d3246b424d6c", - "0x0020ee4Be0e2027d76603cB751eE069519bA81A1", - "0x0010f94b296a852aaac52ea6c5ac72e03afd032d", - "0x007733a1FE69CF3f2CF989F81C7b4cAc1693387A", - "0x00E6d2b931F55a3f1701c7389d592a7778897879", - "0x00e4a10650e5a6D6001C38ff8E64F97016a1645c", - "0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de" - ] + "multi": { + "0": { + "list": [ + "0x00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED", + "0x00427feae2419c15b89d1c21af10d1b6650a4d3d", + "0x4Ed9B08e6354C70fE6F8CB0411b0d3246b424d6c", + "0x0020ee4Be0e2027d76603cB751eE069519bA81A1", + "0x0010f94b296a852aaac52ea6c5ac72e03afd032d", + "0x007733a1FE69CF3f2CF989F81C7b4cAc1693387A", + "0x00E6d2b931F55a3f1701c7389d592a7778897879", + "0x00e4a10650e5a6D6001C38ff8E64F97016a1645c", + "0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de" + ] + }, + "10960440": { + "list": [ + "0x00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED", + "0x0010f94b296a852aaac52ea6c5ac72e03afd032d", + "0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de" + ] + }, + "10960500": { + "safeContract": "0xaE71807C1B0a093cB1547b682DC78316D945c9B8" + } + } }, "validateScoreTransition": "0x41a3c4", "validateStepTransition": "0x16e360", @@ -50,6 +64,11 @@ "eip1052Transition": "0x8c6180", "eip1283Transition": "0x8c6180", "eip1283DisableTransition": "0x9c7b61", + "eip1283ReenableTransition": "0xd751a5", + "eip1344Transition": "0xd751a5", + "eip1706Transition": "0xd751a5", + "eip1884Transition": "0xd751a5", + "eip2028Transition": "0xd751a5", "kip4Transition": "0x8c6180", "kip6Transition": "0x8c6180" }, @@ -64,8 +83,8 @@ "gasLimit": "0x5B8D80" }, "hardcodedSync": { - "header": "f90247a03dc1f4ed47c057717131ce81535d06194d990be6969334e9b8034e0c875f9dffa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940010f94b296a852aaac52ea6c5ac72e03afd032da0fd1833e970c207ca16e1e74d937c9d8e01a1f719643fb25963028427295fc2cca00d9d5e376ebe3558b412402702d34a93256bb03a61df9f17ae234f0a70f95b20a0129c38f28acd251820f96305d217511a725a1fae1a434d77034bd7efef1f9f5ab901000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000080000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffa839f3801837a1200834bb5f3845c7361249fde8302020a8f5061726974792d457468657265756d86312e33322e30826c6984171cd849b841d077cf579661ac8634ee865b5cc67918223aed686d6ba189624a6f6c0dfc5249418b25423e30e072a79d5377e01845d5234ff5e0b9b0207b1bf2515f805b47e300", - "totalDifficulty": "3500253997070921577369506418666760871805116639", + "header": "f90247a0d0c0f490e8e5045fa96fd77ce45ed983900feaab964b2b0ba3a2d3a6b5e0f842a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400d6cc1ba9cf89bd2e58009741f4f7325badc0eda0c91e59c81193c4fead4f64ecaa349e97056409dfbb787772ea3c1e55e7582b2ea08be1332f5e7eac286c7e5e5ccf3760e47f4a919548c15e748ad4351bb8405f9aa054e0533aa3433f4d07afa226230c867fc1e2844b5f49b25aba8df17630d9f8c8b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffe83a26801837a12008306f78d845c9da0b09fde830203088f5061726974792d457468657265756d86312e33332e30827769841727682cb841d6db93a25c84287603ee26e48db0dd301753840cc7283d411d3febd0485e02b2520086bebfb3aec1ab69403f45f0d59249bf0d458f33aa268dc4badefc73c8d300", + "totalDifficulty": "3571337622391237938633151520660827524104528124", "CHTs": [ "0xdb9557458495268ddd69409fc1f66631ed5ff9bf6c479be6eabe5d83a460acac", "0xd413800c22172be6e0b7a36348c90098955991f119ddad32c5b928e8db4deb02", @@ -5161,7 +5180,109 @@ "0x7ba1756f8fa6637d8cb6cc588a679f6366827bc2044865744837c63e8a5aadcc", "0xfc1a94a88f1e52bb78a0862eea4b996444f0264a3b301c1a31e59744d0216de8", "0x79472bc4de84a0c430f15bcf8569486cddd2de985409ceb8e48abec8aa3e3fe7", - "0x02bc578dcc715304c651a43d8dcb4a761d2073a93cca2c39da3ee513f0c6d415" + "0x02bc578dcc715304c651a43d8dcb4a761d2073a93cca2c39da3ee513f0c6d415", + "0xcf6175cfa60c20178241c18111d64f8837ec008751c5c333bee96c616d3cb6d1", + "0xd8281202c7b6da2a2541cd7f8d4270066f6546bec601e83647896ebdf0f2eb66", + "0xc4975ca8b2b71f61d2ba2825833df91096bd733301d54a3c7b6eca016ac14153", + "0xd01d6f14e93c8ba17a602378bce1c9bdb51373675109d6233c497b6c638a03a0", + "0x805057e19b7dd857ec014b4e6333bb60f48c02d29b128fe37a69f952df8ef16b", + "0x69c55bdbaf74bfa3d53ed32b79dd35ac2c24dd723a1c0bfd70871cefa4dbb8a8", + "0x523efe8059e6e8e2abd85d77d22123f97cbbd9864b4a3ac1fe0c0e4b8a7131eb", + "0xe5a4f129016bcfbd71913d1eff01cec924f9d130b8762c921d43fe5bbbbdbbd0", + "0x07f68773d16907348ac6e7c5be293ee1163ef41b91a2a8abb17a004c4796fb42", + "0x90742f88c71f9e689b6d2ca0236c48bba0e8ddeace5fa4d53a5af082055cfd73", + "0xaf7af6e9f695c4ca9e9a3c0229d94cbf02fcafbc4ed978a6b662862182308a72", + "0x0208eac99df5025cab13d9767a2ba3e42ba1eccb72cfa01d87e834d15eea3751", + "0xee9ff9384cef76b51a9d5b8eb12fd7e00ee7f8142f81bd68393e7fcf0eaef90a", + "0x4770986e657683d901d73df444836f11f169f94ac55ec81e4e19f2212052788c", + "0x9f9c16d009da6e8ee20d9d5f3bd7f1a77b853dfd19beef68d980fca6bce2b707", + "0x468efd7c8dad29cfff0e278fd950f89e2d5a57d6824c6c1a7a7659bd7e7c0ffe", + "0xd0391bd0a2c1fb2260d89bd5e519d4ef26b4945a7ad0c1b695687fe1b24698dd", + "0xdef9ee668e09f8769b2c706a8de426e06f0bd9c264e67bf0c0bb177b851cef23", + "0x10c5b79048e611c6e65f92dd54754753e595cd8f8f0f1005d7a647fa59deeb78", + "0x4ce6d5812d2565237a9b018ed6ec386cf3e9fe1f2f429605288f2ef744c5a940", + "0xbbacf6662d816d5eb14fc1271c1a3404de94e12c175545bc8273c231c280b789", + "0xb216fd154d3726f16907ae571728d92ae2199872f180e4cd6be3b53a8dd43ae0", + "0x2b76e6685604c69f29399451c66ce053ae033ab011eb52c97c112df968e37232", + "0xf93b8076ce0dc6742196d2c9af501fad39f570cd927e8fe3b8dac4127a20a6a4", + "0x35027cc654f998af75b8379fac0a9d51703f058b518880e25e658151619f1611", + "0x3e7f59319228d40e5e07c06b696ad6478237ed0c8a71cff418ac259c6b5579e4", + "0x7295e21fccabab1545c1e64a57f0401e62689057ab4fef26f70c8d02b63867ab", + "0xb06bcf07fe1345c41ba16df213d699e2e185ef2fd3b5e19b194459d0b7baffc1", + "0x1b13d005a29e35fff33373e2d8abc81805a85e7970b48dca8fd605069c8a0d85", + "0x90a5a61ce554bb73253d7f62c78b1764f03fb0fd8f65b6aae4f9e529acb1d991", + "0x1b1eccf7565339748947358caf473ba0cea743da2ed4790763d3ac8c402f261c", + "0xef9b05ae7ce93febce342336e40922e0884891da43aac06f3e9bbfc0aec688f9", + "0x11e1075b50de92e960d0d65e9b37b3cec81095f5afc2afccc6a9a8a325264049", + "0x128e6dba4205701f673dda9e980dc0c02f3c0c8cbc570f9a240257a261f81b39", + "0x6fd9d3eaffaeebd52ce93ac8fcd0f69b146e2c0b05218850de1c9218db8ecd8f", + "0xc47e3487ad63b7db773f413cd5302818061f168409c27ff2daba4579c0a4263f", + "0x0a55695d4a132063735f7319d3a90a2e0b83fd6ec6b6f9994068f928f68afe12", + "0x39403d84aa319edbb18e0313a61ae075ba9c5dae40b9850eccbfc3e09e6b27a7", + "0x79ba98eede4cd0b7031472baacab20df85c704a26e4cfaa6e01e3d4a9d26ca39", + "0x219240759d36a317f269e4301256164cb3709628e0ba07e90a6bedd664cea059", + "0xec793562f8498937f270c6ae5490ab8f2ad21a20510699dc4d7d4d0139efeb3b", + "0x0a3e9c209903b906013c8876cb4292e6ccc8b76dbf4af2ca25d8260f9f8e7c22", + "0x0eb347bb16d897b4909dcaf31a0009e198cd197f722075c112fe29bc9f017f20", + "0xac1e6a97c51f5051dc8f3a1fa33c1071e29aff3d7040972dbb5481ba215010b3", + "0x7e1be83ac51c7e68110c6984da43885af18bc9fe988a57ada7b2379d0a122563", + "0xdb01b1cb4084a43c9a57bf8a65a58245edee5bbbdcf0573a3626e9290b4a2e6a", + "0x6c97523c89da4c9325fe17d2e879bbd6b4693f3e6d807564de83ccf801e66737", + "0x7511c0b30bd4dfa6f9a4f38793ee11e2a616de5d9d2212024c0875052ef2559e", + "0x6faa338fd78b41f2ecb623d578520b373e0c74caafce95938161dbd95edb0e24", + "0x0622bf3e00fae0e244d138f73d16035cd05aa9e0c4c16d20b36adad77951c2d4", + "0x72e1ed876e0bcdbdd200dbd55a9d7e8248a4c7ca75588681b61f6f76eb980060", + "0x981a052ee33c36c52fc33598c2563ff3698e1efd130090658cb457bb814ecff8", + "0x2b732d67211042b340c1bc49682518bb00dfcaebd0cfe861b5d38df9c127ed64", + "0xfcba6702d24950030403f872be646d058039d735cf297fcedb5daa255d47ce72", + "0xba3bdc1bd47ab43c2d39ee67a512f306e987b577166d7037705a1fda772bbeec", + "0xa39705f9efc0c0b9051742b705dab9fed7a08b3a00ff15583e15de95a9933356", + "0x551658242a3237fda7b61eae6dc40f368ffbbe3e7f292bf1b3d291d1f21a631d", + "0x631783a116fb5af727d2617276bf310e9f018e1f072d9f3d5432773ec29a193a", + "0x7d2bee7cbf5aa7a5247f047b1147f55380e035a5ff1ce958037d96a539fada37", + "0xfbe38f5210d9fc7c3474be4ff932d1ca393a565426f5d1443537e962beabbbca", + "0xfc9b71f941a0a9dafd6356c4a42c369f22144b43f32f5d50fe3d4c1cf3ee3cda", + "0xa4eb11bb0a0e210af085dc446766f4bb0d19dfec04e9d5d0d2c0ee390597906d", + "0x42e8e9e3d4d6de275146369fa7c010a10979793276a4406bbfd77a543809e762", + "0xb2fef38ac3b58b498cdad7d195bdb3604ca0cfc0ca3c7282163636d3022def43", + "0x923269e9a526ddaa446a2e7acaea5189726ff77e664c20a341f6ad2f6b810d5f", + "0x02e876ba6df7c9ddd7a9ad9bbc15f5918b096e299260fc85a8c7ebaa71d7dde5", + "0x660442f393884c6c4b879168ab3c80c57318c6c62a67ba8df3788edf9ad7303f", + "0x37f7ab248fded056ae5ecde87bf51c1f4baea786fc7c9f5b6760ad13c90659ac", + "0x36fda244e2896e45d3a8a9ed67d7c09a2974c75944a7233f571928a497b55f8c", + "0x4914478536196c3c813fe151cdf37097c6dc9e8d5c0cf9b370fe7567905fc4be", + "0xcedb88613a1d6fbc24909963911efbc5ff56ba09377350b5e824123b50d1a910", + "0x236fe31e63e426111507b2f972547255bd12c6f5df9079953a8b8346179bba57", + "0x2f08e1b0ad4024814428237b4f0e7ca5a83257d25a1cb97f42db14307113916f", + "0x41e45a3a2239551e8cb9598fb855f3d8922386c2e004426e294d111a94856b92", + "0xd5d385b54446abfa8c78950aacae52edede3a7a65d9c7515043431a4498e4f85", + "0xf2d2eb5169760d81d16067b9453979783a2feea91dfa253baa3183f2419478b0", + "0xa5aac8d064c4f4cdfdd2c7f7326c1e0260aeb44be48b391616eb01fc6d30c95e", + "0xb2a298085b0a082fc1781aad1abd263e9cc2c5eeeaa70acd88e8bdfbc0be7d15", + "0xe2d19c438ddb9b96e77a9bc70566f49021bb6444569eea3cd039ecab4d61f73a", + "0xa8549fc117d3faba2ca53efb94bbb37e9cb82bed8273e408da5ed47f5df7aab4", + "0x161c898240dd6e0a0a1f1f5948c652a796bb6586995783a35e7ed6c3c02fb82b", + "0x57214b17853934f1a548a7e9942849a04b9220f5b783a9d2be7395108bdc12e7", + "0x7902ef6c69f5d0a3de1e45d8b46aebcf35aa87cc5f4644186f1c34614a429175", + "0xc290a119f495ff04f406c28461e2de50abf92743b7fdd680048e491044fc59b7", + "0x09bf0fa4aa8b65dcc8f937e46287eb2585c85c587b425f8a0af69d02948f35d9", + "0xff20130699483dee0caacca392c2ad58738f61ea2443869616a3bf006e0cd1ad", + "0x937c629f7307f7411a4b1cc5b92f6a1f1f42f716463f15c449c681d16525996f", + "0x7cd028f48f117d8da3d537f0bb0fb0c832d3111d16fc116bd06454ddd513a095", + "0x4bf15bb783cf917375b5494e00ce003d8da01c65fcbac40d44e62a6172f2cca8", + "0xaff5ceacf024e9146631c772e4e87f223a241e789c88ae083da716c9aa47b860", + "0x68c1db9a727678d2018ec98d0bbc369faec2fb1283b479abd5d6f2b1b04036aa", + "0xe70962a032b4cb81910cea9911eef50ede2eeaa6f487f1e9f8fbf88f133249b1", + "0x1bc2bd4440a1412fbf582d167e0d08629ad2bfe0bc0dfaeb5eb7730a4baf007c", + "0x2d4cbafea30b01e466b41f6911deae979f4f5c82dcbdd76f711f7bf9300c23f4", + "0x252e39a51862ebaf28d9b38f9fb842c70b5bf0669ca008b4c83c542e5236a1af", + "0xba04c89c7ec2867d778f8632e7f51e11f06e56004520444ca922eabdab623473", + "0x74b8dc3bf589a6d9051fbed9af3021e8fb775eab0f457cfd5d38b2ec8f88a24c", + "0x8c0a98cd1665f50b702b44e10dfbfaa70f08b65ede72e39306b1d31b75c07afb", + "0xa38c3526f5f6bce7e64a195cf8659160bc7318b8862ba206535626c338485c64", + "0x4ad34e3c6be8cac9be3fba22eb7e99d951baf5827df5ef921f2b01d63862e116", + "0x596670c729beb030c8756bf2ec6c884f9b4edc433a94f5dc5d4d337dbb712d76", + "0x39611d27f11938df810165987ee7edbe87cfb7e4068216cbb45848b4029f8419" ] }, "accounts": { @@ -5228,10 +5349,11 @@ "builtin": { "name": "alt_bn128_add", "activate_at": "0x4d50f8", + "eip1108_transition": "0xd751a5", "pricing": { - "linear": { - "base": 500, - "word": 0 + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 } } } @@ -5240,10 +5362,11 @@ "builtin": { "name": "alt_bn128_mul", "activate_at": "0x4d50f8", + "eip1108_transition": "0xd751a5", "pricing": { - "linear": { - "base": 40000, - "word": 0 + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 } } } @@ -5252,10 +5375,24 @@ "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x4d50f8", + "eip1108_transition": "0xd751a5", "pricing": { "alt_bn128_pairing": { "base": 100000, - "pair": 80000 + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, + "0x0000000000000000000000000000000000000009": { + "builtin": { + "name": "blake2_f", + "activate_at": "0xd751a5", + "pricing": { + "blake2_f": { + "gas_per_round": 1 } } } @@ -5265,6 +5402,9 @@ } }, "nodes": [ + "enode://f6e37b943bad3a78cb8589b1798d30d210ffd39cfcd2c8f2de4f098467fd49c667980100d919da7ca46cd50505d30989abda87f0b9339377de13d6592c22caf8@34.198.49.72:30303", + "enode://16898006ba2cd4fa8bf9a3dfe32684c178fa861df144bfc21fe800dc4838a03e342056951fa9fd533dcb0be1219e306106442ff2cf1f7e9f8faa5f2fc1a3aa45@116.203.116.241:30303", + "enode://2909846f78c37510cc0e306f185323b83bb2209e5ff4fdd279d93c60e3f365e3c6e62ad1d2133ff11f9fd6d23ad9c3dad73bb974d53a22f7d1ac5b7dea79d0b0@3.217.96.11:30303", "enode://56abaf065581a5985b8c5f4f88bd202526482761ba10be9bfdcd14846dd01f652ec33fde0f8c0fd1db19b59a4c04465681fcef50e11380ca88d25996191c52de@40.71.221.215:30303", "enode://d07827483dc47b368eaf88454fb04b41b7452cf454e194e2bd4c14f98a3278fed5d819dbecd0d010407fc7688d941ee1e58d4f9c6354d3da3be92f55c17d7ce3@52.166.117.77:30303", "enode://38e6e7fd416293ed120d567a2675fe078c0205ab0671abf16982ce969823bd1f3443d590c18b321dfae7dcbe1f6ba98ef8702f255c3c9822a188abb82c53adca@51.77.66.187:30303", diff --git a/ethcore/res/ethereum/kovan_wasm_test.json b/ethcore/res/ethereum/kovan_wasm_test.json index a4e19b5dd7..54c4a1b83f 100644 --- a/ethcore/res/ethereum/kovan_wasm_test.json +++ b/ethcore/res/ethereum/kovan_wasm_test.json @@ -60,9 +60,47 @@ "0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 5067000, "pricing": { "modexp": { "divisor": 20 } } } }, - "0x0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 5067000, "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0x0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 5067000, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0x0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 5067000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, + "0x0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": 5067000, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0x0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": 5067000, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0x0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": 5067000, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, "0x00521965e7bd230323c423d96c657db5b79d099f": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } }, "nodes": [ diff --git a/ethcore/res/ethereum/mcip3_test.json b/ethcore/res/ethereum/mcip3_test.json index 4fafcb09d7..8f1426b992 100644 --- a/ethcore/res/ethereum/mcip3_test.json +++ b/ethcore/res/ethereum/mcip3_test.json @@ -120,38 +120,43 @@ } } }, - "0000000000000000000000000000000000000006":{ - "builtin":{ - "name":"alt_bn128_add", + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", "activate_at":"0x7fffffffffffff", - "pricing":{ - "linear":{ - "base":500, - "word":0 + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 } } } }, - "0000000000000000000000000000000000000007":{ - "builtin":{ - "name":"alt_bn128_mul", + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", "activate_at":"0x7fffffffffffff", - "pricing":{ - "linear":{ - "base":40000, - "word":0 + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 } } } }, - "0000000000000000000000000000000000000008":{ - "builtin":{ - "name":"alt_bn128_pairing", + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", "activate_at":"0x7fffffffffffff", - "pricing":{ - "alt_bn128_pairing":{ - "base":100000, - "pair":80000 + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 } } } diff --git a/ethcore/res/ethereum/mix.json b/ethcore/res/ethereum/mix.json index 7cdffdda27..f788191c96 100644 --- a/ethcore/res/ethereum/mix.json +++ b/ethcore/res/ethereum/mix.json @@ -62,9 +62,47 @@ "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 3000000, "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 3000000, "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 3000000, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 3000000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": 3000000, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": 3000000, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": 3000000, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, "97c7f4f8f0bbf384578a9f5754ae73f37ff49ec2": { "balance": "55000000000000000000000000" } } } diff --git a/ethcore/res/ethereum/morden.json b/ethcore/res/ethereum/morden.json index f388baa179..a4be222c16 100644 --- a/ethcore/res/ethereum/morden.json +++ b/ethcore/res/ethereum/morden.json @@ -8,11 +8,12 @@ "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", - "homesteadTransition": 494000, - "ecip1010PauseTransition": 1915000, - "ecip1010ContinueTransition": 3415000, - "ecip1017EraRounds": 2000000, - "bombDefuseTransition": 2300000 + "homesteadTransition": "0x789b0", + "ecip1010PauseTransition": "0x1d3878", + "ecip1010ContinueTransition": "0x341bd8", + "ecip1017EraRounds": "0x1e8480", + "eip100bTransition": "0x4829ba", + "bombDefuseTransition": "0x231860" } } }, @@ -26,11 +27,17 @@ "chainID": "0x3e", "forkBlock": "0x1b34d8", "forkCanonHash": "0xf376243aeff1f256d970714c3de9fd78fa4e63cf63e32a51fe1169e375d98145", - "eip150Transition": 1783000, - "eip160Transition": 1915000, - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff", - "eip155Transition": 1915000 + "eip150Transition": "0x1b34d8", + "eip160Transition": "0x1d3878", + "eip161abcTransition": "0x4829ba", + "eip161dTransition": "0x4829ba", + "eip155Transition": "0x1d3878", + "maxCodeSize": "0x6000", + "maxCodeSizeTransition": "0x4829ba", + "eip140Transition": "0x4829ba", + "eip211Transition": "0x4829ba", + "eip214Transition": "0x4829ba", + "eip658Transition": "0x4829ba" }, "genesis": { "seal": { @@ -68,6 +75,2004 @@ "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0x0000000000000000000000000000000000000005": { + "builtin": { + "name": "modexp", + "activate_at": "0x4829ba", + "pricing": { + "modexp": { + "divisor": 20 + } + } + } + }, + "0x0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x4829ba", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0x0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x4829ba", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0x0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x4829ba", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } + }, + "hardcodedSync": { + "header": "f901faa0542ffdc248bf2c071b74d84e73ae9a2b8bd11bd6d202430d0f204cd88cb3aa76a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479497b4ec458abf3a8f88a206ca43c8d9a6934f6f11a06d11abe2a71059fa61264bbbe9a34b1f5be8fb4ada52a705637f8f110236f1dfa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000833b7d7e833ca0018347e7c480845c9d6a1480a0845d9ab9164c875ceece68e674bd2369b9f9eb7916ea1e23f439f2b3a6904939880dc60854f15ab6a3", + "totalDifficulty": "557317515715884", + "CHTs": [ + "0xc807dd41b69a19ac6c380c2a0b4823c3878ed073b43cd978e2a77a64df7f3ae2", + "0xe5f9137adaf6d6d8566cf206c012248bf24591578436d990789adebbbf57cbad", + "0x23a3c9bcf4eedd6c0c515aec8c30cf1cf769c829a30ea31d267b07b5e199a7f2", + "0x6ba3c43460794f494efd505fea3a2e519513f199ea9148c9e2d106ce42041128", + "0xa9266cf07f4bc9cc436829752e4ff0581d7a6f811d136d0a43a213eadafd6213", + "0x9f9668d12083d72e1309f0ea9643f721ad8363464ea8b82c97a10f46f455c281", + "0xe65d639f27dc2a1c3942e6685618699f1d6bc880fe027887f62028a6baf4aae9", + "0x102089b9a2c7a1d7954cb550403ec61da257fdc244d43c10d3ae0071dd9a8b8d", + "0x05b953b7920f1ab12d8da8dc4b885ea506bf6de0a1da696415c7e181c9b4b4ee", + "0x811a33e154c19dc735c6a88f59860b33f0022d453d8073ab50437368eaf95654", + "0x33123d65bf01fae8cd8ee499737deb366bf22805e3ebf0bd085bf2e8a6839676", + "0xb5f7aed6d5a438494df68b4e408fdc11beb8aeaa116241d08ec59a0675f547f7", + "0xa342b40b1d75f398d9973a5233e5073a8d0ed46c3ce56390d37abf3856716c58", + "0xf596fe04fa052d40c3f163e895a271b84d33f5433ae3756d0eb3c4e3f736afec", + "0xbf740fe291640e5efa787aaf5f6e5c1e785549f64e82fc63a5f286c71fa2416c", + "0x40800be2869e05982f1bcb20e7e69e671b9983201993c731d9719446384dc8a9", + "0xa2e55c78e611d6f8b66090b7b5d503624a3283c3ec8d2c44f0f303fa60565371", + "0x259a40837fa15a1ff862c673efe47e8cc6d3357d629a3ed541877ca53a23df4c", + "0x8720da23454e67059c90d4d17e5f593c81c7f39fd03fab1450a6f37d7422f3f8", + "0x0ce848313e625f8dc5c47cfb6a724d2c1a31d93c73a50e249fc05cb8e9ed037b", + "0xfcfe0c8034e349e97371f7212868b2accb215c5af01588951404cf72eb22baf7", + "0xe755886383ea0cc4d91adf37a307bf4e1cda6dac9beae697016799df4c555c25", + "0x163968f7d35ac07bab096aeee286446b69a4f73d5adb3f86e0159f0b1ea96697", + "0x4a470e0bbf6eb96388d6e737ae12acfca3e43189a83dba465e58ebe9149eeaaf", + "0x1888c221c04b7aa45a9861f1de385830f6a571e1582c10ce77974fad24e81212", + "0x854e426e6cbaa0ff1607fd5fbc0a66359886e2dbaea606440e1d914f460f5e99", + "0xafe3c2e3d8dd08fbcacc2e4111dcd5673a7fede0e4dceac6b0e31947cf425932", + "0xef40d19cc969283d769845f483c76cdacfb70d9d546281d2febef109fe4a844b", + "0x8729785f16e26626dea3a212059bfceb66f0d5e6a188888013817bfb246cc152", + "0xa66ec51b44a6b7f8fc6b2347e1f4ef93a7edf1cec752693e237e3c6ed853a4bc", + "0xfb2720906e0da3d302881963289954200c6dd2578800c712ef2db702fb2b1810", + "0x030ddc8f72c3070b7c7303c71138bf4fb1b638b1ff54aea16a304682bbbf5267", + "0x7892407bc680352974e4c64722e3be4d3a88dd73275d3176ab00e8b7bc427753", + "0x991e25dadfb80022c044cfcddc5bb814ccc6b7ba46efbee757236e467f8dfe57", + "0x37d1d97d1a440b6534d8e7f8997b3993e804a384b18db0fd1142fd2ddec9ff8a", + "0xccce382a99c1fa1062468b9a1f444854bddb36391536ad87a433c148bf908cee", + "0xfbc43e9f5a631c12c7fc73813be957dbdd2e91a33d8f6c928f026464e8a710ec", + "0x152c55912b4a751800117c2d628cda1ef651470d9236388c7974a6ef7653129d", + "0xacb187f272f5eeb3ee36d3f7d0f4b6f9fdc3f4cb701984ffd4023f9fcb2dc9ac", + "0x79b52e935e6838d3ab159aa7454c15431a63b09d554c6650c058c7c014ac6001", + "0xdf2a1ae101b560ba5e34118a748a28cc5241c9a51b5c8343c0e8912904b82774", + "0x2c1ace44b890710096696cf715851b77392229644ac8dd6a3497b46ec383dbbf", + "0xdd2da6958538e572ac83dfdeee1714650a5065ea1fafc0f431539ff38616491a", + "0x599c359830f0cdf99989cdca29e96263b9b760ff3c33be905f4257c2e5301bd1", + "0xf96202d560e1b2161bcaa5f315e5b1e2eca93dd3d8072b3ccabbc8135dd12e9b", + "0x7d93ec83e59fd401c711df9026bd72a87bf343d799e1282afde6aa1b1a43cefa", + "0xb5a859b110f68ea54b38e93ab8ac2f0345b7fd067b08aa51d67c154c80312ad3", + "0x7cefd82fbbbe8dacf4c55871368b8b5eec505f60883a85640242f4ac4c5deecb", + "0xedfdaf2bdd69df02c1e8dbadb65712e0504eee5e5ff3fc0f539469710dd5a5a1", + "0x8ff0e0e4855c0890d71ba87386aa3d5f6478212e19613cf05b6bd067f5a0adc4", + "0x7830f4ee53e26ca607905bb9c127d6915cd7534854270acf1decdd45bfc82c90", + "0x6eac559c95bca27833457ca73be5d93fae6f30b75bfcc53610fde590eb251805", + "0x624112cd83afb5f5078de2d1523f69beb9bd21f8646472d8c87e9b282bfb9463", + "0x0fcf00311346ece9b518b3946c71ab18b4e0068b58daacb60ae44f7b7f9c6159", + "0x580dfc57fe900b2621048d7d689ecae98a567645601449d7d7c703bfc3f93e47", + "0xa1558a82f05714aa7afc11e8d0b964d6087a4454dcc218f85a4d4c34f1adc2a2", + "0x2a95556e84c7524fd21e8e7807100f52ea278e25f43f16530d4c4a3d98434bff", + "0xc9cfbdce22901b6a2a2890883daa122501dab5d6fce92f527d699a1c6bb21e73", + "0xd1b86b1c3af0fa51d068ab86c59bfa33e564454b31afa8e4e38d71af50744b49", + "0x731468089781f91a8851f7765ed37939bf6a128e1ec1519182bad053d28e6335", + "0xbe15dc806e540e017226c5c70293005b4897efe5fa2fc250458c69158977053e", + "0x47b02ef97cfae1cebb39c9d586243583566f7a8c1a94a7e0cee03b9f69852397", + "0x630012d012d1401ccc0d0fb2e00b3cf5ecde470bffce52f93c55db24fc8aad50", + "0x462eb1e05f12c8509051c0a49a62eded4aaea9ac3e6971a1e938eb205db4e235", + "0x771bf93a1c5b137c4ac01300cbea8bd784eca03c19669eb107c2e6d52884bee4", + "0x118f4942e1a52a92e034c63fd99ff027e3669fc31967e8faaf6ea293e0b8709c", + "0x20db323c06beca205a373f294b05f299fb60861b7e86b61e20e298acba3fca65", + "0xce32378b733330dafce88de5b97c64ecefa43bdb0aa81b29b29bab6fe275650c", + "0xbbac315984167276c7116f7704589fed29fc34d63d188563ff7c8110bd6e97e1", + "0x5d40637104a9bb5524e2b3ef41d37e2634a2cf894732353a6fe04432c09bd762", + "0xb9a69a32753eb0ecd5e259e64c3953533efb8b8fe164b973a16c77a9e6146114", + "0x4aa4df7a0849f424c5975c28fa0b5b449eca26022a7d6fe65620c1d93bec9820", + "0xf099fcf9f8108254dd60531362341e641c4c150a3848373c82932bc1d51925b2", + "0xc603041029c1d86644ad750208997d2c72c061fac7fa4af0bce0701275295a0e", + "0x15d16b41757f81830c23faf58c499cd09497a474f46c5ae511aeb45aa48bdc3f", + "0x964a3f4efeab9fcf290566afa41e210276c1db10a0b1155f4615974e575c09de", + "0xe5fc4556103e0aac0047784ad3eb75c4c4c5561834b3e60692828c1f98d4253b", + "0x46927e7b6a30ccf6abc8f1ac967743dad7af1b6002cb408ec04f92d1666dd5e8", + "0xac4ef88238077f309c4d487f8b7347b768074b54bdc32b9d86dc4d884fdc3bac", + "0x41116a0be7226adf1968baaa3b5b58267eb228019cad151397ab0bf98954109d", + "0x7e7e9d375928de3025a59d90da01d7e0225a9cfd9296f219ac25218596725acf", + "0xb7a35780b22190c0c17e43e8287440e4975d380421160e75fea99cceae2330c5", + "0xe38c7f40a3a760425d6f27183c4ce827313503a126d0a6385c5e41e83b3dba2c", + "0xe431d175d47cd897c227a1657cdc89811984f95b94993bb61ec54d9c7b23f8d5", + "0x4f47b0e4c5443c11a7862ce98367cadd11b042a4991c9f1bbda88d29f3ac8569", + "0x19e6f17eb87ca400b3aa7a5f3b28d8dd0062b858fdcd9ffaaed1bcad9e378e51", + "0xd1144f5c397c11ce4bada4394881046a5be59d2160d1e6c4ad231b7582fce79c", + "0x01b05affa98baf640abf73b370a2730758f492eb2e639134523ebb4b0d4d9c27", + "0x009ee372593740561b641c5d8a84b0e65d88677c85623b4d331b87cdc9b95394", + "0xe0869946fe60ec13ad38d8d20b8e3a4cae09eeb023aeec2ccea4635a92359cdb", + "0x1f5a36ce048ca23f44ccc485ef9497e5c990c3e9db0ce4dd5a7b8ae334629504", + "0xbee0980f08ce37a634a4423cda8d50c4cd1fbacc093565c14e3a24a35632ed2e", + "0xac61b0e93d7fc80f1fd21b13d27825e44373c413eea519b57ecf203c0f028bc5", + "0x53a90ce7fa7dbedbc8e840fe2d405415539aff25fca430314736e50c6f9ee984", + "0x81064e012d19da85422f9fc09cf9bf1e716dfccc51286974d25b2f8ab6d31fd3", + "0x66fb9aebbb257df30adfdf66aa63c7e3c1daea27d4ef563d97743da88863a86e", + "0x5a7b6908f93ef5c779a4ece2232f84a4803359b40c851f53cc949b8ccca22c8c", + "0x5ca0093f965d120ede845e1c53e9eea3e0aba705fe3351245250bdabec550aca", + "0xfccb96ec021b946ab6d957df39288e58bd7d0f965f731ed9ddc634134d831aea", + "0x1ac0a3e2bde62f28e81edcb8586677ecad77108ac3186dc9ac695a1ece429e2f", + "0x2baec4e11e355f77599f6b5e51d43cd21ada652cc38147073d246a54b8c74be5", + "0x349f045d2d0647b7728c48de3ec8c137b01e5ec2180c97633fce75665847032f", + "0x5f072dbdff5e4fa6525fd7cba56fb3f614bb67b5f0d3307de35d19ff9d22ee94", + "0x1117e7dd45312ad180d28c76c40385397a27d6572c34dbbd6a4f04918e6370e1", + "0x3ed396cc8c99b9784f21688ee6d960330b72dcc4014f920bcea28417b9e2b231", + "0x4c654a1dcbc0763b6e4ea6024e81fd7393bf4b921661fee3f2ec9080d7960b0a", + "0x6750fec450fee7f6b710db501098f7da59fe76e644940700f511648ba6580594", + "0xa539a7d3f460dda620fd08fe11b15bd1d7f93d5987fd05166eea95bb133608a1", + "0x9cce533ac9adf70b3c5de99f6d4c25b7493fc62ed4e086bc0cac5e78ae6b434e", + "0x196e7a933f28e4f70229e702198ee364ac095877bc255be915e468af637b2cd8", + "0x64adc83833fd478f41ec97f20691e6e0dfe66994e9341710a7ea6deb66739268", + "0x48c8fadb1a46fdf9f10a5ca6d8c1156879007d39dd4621eef2a3af50a971cabb", + "0x19c0b693193def13b28111fcf1fb06fc1a1268b40b49124fb606e69b497952de", + "0x6ffccde7aa6d1987680db26332077859cc42713d7b479b390601e9d382ed4970", + "0x4685c98bf99101061453e23a4994157ebf86780d73c65325f1f053471f4658ba", + "0xa8c0250d3c708b22c01bd468052afe784628d8fa39c12836a872d144f03d500e", + "0x60c76dd584982a3f05b715a6c90f9c1e9ef46d2827e97940e1b67feb011bd5cc", + "0x0f5a92f5573ce6f4be3ae58ee5e9131cc45f4794480a4974ee80ea50ea2a2dae", + "0x2495bf976e3877303dc3647cdd2ae47cba05b82a6069b7721a6e6a731054315a", + "0x16a120253b7c4f074bbfc659ad65af3534aa86217e133f2678fa503485b61fe2", + "0x85181fbf375026def264b1ff000dcdfbd487be6d18aae3272f181d92c9f0337c", + "0x3c7181cf51f5e05aa1f4642e3b51811a94f1cf4a48f2ca661c15bf21937a0f91", + "0xf65a4c993a941a28ee135e56aff76a9c1a65cd90b2e3bea8c52b97e322b2c6a3", + "0x2650635481a5ec0b92d46fccbc2b959759eb1506642244570d34d279720cf950", + "0xcf0415f4a01e2dc759b8c4df61c20d9b61e001326b9964cc08a24d1bcaba79a9", + "0x497626c7a99d2383832c282bb9276f9458989bb51dd2cb8beab19069f145325a", + "0x258105ceab92adcf7e1071085f4881963cc0cf98c28b5da174813e80b564acac", + "0xfc8e8f4d831f9176b13e214af17977495105128e55bd58886cb6b699ab0b82e8", + "0xf1fe70de2aa4bf8832839027edc5273b4e1c9b68557bc64b9dd41639b76f6da9", + "0x67b2609150cab4fdc60735dfd251f58e0ab4c37f4c5e06b742088b0299bbaef1", + "0x991be3047b87a9c7df5d14c8b994e225c18967ffd8f165fa0f11701ec9893bb5", + "0xa55540cd2b397abcd88733896795d3f36bbfdd1024d18ea7d08f5c29713de23b", + "0xc72955a6debdbb088a6588a5613bd2e329612e366ffbefb246244563c78e3a13", + "0xf2e8bf5f11b5d144fcb2e9c26dd1c4b7acbfaf7ea9221a4db35361275bc02d78", + "0xb61d47b97a001e07a63212bb473fa8486d1da002ee774d30fa03a704f575984b", + "0x373146b0da2d2269aefc099d0e1ad48acb1dfa018af540433abe1785fb84ad7a", + "0x55b5675e4a7418ef176fc57e339bbd438a73e9d07496ee3044aeb9c55001b176", + "0x758af96b4ba6fb256a7f30378dc0d46ca067e3e7cdab7ea3e974551d5b9aa2df", + "0xb37b1858153b6d2d2f914625067dee98501b768641e30f12e4596fb0a6603093", + "0xedffe2510bc146b7d1fbbb226b9fd3370f6b711b1cffc1f6951485be80ec2246", + "0x19985ecc6a8750b3326248776c85a4270e6d125718eab5d8d988a2b7c75606cc", + "0x48b5d00c0063db48b907c2a03ee9f33015c7c07ccc845caa7a158899b358b85d", + "0x99d95d31ec4d06281f0b08173851fe4ab50b5c787f2e6f9ce20466cb7121b31b", + "0xcc104b8bab53ee3753bace59a4ef59775e3665af65c728b301ca3fa5befcc1b5", + "0xa852c92b55f55c16a99f0d110d4ea7451a172a3be46745ab7d8fbc5eee9b9283", + "0x9b2b3660afa61c4e56a25b8cfca058102c2f2b16e97f9e26e80fe61d5af7fb8e", + "0xee87d114b2af91345deea4ee759c989e854b5456fc5b1c11ff4cfea40192f0de", + "0xdf865eb8ff849b25b12ad4aa19964baefdce7945ec032da2e3c1705a53f020d0", + "0xc367c8e3f196b16d93ac86459deda6ee469846072f2ea72e53c84f152d576ccc", + "0x60ce704c4addb76ddce1e3d81476e98e11bf2d2ef46087eda113d7e6edbd8f55", + "0x18c87d7573c19dc3f66dc3c9756c40573e66e59d15afa69b007fc51bdf0d357e", + "0x0b5b583d706437fb2cc549c39c802852cec9c50acaaff8c9151a20a6ca8d2ef0", + "0x0014b94a1acf7461b89b0506f30c26ebda6d319e5a6ee63751d320b3f4affcf5", + "0xb6ac380ff03a0a66a152437ed43434fa786d6d3c22335852f806f3943c3fe132", + "0xea8da8fed31e69e2698dc928b67b5353d35525f25dce1f6ae45865b9ce90169b", + "0xfe9e5bbdd55aff1c660ac89c54fcc0547abbd671b210ccf4af31b70404820884", + "0x7347c74c6be6312e284904e5b60115d5ff48a032777e91423d5356aa9d415a9c", + "0xadc1b5c371a79c723166c3ddae708b9eb788bfa6d04794bfab5553b43153c38a", + "0x32f150c20cc07e1ef70f305a3270f351bae9dc13b6e0d67c661de5412cf0db0e", + "0xd914de07ff853dbdaee5231be517ab681ed340e552458d640815c0e44da377aa", + "0x5a01f086ca42b793754187d98dfb333996a649852e51b48ba0eab1716fa6f224", + "0xe5ad5f6ddac1eb411bfb05d2ccd41d3d1743ad1c9cbb96738a9979399ee1dbd2", + "0x574517aadfc912986e188b0ff0818312fe9f016007f4a30759a92fdfa069a6ab", + "0xc46db2db2552e53f2fa6a169ce803bb18172cf20d5a36b872a5c4d9963c7d42b", + "0x8ad27ac3db4da1eac8d6415b5aebe303cfcd681950269f0d1ce57215788cfe23", + "0x2aa7a60b25904d1e968f0dbeab510c06355b052b80872ab07cc58d809b58ad15", + "0x3031132b43c9ff4b2c96dcf7c04b31d18b6e8bc2e0cba24e8fd786b02aa00fc5", + "0xe1fde8dc15e887c6423dc4b6ce04d6e18a65831b073836a921dfc04ee016b299", + "0x5dbad0a396f6cd16ada2369dc2d08ab6af60b7da48fb0f6c320a566927745f3b", + "0x4d5d4913791fb3d819ad4c45e9f0ecbe062d0198e25bc6b20bc695e931d35d86", + "0x8825cb707e721a61c4bfe7f80a83b2a734d8406146b11ffed638259da5f91dce", + "0x6c686743164839f169f94ae4c7f80298df5b9eefa955cd6615def97b5fe2375d", + "0x5afee77d12298cd027840f0c1a26ed057f6af4192c19eefc6df965cf502788c6", + "0xda9312700594f18fd5dfbc2782fb440d3b79073b31b58f85275aa907b25e0b98", + "0x94eb93407bea97e074f639256839e2b1e955fc36b1fad232b19b278dc89006c5", + "0x81f48cf3fd6183fdf5e109c5818392c8b23ec98cf22a8b330cec22802950bafb", + "0x7ba2755d9dd57bfa22feb05fb10ebd1a887d016d660083eeab1c447f5d2aaea4", + "0x770be40b4c51529a27ed6e34e4d7caa52e1cc4e645eef2a5597b566972eef290", + "0x4dd8f1711f834aa709485ea0be3f948cf4a32ac4157cd217262266ee282083eb", + "0x76d2d40a7ddf60cbcd63154570fef14ef41f60b6400347cd9e66f2be51fadcaf", + "0x2bb51be5bd7fe41a05fa9a719aeb4b26f0e624b5ca5e874723c88f8af34a8448", + "0xa62d0bdefa2428c6347e1575029824b1e6c985a5a8496d2b862850bfb038b55c", + "0x4afd8ffc47fa73d5f34752278974358d1979c62dd4d0ccffc65aa16a3a748764", + "0xdc2cd7b80144147d26f66e44a03b3fd81f88d8c92c967b056b12ed54a09c1bc4", + "0x2e08104188c24e988c719984149d16dc4aa90bac4339cb4c3390f6a7040bd122", + "0x5957803ea74ae2f332137a7283c87c9412e66ea0ac9f6d3512ece8761933d4ed", + "0x66ea33306be78fc4cac257e19ba5856ea60e171f359d2611916bb6c1a1e8f01d", + "0x6f1b23cb0739caac8cf2e9bb61a2c1d390f6032b8fd2cfd229def9319856703f", + "0xfac23cca5ffe9719b9e60549a88da5a2accbaf1a8848184882b2ce94f66ffde1", + "0xe8f6f317143515b3fee7802be18866e8b33e8939f0c4899ac69c84dd484168cc", + "0x450bda8ac1c25a5e864e7a4dd3c0bf7ef9b4672b7bd886b4449dd6a9c2520d5d", + "0xe54ee7a1a9f089c66895c681a6876187dc3995e2299e17112a6d60295e1c8812", + "0x23d7c3d49ebb33312168eefb03ffe680a6eb969b719c573bcbca5ace4fadd182", + "0x961abd32c2fb7fde7054ee5232cbd485de5f83c427b36802f27b2efad7817d7b", + "0x98d83a56dfbf64cfffbdf1d631d0df7a4d2036a629d36794f9bbfeb106d94b09", + "0x7e06ea4d5059d55dfe9df764004261f907d08ce4043e6af73f09561974d57169", + "0xdb208e24e9f6193ca94486801ab570f7cbf8844803609ba03f7c4524aa92a38c", + "0x663f20eacbe6847073b04e7b2d98e820bd85cf29370d71c8c3573d0764360861", + "0x7bb39b75c462f7812f1a458dd06db76362bfd10d27425eec78a88228a48f1805", + "0xcf07ca736e96ab42264abc426229019165a3ee4ce8eeb2558ff8a086aec30918", + "0xafdc6af1dc2f93556a4aad36d0695dc2e1ec84d5dfe928c66d55df7270d5be4b", + "0x4f9172ef6b6fb4fc08c8b4878bda85bc58ed557b18aa3a3aaae449c773c1bf04", + "0x81ffe0561836f05fabf77b79e2aed4941d90d0910451c3863caa5ff3451b941a", + "0x112490bb941dcdc267ef27e3dcac89fe2690947575df1e53657577af72e6fead", + "0xde4a0bc4ded2a7d6a181ecdd9cf064858293bc313a84c2b33f51d42d7fa9d96c", + "0x25364f970061fce0d3b481cb97fd386a6c6e7b978e40015cc8357cb4b3e6f89c", + "0x524eca86148baee8391217d99caa2a644e5aaee2591fb90962ce2a34e7bbab36", + "0x56e971166db8d020b247c33a5ad59f713e1241808a2441c47ebd6bf5189f01a7", + "0x13e761f3f512358b4963547418ccec496b1205347cd3ebe2a510ab18f7cf2115", + "0x45bc998da3b99baebae0fcf5703f1ef5884fa0d049bafd51d1a491a762c80193", + "0x6727277814838b616dc4e78831cfefa4b9ff0026d2e7f52a33a8e7c99b5e0846", + "0x216e20d230f00e5b2c788f6073bb68c4a0afe5291d833350dc555259a8f37e0f", + "0xdf1cc61ea687ed6bf1bd576899003f08a13cc7b5e5ccfe08649887f866888973", + "0x9301d182de849055c299983a7c99a59166460e37637fc227ee038380dca42680", + "0xdb0fd7bc019418c8426879d453f6e72c38305091cb7306a8f503c6461b72aeeb", + "0x4a8183ad7c2a0301b5ea7c6554476e9d7747dd8931330b8b7841394b8178018e", + "0xe1014a500104e29335b7d5a423cf2504b6d2e4fb313021ef8d4051d07f612cff", + "0x823de414bae4688460c5697d22d3b95a882b74c29a14f0565c54ec61e1449b69", + "0x80f8e29216dffab2e4350de36925b60895cdb6968e497db432e12026d6cd56e9", + "0x900673ec8035f93ad51b3ae2e3ebb26d09c50a6a7f5436fc95e5ebfa6ad16d37", + "0x7073bb4f9dfa46161d314a87a6d77c661ff1bbb507fbf4030a461625fba06d32", + "0x397feec1f80c15e2364c776d69d78fcbca750bd19fb4c30cfcdc1b361caa659c", + "0xa881765daf0b5dbf10c34832cdbad13f5cacb9812514241b443d26dfba8bc448", + "0x9e0b130bed0a59e804c4c380665757ffcd0ee6e300a1b17639afd55f6cde9e16", + "0xa3e0f7e5e174fff98c24d3f31ecff842443178ca09234029bd5d0549694bb4f1", + "0x887201dd3dda8405c4a29fc49a3ba22a3ee26f227b4a8079e7c839dcb014cadb", + "0x20604a57bf1bcaa1ba7885135efde3fb4e8b118c85c6448a2f9fbddab44bdfae", + "0x4f9a6712963d57774c919b82b8ba48026dc61c01b94b77668829b5ccde82f2ec", + "0xd9e91f925e3eb83f8361c37e03aa0aa60641e5a5f9b01f92fcfab199b6493ddb", + "0x339bfe6603d8e2f0bf2c8fa925ed97a41f589653268aab0f494b79fb5092562d", + "0x2e927b1510753f5a83d707cf89d3b62e1e5ef7433d4e0b194863ff27125861e7", + "0xb177f311494d3d52e4161f072d24ede73d0c18256ac43a8ee5db30c525245fad", + "0xf873b085f8a42bdf1508b478aea9106cdb4f27f347ec997c4cdd5664c35e0e78", + "0xd80fd167784537b68ff33e2e6423b6b9647d82af112a5299c21da4d5b8e6d20d", + "0x34ca5d08b8d391778cac1d821fa1d6e94989ada35c2c52b691eeb0e8183d8552", + "0xbf80f2a0081854b4d2d0b91dcdd199741b92167dc0f5581cba76a7fe52b96150", + "0xdabf29b0fff0d327a111e17eec9160b178f6898650e45829c0c3afba6dcdbf02", + "0x025dfabea1e942dbafd9b0ad5f0b6982fb52315acfcf1270141f924575124609", + "0xff960681061cb1590f38af8a44b6597394687f780d3ce0afc9cf4203926cca6c", + "0x72ef02bcdbd5c43463104f0b2f22750556b0c73e862c89d1750baceae6e47d5f", + "0x1e4cad2aed7ee0951c21015d12919a51142ce902ec15b08f457ca5f962099b10", + "0x8aa5bb7bd5cf82a5696f523e16aeb4f9b48aa22d252b8338b403bd0b19b3de37", + "0x5762ad980b237f1a70fab5f6ce570f68eb1ba25caa87ef66e0f653b02e6bf808", + "0xb4121faa65ed4fc53f6f377e4da1a3c0f65848f0fc3363a6d66da7bcad514a30", + "0x67959aedb680f267d61dd647b88a6e177d5d84213f94ab4a071870a51df2d476", + "0x715647d7da67f6114f16ff0f6c9277a186cb4adcdbbe9e990a901118a84254ce", + "0x0cbdf473c4f3646c32f8c0002d7f993f7876f8c9086222d5a82c678eef60ce9c", + "0x551adbb1ce65205710014bf69a5a6bf5a98cc67f98e6df1efd22bcc1fa6d5d08", + "0x3bb1e51f43a2d13049d15492b8b78cea716f3d3f884d35ec65c72d24a6112c9d", + "0xbc91486359e3e62f22c39791afe7b2b4e09843d8a3ca301897684cb8d05988b8", + "0xb575d4642418c78e9f29f121e82886b23d7a061edd7bc6d762155a1bf34f552b", + "0x3c4b2299588786594bce7d50e060d26725182e92f8de40a86dc18a4434ac292b", + "0xafa9cd14e23ec071c5a22e2d0ff21656c8cabb710578d31acb6cc8e1e3315ded", + "0x9f6a198a59246aa15d3b0573cc080d0ed31f5f41e1c4efe16ada8656fcc94c46", + "0x4667eb3aea65369ebdbfea2683e172295d6b28436e4a5c7fbefebd8e15a01fe3", + "0x89ec767b3b1e41da68ad53f11c5755e61a18a0d07fdf6d7d53cca6849087f135", + "0x2046d27b46d093c35eef24698d1fffc5e7532007a2279f646c7bde034402af71", + "0x8629705c85e0d6060906ced37a5be8fb7b5ac351eca5a1934f9a084a47fe7420", + "0x42f465868c164eebdc6efd395ef39936aaa9e65e753850e6d2c2cde9837e1647", + "0x766d160e4d26eba8675552a90dff4f63ab598e1955bbe0ba1a5963f2a524b090", + "0xd05c5c90fa9bc35c43f2a6ab9f5cffa6f9bc2557f9019cc2e9c8aae269041fa5", + "0xc1a11fd05c80a1c9512ce10c89ede225405ac58321f63a9d1335261454dc0036", + "0x05092398d5beed07cf2744b91561083dab7040b09d3b3bf64d2b68ea0d4a817b", + "0x7fa4113fc5be42a29c84e7665fd3d18c06ecd482d645a7556e2f5bfce25754a4", + "0x06e59dcfd141ed7be88b602f2ebe9efa4091c80de4353500b21d597e26f22caa", + "0x03da4109fcc40e21edc20001b619da6184d64eddb1b3fc91d2a2ab6ecf74bab3", + "0x64ca02e31ca8df66861511a9a20f4297bda741972ffc636f6187fdf7f09fcf17", + "0x7c561edead7f97f117f9d7b556fb5dea0c4d8ec5bc79897328c4acfe069b73a3", + "0x64b7d9a23879a3fd86d561ccc911791c2f0d5616ef0c0cffd33ccde84c5b7da6", + "0x083fec3acb799318048eed14ed35a85cf45010c70e482fd99749ae25c1d0b782", + "0xe9529f45f938dd2576195d7d2798cca2eb5df1f31e0f72a4645393b641e77a1b", + "0x47f289d3467b967a0f8034098efb542172420e00cc29e1552cba377597916969", + "0xf4416df2dd30effcbeb3b80bd035a4236a0a5cb85eeebd861ff1d58d699eda50", + "0xa3fec237960e77871219fc08473c948ce4c0f9ac61ad80ea2bed7996f9507d69", + "0x6f3d597bbdc64c01d432bea19b720e72a705f843a5f1eb8330d7115b55e60f71", + "0xf67e1f41826290d68f6b0e900be97212ab334280112dd5e9f848db18ac3b9271", + "0xf0230633f08dca03a3647c4f6ed4f093df94d7fbe59b51609460a6b466837bf1", + "0x0484bc99cd286afe2d3e33f30f0e6887bdd3c314a5e81e844f21940ecfb1ff9b", + "0x8ce05e8d880ab3498a7de438eae5f6080b048b3e9b9f5a23c111c1db7ed9ed83", + "0x5a0109a7920d888d4cbb0431eb0b34ed1fa1e2681ede169ebc845252c4aebe14", + "0x7f28a7a93453c7aad30ef6b3b85f38ed40bfd4f7469a0a2f66055c60a3276281", + "0xf48b88a653ec5bc25bd78a14d038a517545f83b274a8b3cbf81102647e5482ba", + "0x55f6cdc8ac367916e81eaeb3e7255eba26a9c5495b6b1442ba30f1856f4ba85a", + "0x97120be21f046e4ebd57ceefd9f5e4583c33103017fadda5c05bc6e6f847eb14", + "0x8ce01af1b8f413b97c1aca65b18602bc48a84135b84c425ffade62535f6d177c", + "0x2ba45b460e684678f4e7605c4c912f2480ee9c2b17b7f75f018423951c2ce03f", + "0x932155dd74599a7896ee933838b632593175e350f8db1ee001c8c8b55d156630", + "0x9592f1f50289aa899f796c73c62583e758617ba66ce3ad2f5a1e3e4009ea0e44", + "0x68f2510fa98cb203caef5b5434d8ec4b5a63f7af17aee2eb83cedac637e162df", + "0x28dcca4c376df916bbed16d0e1d73c0568af5b08b4db3a86f108333638d61f76", + "0x980002c98d465e0011c438939c6a97b8b8182733da14ae198ea077a257f01eb2", + "0x7f280b8d3da47619e505063394c7e84beef045eca57c22a9ac71d2c0e4f9ff1a", + "0x6798250b993f3b9b83d30139a2d497f93fd825c1dc94fd57c10ef5c8818852c5", + "0xf5b978c4ff28deaf652b1ea3d7b7367cadc440baf440735a62b25adad4cb776e", + "0x74d37be2d2addd3839d9541111d72c98f09900305e891d94ea74879ac975851c", + "0xc77c2caf24dddd1204a856631c8dd2358e2c35bbd5732b53c1469fe91f975b82", + "0xcd6ab2ed9cb320e22fc345c58e23121efb68654810cee0dcadb265e06c3ff7bf", + "0x204b4e66ce38c8396f924799548aafc99d268694262207bb5fd5d45ebafdba17", + "0x3c67f0ee0d1125ee7ef93f0ac38bb14c490b4d85be9bedced7e4761cef9eb40d", + "0xdeef5f3116639ab746da2d6481b1d6ce75a80fcf9d495bcc863e4fadbb4d9de6", + "0x30570d79646a5cc3a81c10976b310892030d339b679b56f453d78bee39a70b7a", + "0x4c5faab35c94e41bc9e1d19984d184e396483d98ca546fd700abb5b332df9412", + "0x1f3e674220a9274313dd76dfe3a84777e04051a9dfb8d87799da979739561d18", + "0xf74999202a6e5120d01c97e857bd8aff0f36f1946b57f6b63e9766fda3b87724", + "0xae65d50f5ff120b96489289d97952d46a3697a00424b309bc3840dee2c9aecf6", + "0xfbda361f2512dc8e64dc15a3253c5242a2ff8cea29e435da91bcd3b2c6d979c8", + "0x7e9bd0797f03dc6d6e0c5d0493968883488efb507844ce749de8101de40c0b21", + "0xc60a8ba7bda89df7e936559df5067e6d1c7924962e6abfab40c708b0174d2264", + "0x8d5700d40e1f396af84d673852afe843090f573fe874b602cf5815fd011ee501", + "0xa05a1aa13f640a250df26e37d48ee70e5216f9224fbb541e6d4b2f4858c76f71", + "0x2ad9058a64d93621095801ce8272d2208e90e71a1a0b38dc24f71123fda8d8f6", + "0x40c96a4cc194d009b6609b154fbe63a833cc702dc2fff5b837e5eb6c88c7e005", + "0xa2c233b6964e1625a43ab70f1837543e5b3868dbc0fdb4732ecf8a4155d29d79", + "0xcd627d5278f9400834eb48b54f331a74734846497d86acc348e02a41d513b201", + "0xb34b79d45abf13ca51f88f7d7f144a260a44308390573eb2b8dd292b70b02e77", + "0xb8986ff28901817523ad8d796dadf9e5284257fb34709a98d5a3e5738dfe4379", + "0xb096d14fff72a2c833b112281f5f52ac5dbb4d48f2245570a81b85b140f40948", + "0x3818f5b06bc70eef065d7d481f80c97c6806c4207e600c63c663c1da210d8be9", + "0x7e3090a67933b2f83e6152fb75178f79e26f82ad07c4358ae463414a0b02780e", + "0x21aa5f90daa5ad68746f55e7f2510459ef32760867fece3f0224d65b3258afac", + "0x377b4d870eaf1d610e9eda269e4eb85382f527ac683e5ab53d04b3b0caef05fa", + "0xe6b2742b454708e3db3dbff642643e5159931a211a999ce57cc633e6c4d8da93", + "0x39ef67462038d2e25a9146727ead5ba921e9080e2c999a67ebce9d724893fae1", + "0xfc86a21f2f521f6d20e57bd3af58f42cab41add721580831a3b3bbf3680c0ccc", + "0xa2f54cdf34b1c869f5b248b3ef849859971a23eccbfb94ae8acf4370cec11924", + "0x8900fc71a6af6e496b5ac6ddd94fcf9a0656a342362019e971c44038e867d3e4", + "0xd1c988a3136c1521f70a547eb40c9ef40eac2750b940a951afed3dff7789590f", + "0x39e49739745830f5d91649e8032d30e22e45265ff92676f7d50c9a2335e21d84", + "0xcc964177439b593bcdfee8bab03bbedb9036de7b856e6b7d43c95e055f2a8f45", + "0x76e4575fdeee92408341b576d00ba3de2bdb964de3630ba0d494d79093d74536", + "0x3915002188b2d3e81ecebf0e1406148f0b20aba94e78a5b68969cf62b10ee7f9", + "0xf18f968a8f3f6f926b88be7b62230c9ecf6d44420971331886b7cc3c6bc9074b", + "0xe605ec94dd9a2e7e2c214a49f8eac960b12862a6aa435ddb8b4c74288b343c95", + "0xe6500a2b86b56f1acdd1012440835cba227ac7841550f30415f83b0cad5e6b16", + "0x0c20a4fbf0c1c766560016cb42ddb2f30aa6f841d8962e98dc98b723c8729be4", + "0xdef58db01c902fb676f8c515b708dc4762c3151fb9d80724eb1f3a02573071d0", + "0x44f0d489aa086c5b6cf6d3198cee057f60dfd6baac0529fa9b9b49e15d6209e2", + "0x91d2cf4797ca2c817d38db0ade3de064f66760d4f0604f90e209f5cf1b541977", + "0x873666cca9e593788f770f7cfa928755dc706647466b4cebd0362079a13b41e5", + "0x992ed0a28457f993bf57ada40110f6ee947fa127348ff6d211bba26a0fb3696c", + "0xfbcb1fd57adc08ee435b077e17be9b087df6d0e71bf39060a0f620955c1dd07f", + "0x544771081accc2219221cf353e97ccada6aef8aa94048981a7d060a37899a932", + "0x768ad3e04bec129183a33fc136476e1130d9b167177c6de4849613ec220083f0", + "0x44b0a9afa8de7b437c6c199f0fcbf0aaf377c1b847c9e8c64be7f14cb3792b56", + "0x10b9c4a0da33edf3db0b0aa33f2ed1d1bdc08ef6d7bfb8e910fe0a74ce809efe", + "0x6831f98b09864abbeb1177d50bdddf12acccc7abbbe1af173982814ac04275db", + "0x3e0466a93aefe563285ea1b7b6fff1c64b274161cdb5a37542e888a0219677e7", + "0x01315c879852a7492c6eaba9819f843f60456a8e2fde0a9ee2cc5192b3a00b66", + "0x0ac3011320ca4cde5af849ef12dc87f318315681ecc0f303c62f29fc556a2490", + "0x91fc1434251b487ff854c41c65dfc5ab63d309c0d88dea41af268e0d7cbf5df3", + "0x59d8dc5031c170ae9042d44f1d7a0b95669a15edbfadeebeed0f290c2afaceee", + "0xf636e4550a81c8f1b7e318f15c85cb57149fb4bfe3b879fd45f809fd57ee7db7", + "0x68f9a9de0600d560c7693bc0728741751bbae831bf358ffc195d7c304d9b280f", + "0x6c1358206b4fffb9716a634a5804bb4fb9331bd2c356d0064054a9263804a400", + "0xe9bbe71942123394e1615bc1935f0ea7a7079c708234581a708c38d304a1f783", + "0x41511870cd7271c3e3b1bfcb3fa043a4db8ed6510543e35dd8d4ab588017f4a4", + "0xe90ae56748f84a0885a7362993155b47b4d0c5532d7862c6fa422e28f09b32a1", + "0x37e43842eea4ac64b65d94b5fa1ad7a2d6d16f5941c43586913f574d5998ed7a", + "0x1117f28caf34809d49a0b1ef2f890680116b44c76c9aa27efa0357885dc1f2dc", + "0x699f428493f3cc759565072dc237c01636e283b808f95842e2be46e45a58f3dd", + "0xc91f3d366051b95a6a5b3290b501e7e435ea967cf39df1ac94e8769a87744f34", + "0xe28d8d82d81fb59b445e16df7493a74d1540b43ce61692605bf0d5287af9418f", + "0x667313aa96fd2950367a671e5ac01e685fcca1fb45f325510d38fb2c622ab67f", + "0x48860cdb6aaaa321d2accbb8f1e9769e70dd6d4c29c8baf490f4f0e23c40dd05", + "0x3dd9f9705c4d72c2d69c90cf2fd68c0aa5d0cedefd7dc012e9b7f2231f3a0786", + "0xc7aa31f7bccc6ce532d673132cd980d51b00cbb2768c9846bb60dd6ecfb584b6", + "0x403229d6b2a73c367262bb93d02de563ead582921fc763b8fdf495fada77bd55", + "0xffcd7f454695bd9f3b89a460b1c98de5ba3a989888e2331c885896e49c19f64e", + "0x5f9091b21020642ba4c1027902906f7e6246c42392ef333f00990d62ed8cd008", + "0x2d7c6d6bcb42dcbb9a7868cf3c3df439ec18f28ea232a7aee34feed6cba38027", + "0xed6ad62ff36c517deab2f8a266eeccfb74548baa3b61ce4e6b6577628a9a0732", + "0x4f301038bb42b93f85eef264ffc59e8695265cddb4084c38ad08d9260ed99681", + "0xbd54f734c93e0c71128409dde4a423543b080b3e16c49bf61fd967b56b22d53f", + "0xa32f3f4e4763b4567b2613bf15c6999789213849588e756bc6165bbc9e58d072", + "0xa9398a4b294a26fc9cdbbcac4c32dc3a57a88a5f269b41bd49a0e696728f57a9", + "0x757e6d5b5b128b028599ca3ce3cf637aca013140864a382704fbd73f91ef1059", + "0x9d35eeb49fbb88ab329141001d211dc074223f992f7faa25453b31ad1686fe23", + "0x32fc286389aafda1f3911062dbb61841ba8b8943d221d553a97276aec4b18221", + "0x45f5f7330f02814ec0a491feef7accf09dfe0d4acf6295799894f793efc5082a", + "0x1063c89a6cf98b0ff44456df9925bc3877e96c3fd1811940d94fc0ee554d108a", + "0x2dd74888cffb6d854fa2acfc2f9780ba82a3fd849b3031d0a48bda091ae787d7", + "0xfc589908c8b621b7aa96b4c5675ebdf61ba09a2758dcfa8a8ed741edc1c0b946", + "0xdf8bf0a37b01ee0e2ff7b9e6a1186ba41b6a3cc1f2dbc776664b86df5159e8bc", + "0xd880db83f1091fb064ebc0143110e0de9b2471be1bf09d033e73f586203c789c", + "0x5dac7c9f4a5925292ed8fe41fec20063bf7a08046fcf31c7fc782119ffe422cf", + "0xbf3bf656c9170df01e9ffc1192ffbd0976a68c325767a6006245e7b885523a72", + "0xf56e3fc84c71743bb8955503ab1b5ff18b673b90982127524d98ad734323840d", + "0x393141d2b434845ca225588e2d94e5b082b425b9e627ab4417f11dedc1a3e3f1", + "0x4685ebaf81be0f1d89eff701f49d8436fe2f451e557d5635d199aeebbdb0e2ff", + "0xe1cfe4c9836cba7d13abc522cac6ae5513c396d8b46c7f61f8aa17da54205060", + "0x39b272decd976241df1fe242a2cb2a98f73d9a40ee3fd445b6830752174c4718", + "0xb656eb1cd8bd2c42b6ebe6231bd6d78556ad2424603eaba3f4740e7497483078", + "0x14ffcbc3d98ccae3ba2414c17f12a9a70365856729a6317a9c80e46575f89563", + "0x36ac3e640f31e48b5fffabdba7fd751fd803a1707b6ba7c587a7508b3b1b4231", + "0x1fa3f177431e20f569a2c10c79dce754eb8b7791baf5f2aa1a389c64c9f4c547", + "0xf7e53b29648da476b4df26086445adea1cbba0ebf2271461417bcf64bde0713b", + "0xd8a0a1781144535cba0e4b7e9ef72d439af344d6d13e9f31d35791e82aea57fd", + "0x730110ffac5fdcad1c3b82c00ba16e43eef88f3f4fd90eb5403922fe5bedff42", + "0x24cc38d4eb2b82fbfeaf2bf91bf7fa470a5ef49e344e75973418915fe218b42b", + "0x18f05c3a8f656c831d4e4f61100bb6619216770eb66775cb9ff9141849f9cb0a", + "0x0eabb089aa92365dd492fb0f81fdb2ff6f4575976154b1ead5d8b06ba5b4fafe", + "0xfa557813e8cba6fadbd410aaaa5d7e01a94c2eae756c7d064b8c19a26d5f8964", + "0xb424772a132e6a59b63715ea1e2689fcbc00b1d98368f530af840bef4ef72b7f", + "0xdc5738d415e77cd5a0ef5dd3d4a52f911b1e9dd4e386924e28b9b0b6dd7e6884", + "0xbb8596337aff09d46c4a5d6ee9bdfe369e41b2384a57f45b5a5151d4bf2be89e", + "0x882a79f76f1e876bfa8802c7e2305537f72aa1a7ca4ab34e09bdf28dac815776", + "0x6d3cc146b6db4257fd768280a58146bab3d6bbb6651c5bdfc12645d132afd904", + "0xecf827c44a85e1250ba58b311f1160007b29675570223ed5c642ce7f9b9a5cbb", + "0x64c58db8a9534ce75f56bba7f2fe704a4333d56641fc2eac3cb39217b3c10e76", + "0x2d3b0e05f4d190813b4dbec787f4a9bfb3b029c44bffdb193a1abb9577c8a9f8", + "0x514ecd87c88b6ee3b984d389b66ed5c96ee48f334fa5ddcd03c145f4e4d3dcce", + "0xe856f1c77b345793bbf9ebd77b812ce2f393d2993e8b735f1b1482a2b2425d13", + "0x05fcc98827976ee1d39a0d31e34e7d9239dbdf287159a07d0353c077e19e4350", + "0x7166e2b9120fae430512ba36205080875b12a5c0bd92ec1de24fff377d380cf5", + "0x67cd75d24ce797449761038f174c7b1aebad5e83a0e39179a011e0ba389f67c1", + "0x16769224b8cb92072bab6506514c78142f7bc02f8f87b00b65845d21b6bc5b19", + "0x0f915099c11b5d1a9fe07ad11f684a84c60bb78a4b1324d287a3440d1b043beb", + "0x07eb4a64b36b479ab579cd25a68da5091e63cc19b03b49e55da80f5cfd85df10", + "0xd7c98fd3e2f8290d670c96ff39df33df4a803f9f5f43e01d2f09a2bc13cab132", + "0x339a8c9604ea03a4ba70ba357c49af83bf845731d3f9c2ac52f8cf5fdad401bf", + "0x9dcfa65fe12ef7232d3d1c052ff4e5afaf115b7d4fa3eb09d07c684fb2cfabd7", + "0xe27eaab5c986d687f3f943d0b6b983e620494cba1e7e2148e7934bb5c4dd0869", + "0x5f6ed69c6633e088e922cfa705aed670a32f100afeab35130b38c323037697e5", + "0x2e3314c00a75e9f17471b393619b3d08ce276bf5de32a6231f7aa270030748ac", + "0xbc86dd6a1f7e07fc84340ecc774e3489571dc61e6c4423e64f148eca272ddf61", + "0x3761f5b746aa79e23ab83692589717ff225b03b02e668f5d51cd715570777f85", + "0xede23d7929b19affed9906d02bc39d519b228a19802b16a4ae9151426688ca05", + "0x6219acadecec83334f3c3ffec13c8a1715430f06f0e7a0039f5271aa334cfb49", + "0x28e09034b7e939e9f0cc236e66b2fac2070ce28837a8267e375cc76761fcfee8", + "0x0c4a9991804e019de882955447687a27117f8480eac60667989f641b6824f836", + "0x67160c6ecbe0913a51ddd163af202d3dfb9d4e826f2e7abcaebe57f9cef2d808", + "0xc9b590712145ac72c81a6e24ea96f1c5398fa8650955d25c9c102bb7ccd0ae1d", + "0x461c328503f928a03640021ea12980077317209ed4fc3d0c21b550316e8992d8", + "0x694f2afb90b35c87cfab511f9518160861a9ce1388f6b2d8900dcc887a943003", + "0x2399aa9e302c40a25d8154b8a7a884455a0a81f08b3b8228ffe6cf56919c2a3d", + "0x2faf9b05da0dcd0e712c95d7c8cde660b6a8dbf145106220a0a2f38919f2fd93", + "0x36fd9ff349ae7bff8945b90d5b4b3576a6b87624feea2153867b1bba89e0c1fc", + "0x024e47593d7509fc49e8c4d0717de52f7b63c702ee191c5ebc15a772a0325711", + "0x78954a4bcb0317e4147a8efff4abd7192bb941cd7278e397e1ed3c282fc54d9e", + "0x2735e04d281edbb1f0907e7565a36255028f8c4b084f0524ba9ff0cd5192a481", + "0x953b4e2340d04b1dd78771a65cd051b983ed8d8e870af85196135b2e10bee666", + "0x281655ac912af297ac13e4193163563c6c4181ebd3132a309aa8e9bc02758ad1", + "0xeeba9581563ada6481807a06b91beea20e05f191def9a31607e49296c6f994f6", + "0x2d4b2fd56623c139066a9d2ae72b728d5ce732eac2af2bfb834c03ce3b1cc752", + "0x0a6d56ba67da39811db01841dbdedf9d34e07bb954792151208670fc12c4c1a8", + "0xa4536f1f2ea3e046503373e88d9f8bcfb06f9f15a245ec73e6daddf1a9a2a025", + "0x28061410720a6908463d604e3375aee44f65a5882fd3f9bb05dda4291824f7a7", + "0x74c50d4fbedb21f96c21a9b1fcacdcdc4300155198a88f66333d843e8fd97cfb", + "0xef12f70d5f61d0cf33ae969ef303690b317a5622efb9ae2206f574ae53b4510a", + "0x00992e5fbc8a9963123e1c3a4cf8be6d1dc696480a3d130f1d6fb5c6612115b8", + "0xa104ba3752a76261008fe458d3214851903d3d6ee7b2eed5672815b8805b8511", + "0xe4da5ca2fdc5e2c8e0d6a93dfcde2e4273e1c837dc17dad1329fd57d0467e131", + "0xa1ccc561a0f5c87e5c36f3e98940f682bc1d5bc97615803ffc100189bbf3e906", + "0x95096f7f0b65d39e2f12a47281e046a31ab4bc01f402279c17aafd5f91a933b4", + "0x8f3cfeae59dde8f3b80f925fbdf104b99b43c661bb8b425d85953a6b63971a27", + "0x3b6544fbea14b28004b9a03a79688b86266e5e7714ea5ba27c8184dd0eff6916", + "0x8dddb96c7499b8e79410ca6b22f03d579c00446bbefa861e7121fb46b1644a7a", + "0x3cfe8d71fd57f392328d45a4fa4d6af05495fc45bd3efc943c35a59dd0feab97", + "0x9dff138167f92a5cb5e19d92545be2f6967e64faec4ce3d912261d13b0f77381", + "0x700a13c03623de6a15525b4b80ca7388305d4b526f0c52795935e02e6c899953", + "0x41d6d84b0af2d06e3c24798a4f430760a70adec3236accd6495e62c51b935602", + "0xa0d4b65158ca6876e04ead358ac8f262ec190cb20383f922fc56bd924f08a2f3", + "0x6fcd99bf39e3e02b159ea0f8f88af3e3d9106cab7ef3e0ca85aae1b7d65df2ab", + "0xbb3433e9eb7540ece7178ba2980221741563600e5203775c253625de9188bc18", + "0x52162680f1accd300e3cf145353a92259a67165072634c170285abe8aa146d14", + "0x4dbbbb9328a0ef70c7b94e7dc68a176078a744e4e37e1bf989aff3ad983f5751", + "0x0925afed938ddd0f2776cad39599d47f162859e5de58f1fc8144a01e14de394b", + "0x0b3ec75ffa53ee08e9ed403921c2ef6190777bed173a1645fdbd51ec3e17ca38", + "0x34e0993e94f3277e54d3497319ce1abddd09ba29a661eb3713bc1ecc07ffbc0b", + "0xb65467d4115d3b13075b298cd8e668c52ee976b776c99809e87fbd31ee945c18", + "0x642f85a0005debc3cac8549728ac17071e6fbfece30cf83e21a36bc36430acd0", + "0xd5991eb67e45b265ca67269dba2a17b56259406c309018e8494781e9a6384ac7", + "0x853d5cffc988d4a2a351f139a6ac36be440fb3a2ca81df18cc24ea842d004490", + "0x97900dca52f34da453abc39cbbe40edd6631381f0cae85f01afe9b66b649b260", + "0xb626879fd793990d2a7debbb0fd9cd4008ce353fd933395bc94555bad3563b7f", + "0xe287bff3e7de4a2ed9480a35d6ef5690abeb159663c2a166d338c4b757703cb4", + "0x2335cd471f8e16049e760f0233590a43f56940e45d6b38d21baf8db8658aab68", + "0xbee5e01c215dedc9a4531b73d6c2d8d71bccc390bcf34113dbda1d02cf3e790d", + "0xb2a661f1d7ddc11dc4b2dac43f1d88be575999ad25a4d7d7b181b11751eba19e", + "0xf18b71981cb3781230b8518216c324f706b13b1a871af74aed365c90f86cffad", + "0xce84447a3903e632751ba244999b7a61a403e92da74f07357523f1f067d48c26", + "0xbddb34858e366611a3e025cf6a357e891526972d408e1e080f3085decf603e67", + "0x7574828f83c1a7265aca08da6fc5d113cdd491fde3962a6c7dce44fb3352cafd", + "0x542527be1b6c42ceec8a75923d97b99416adc53c92a832f8e8e842d1027c9568", + "0xee384399858b14a3aae705182148a5aa513532d91a234d7c930330fde596d98f", + "0x618fd6df8a93242a489c5b630a4ce7e30a8af759536903f450329fda19596441", + "0x2c7129b3ebca24f916e6e252d71fb7d96666b1b55a9693e1bb30a8cc3327307e", + "0x1693e500ccc7a5005a8b52185014037b470bdf5fe112d90aa0e51db9eac80b28", + "0xf2cf8f47b5d3150e36815794f11a2ce96dc4fa4996d801e56e12cf7eab0aea48", + "0x088c123295156fd640dd0badcb95fc471044f0bc26d04aca7ba6fd7272b954c7", + "0x4403d7e8a25d39ea9c4bebb7775997065c90a3d4dbe0f5f2a4c7a53df79b164b", + "0xd0d82b3ae96c163b3a4617f69bdc9d4a9a65b90240675b85e35f91ca23d3b92a", + "0x0d284d21e9bfff443922dce492c3ae89fe99d9b27f9ceb4f894abde85d82a25d", + "0x5772ece7a44d81afff29b6bbba44bb30d4ff31b5fb5b7ad310b459eb48eb7473", + "0x15a33c4e5be3f9ff56b827de07e7614150d735409eff0bd9621aa04fe1d2d48c", + "0x84a218e73e539262c04d38f7b3bedb35e8cf08130dd46d91b7bf22a1c7f086bf", + "0xf7edd133a8830a2730a78659737973a324f455bf0cc1f9df4f7ae0d6eb67fcb0", + "0x6abb178f84769cec981c17606c3f2acdcbac76b8c7c21a1cb1ea5ed84a4e7bc5", + "0x538a4287396f9c38fe3c94ec45b38243f31211bc657cb753f6854297fa43911b", + "0x375bb5fde1e5169cd125a4c177dcab5ba60e41f2cda1c9b79c6e63f02ba235ef", + "0x4b72b6eed046c0f6295e55138f6733c322228d0874cf62030ad110dae30b0407", + "0x44794c2ebb781ac49e8693930da2aa2636fa683dc4c30927170b061b4385fe3d", + "0x0f9166e9ae260c9d6f950533649bc47a91ed78e57e358d2818b3cf8b66b413a0", + "0x2a25690b31702e586a4d1a21462d45a5a973d86ca6d545a41c35ac2efce48074", + "0xe9be0dd81c29721f6b8a35e4bb0fb8a1a8dd437a1932562407ffe727f3750834", + "0xab92028712829c8db7422fa7d93e8e6162ad820fb067e2a7ac1ee224f1cb54fd", + "0x2406f251b937c7236abdf78d7bc58c8f8f00beb689c9999669edd01558e9afc2", + "0x347201dd79965382f2ba90a230bbfc979cc35c37fbb5f21a4b8f384082434a43", + "0x94eed3164903b05cec96cc2d70f5ecceed69a7b1cbf2c2ff77a97042744b3c6a", + "0xfb8d2ddfaf7d81424ca748056c3997ad923e269bd2153169b297ecd02c74b113", + "0x8713d9cc0e3d9705bbfab9ee1f19a9f0df18c8157f6597dd53064ec05e873734", + "0xf4292118ad14c9a3644019696a3bd601589182215076426f6d12f9ce29f45424", + "0xb9fc592f9322030fe018ffbb80cf7ea0996970fa598be9abd6c97a2aed49fb37", + "0x5d9ac03a1a45cd56e7ec438b24ab98c52c7350cd5001af24c444dd451c4c77e8", + "0x6355e320e8310469b8e64784c2c1c13c939d61f55f53088b23634f9bff3a1d57", + "0x77ab799d4eb740269549f99235653da650d2457f95dd3b1cf95bf3855e517d5a", + "0xedc16c860af601fa7c6461f672ed82f8cc22749e53f084f98b08b0737f3b55b5", + "0xa217aaa12d7f566f29048848a586f5f43d787ea663a0e32eddcffa79769a39f7", + "0x1cda6f3902b67eb9681764ed2929c2d4ecb5e8d8b73e7d434557c56f2f2c4660", + "0xb654fbe4f8908c69911f2fa7fda440a015fdecc22c1eaf891d7125a5ae9cf0db", + "0x75dc3b61e81e8d7bd8665cb9ff254ac8efcbba3bbc0d406adbca9b68980cd52f", + "0x3752c044a4fd0d9721046f7bb68afdc920095cf7d107ebe8519b3b205b807b0c", + "0x680359cce41e959f611b5141ec02a42ba1b56041ed549fe3f7fb7c248b75322b", + "0x5342c1d8815e03ec965dcb702cad4a6b496e8000e07aaa737f2d6f02d4d979c8", + "0x52beae62a4d9cf632aea02c0bf7c3c9362fc0b1548cfdc2949edad071db77631", + "0x51555863ee848a88fa5c55af7fcafd5bed4c329207cf7983a6ba8d3e5b93de78", + "0xaac2cd4b648da07cabe53e355e50964604f65f0dcfed74df8ac5da4fbaab93ee", + "0x5124816feacb7422233640b7f2916e24c48cd5ce922046404af6cd517664b630", + "0x69837d6add2cffe312fe18c8a6bcd0244b3d1646fb5fc81cf25a15555e89d278", + "0xb18671100e02cf1d0280f04153e34d85c1bc79e9b18d464f4c840852cd2b7e96", + "0x464d0f22a9b071a24860815710deb7c724f63788ce1e69dfc5958426b7b43887", + "0x165e2391d76a02b3c15c2ba5d418598f9b6b43b9b62006583a1031e0dc1acb64", + "0x19e8655c389628902e2c1b0a143572da7287d0e7b1e30f61062f3d886a170144", + "0xb01f342e0fb810cdede0a82697c139671e88f9b542dc5e2df2e2715e11b9ab09", + "0x5b7c4bd8311a53ff3f56dc9f5a7b1e001b7c4a02188bc58e2d9d92203c211707", + "0xef874c2625b4abe006207e36af5ecd98a92098bcab4238b3e3275a92fb476b54", + "0xedc237012b0e6b3552e05f9360a49fadb1a174a74d7046218daf98da19d4f633", + "0xe5a7ca7180a946e7a8fb73e6f172914c82bd9571649f7ce17efd2cd96d89d875", + "0x4de22e8a3ee27deefb58f39c3d420cd6ef2c7d94b10394d0bb6ef7c7b347b6ba", + "0xc34745225c53661da2e6c6cc8a462be2741916917dc387d7eb6dac8a55063c37", + "0x562928f070776132a3b035c3860b1dcab90843f077336bd13ec7ca0e330b3ffb", + "0xa2673c9aa322bb6d2ab24d65934c7730585cb1613e4ab4e117f25849c88f0119", + "0x8c7b3edb36156e6d4e36a514b42d3cd074295a13f3f095a116ae5198acb64f69", + "0xafc6957c2f88c2bdfb63e89e83fde2167548f913e62297936e0cdbbe4200fd1e", + "0x075a81ff82b52704a862108bb2a4a1839b462e52c8562c1161cd56b00fb7f1f0", + "0xc9ce0f30ab9d986b6f1cad16a747224ac9566ac044dea341f29e0b0fc7a94504", + "0x7afbb952c21475725af2856f114277e2b76b8a0480f8272cb3be41cb514ba442", + "0x2c4f4fcc44f7e2a5892bc232f703ac03f8d4214c02c997ecb57cea861cc6b0f5", + "0xb909cfd7699a69da5342d1918d179fdd3747795392f2caf4619b3294217516ab", + "0x21a802b502b2d4265b9f4a736e5cfa5a7c9346c17b42b7161d45534cd39eb38d", + "0x72429dcbfd5a80324bfe744bca71edd4d71001ba7f7e37c717d84c05277fdece", + "0xf9d1266cbf5d78fbf7d36bf81fe0f4d6fdc39f6e3463c7e3bd334e703fc24b1d", + "0x910367ea4a43e9d466f93c73025dd99cb535bcb1ec551c9a2f5ba97bced399ed", + "0x74f5f129ddf7d2c306e55c2388eeeefb6f8b7e5f610a0006f649588d46f748f3", + "0x8f6d359b43e9d9a265a7c20bab54c6df0fa9c4f3d38cdb84537cc4b5b15acf30", + "0x97bd0d30c019aa3828ec283910fc420a58251837195245dd36352db4027bfe63", + "0xce920942f6bea6d1eb1817c480c6414d1409a63df38f141a3675968b8ad20769", + "0xa5d06dea02d06548aa83e8fb16a8741071a4353a60b9ba1ca530a51a7d945de2", + "0x60af9aca626191064847d505646c185266658e1f22b3eba2f407ea21eea69ab4", + "0x9207b93c6b728cc55dfa0dae22cb777e05da19e20199d40abedc926f0e510d79", + "0xe425b207ab396a9b546da766671bc8d304986c728a01d164e7661c5cd46713b0", + "0x2e207fe33286a8a9a47f40ee828162e74b60262733bf8e59b7f3b0ac1c35dc41", + "0xe72aba9e82b668caff99c2c8abcff3c7cf95f441eadc8f54b712d53cc256e41c", + "0xcc4987f0ed4e51f2f0be181808720ccbd89521b7797770393001d37df2d2d5fc", + "0xb6be663793329373d1007bd4b87d72f003e3bc6c405d729ce667d7d5a4730d33", + "0x90b961b68b506c048a3bb22fd906329e23b0e397f321c3ff55beb63726859778", + "0x86e0f5e1b9a03358bd5c9af44957f12054599d7c3ff54b1328e3658fdb9769f9", + "0xd4578ff34c20c7587703366d08db79df13eeb4222d6e4b59c8d19cfa2b30ea1b", + "0xf9f6f3e0290bdf5d3e61467ea4fb2ee5e7d398d69c3ad18f05ee983a694cbe4a", + "0xc3f71a9c233ecccb30db6d8dced87b1243ed9fb87095c528bda85c855bb8a315", + "0x0d31f22335d9f802c73c57477812974e3ba83bf66547bb2227e28c4b4db92ae3", + "0xe2ecb8549d9887fb377cbb921f44a4aea87d8951b21ec4f678b870edccebe6fd", + "0xce62c9fbce8b074c8c8da53b5aea8d47bdaf0318346bb5027ec4a37e02b43fc3", + "0xd3f0cc456ccd881bc4c9a8b777eb88c1eb0235f362f647eb413ba90433878ce2", + "0x26ed42fbdb81cf01c78345475504bb24933bcf227ec7135d95306218cf47865d", + "0x37aa161b3dfa8716f22f62bd132ee6d149312e079e43c60efa638a1a24ca6770", + "0xae8cc778b277a22245c3b3346b96995733219899228190ce912aec079b576077", + "0x246ad94e203f268d4f0a0f18b23c6fae5d1f43612b22bf8e981526c7bdfedbd7", + "0x466bd42fc5d96c92818771501b188660cb97e48f9d9f12cde6258a85a88890b0", + "0xeca775ea1a5e03baaf47c5bcd3b70c029c309812151e7298bd16080248365dd6", + "0x3d47dc150027f55c6c1810d7b86ec79390a7611771b959cc51fb02f5115742ae", + "0x3aa1f15ce5e5df5ce604fb6904b370bcf5ce9aba7187d73ca90d0a0995425aa1", + "0x4cb879eb362837a7423f051b426a8df627143dfb22c32ee73c969fd47fb9bb2c", + "0xed8ad7f8356fdc4943ad2da2e34bb45b4b874e2fec94b7c62b1c80b0d558010f", + "0x177d8d82d8be1c35db8608c61c478e72828901e405a5dd679b1fea6ed9f30eeb", + "0x3b895fb2e93e4a34df9688ad144bada044c76249842855f991912c1a281601b9", + "0xfa0b99e265454de96a05424e4f33e252297f99238d8db0a7ef82cbc9bca6272e", + "0x81f15f0ddab76af9dabe0d7baf8d14af2afc88332d76833453118ca9798041ae", + "0xe0fd68f5d09a2de8b00eca9295367f73f53e4cf8b890cf61b9178148bdef13ad", + "0xb5cfffd68192f9bf8e9dad4c26f8520883a1f8ece8da9c77326aeb8bee69daec", + "0x4b676f13ee697d50569b222d0bf9b17dcf37efc299ca7cfbffa1e67fe5237434", + "0x00f61c387fb1f436bda1d0ea9f29e107056593e6290582f3640c673de97dbfe5", + "0x2e982786a7951f28a99f8bac00ed2e778dfc2893e68f89000a60763b8a456278", + "0x13483c74333ee06b47d832d832e5f37eca6c4f736ef7b7aa199ea730bb9c670c", + "0x6b12d14476194ce0d9d279bd8c5f83d58be571144b7987b4a481dc8fa10e8e9f", + "0x4b732e2ba405ab706988a602378da042a0a7a6c81965974a1eae029f6e659064", + "0xb4383796f2772c11fc056e60b9a9ba4d23a05c7bda1b23082e7b7fe281f97ca3", + "0x1ad86ac7e2a91ecf27b202746fc8dd57f66e721d14c3cef8cabfaa66ea845a40", + "0xde67d8828e9f223bf8bce95e293c68d8c1678eb23cf7ad81a333914b5b9864b4", + "0xca00948f426ed34a756f36691f3b3b17368d5568296326c06894bdd358271f6b", + "0x1588b3dae135ebc9479b9236c08654175568425930fc3c08c0a3cec3d5390780", + "0xfa5581ab4a047ddf2e4e11897e8361e8ce24603e53228136c9eab918580afe97", + "0x0d3769ed93c991e5b78d4a6c76782f3356b1d24204815f649e6a8e853dc04472", + "0x8f1ecf593080524d701f4cda40f8f1f2704e3994948b32ddd222003609958af5", + "0xe0bd90aed7b8c294794adb61a94ca02fb9fab693771c2de1b0aef8790c75b185", + "0xb00d53d20179d5702f140623c913c5e42e09cbc36e571fb15b820f91539ec5d0", + "0x0bffe46166ec23ba7f066df0cf14179fb47c126beb8a83a0f1b5e06495ae9cc8", + "0x07e3dc084c4f702ac32dbe9db6ac078b19b9fbdfb2305d51d4da9e2d33c87d4d", + "0x5bea17dfd96f81ae273151545eeaac0402ee6007621fab42c74b92833d190e34", + "0x3f078eaf9025ab2f7759848b5c33b0ebb9aab95f028e0ae0f5085c73a3fdef26", + "0x2a6e8f2715be40302b7530e63d9de7ae64b81bd2b77b3d378c496c9d42d3511f", + "0x9b000c787f530038dffc5d69e15dcef0c39dee75289c32c9ae2f11139056fa45", + "0xb96dbaac29d6322da225208d61c756f63df4a7a9a2d41591a27f7ea1a7af4e78", + "0x4b20f795b7e7044361f319a0ba06389a9825a138a30c9e2cd5b25481f2b1331f", + "0xb90f6c8dd72b689af1d1f92de10de4ba48c10acc8d9921b50a872b4ca2fdc86b", + "0x09d51ca40d7ae1775bc1ebae767b7981f7a66c39f303d024793dd73f48a8c512", + "0x71fada2f87226f9cdb9554620d07b42f8279c40db9ab220737769b440e1ba50a", + "0xb52e3c9c0ced2ab02d5d4d7c4735ff444bc8f016ff9a8ce8bd9fbc0a27f783d7", + "0xeb49ef79318d9f7d7cac1ef41a82021b1f84f5bec0d1223d34bd0b067797bb25", + "0x78fb3c876e62793664cde7117b9268f443fbf1e23fae935f6e6e710e111098b5", + "0x3aaeb697dbdc34598493556cf9eb57e35b61e718fbc050cccab4bca362e89549", + "0xd75400305a5327eb5a0036c70e015a2d286f8814be35abce2d5cebd3402f587d", + "0xa362f91fba2627ba450aa041f02f4644ae2fc1c5a19cc02c63b01491fd650bfd", + "0x1fd2dbeb82034a11d5c14d0e376dddede1f8cc2aa660c6a2f57ede57e2c0d2fc", + "0x444e4ad03ac7305087566e07dad8b81046f293db32064afa64e31bd9b2268a21", + "0x7f7e7ce8b73c2a6f8e6a9d9bcf166c7cf67e2c04d9a2a5dbed89d271ebfb529a", + "0x4ef8be82e0bcce97ef82daa382af63539c3258fad8ab4e7c7f815d753a3efacf", + "0x1b0d1400ddf579ecda24a8b0c9adf346b51613febce9ed41f5dbe28e3dc3f544", + "0xf900a2c448235dcb11f46e05aa04f9214732a5770da9f6cf230462a644698a4b", + "0x8cf03541b11d9a0763160367c1fff20b72a377526bded7d3f1deb6c165a10cb7", + "0xd3f1c1b6ab0f0284e788182e1d6a8c7fa92525ed8621b84a2b45938d8d3fdcd5", + "0xf00edeec9fc8082272ba3996e6a2e3ae8835d6930e9625f20a599e579bc13eb8", + "0x971f80bb7cd7d81c0d719e69a908140438a0a3f04b44fd573afe70212e6d204b", + "0xd09d192e746b64f924dad1349488c563103b6a51f4e90438a69ee1d0ddf5a145", + "0x4a1446a3d4ef051a1ea3dc1e461179a2a3374b78c312209e32f62575ba2d3902", + "0x17f4a89d23160692755fc601893f501abd0528dc9adf0d62fd02e77f0c7c91b5", + "0xc122bc9dc4fea4352c119974d7de78b1f6e6a9372f7d0886798445432889c635", + "0x0027a25ffdb229b2681216719ccbcf770efe806655c906a7e7c025c9a855904c", + "0x4dbcfeff4e831313e911ace5367d855ac4b661a3af6c81a4039dbaae5883e8fc", + "0xde01cc015a926be23495402e93019c8647dee8a58dbe6a872107e41bc5c807d6", + "0xf53866c20b7e0fb124e50f21fca74072f33581b1330e106596339f775626eb75", + "0x474ef22e2b54d652719ed75c01d84546eab8ecd94df1c081539e0f7f04efc281", + "0xb655eea027d9c6ac99917dd0b0edbc38551aeff00e18df5189d3784b848ba9ca", + "0x4142871ec25245d2b8172d7e8965a21761f3c9841831b7aa0e039d6540046f77", + "0x4c31f0670a4ab4485d377baa440742393f648461b741696c9eca4d1b0f7f3e55", + "0xf47c0076e4ca3702f22856f7524c563a8efece0ce3062e0112b75d018a01552b", + "0xfa7c6eedd06a74bbba072b43ab37a86b836e6e60ab89b68ecd14ce9153f9d98d", + "0x2dbe33126365c2d5787fc4c095402b2353b84d818a867305aa323ba2fc06fcb2", + "0x31c5c6a750102bb70a45e88b5a42f34734c7b6945d5505e53cda29819d9d4b34", + "0xc94162d9b47606325c024de23f77df8abce2f5b797c9b11296af55df5720ac98", + "0x24a99f9791b2952dd6923033c68b2af947be8017a6a43ddb66e7974566533a55", + "0x0c7cae3072bac27cf58898d9cf027d3f3f662a144635b25e068135006925a244", + "0x2706bd0afceaae0cecaff80d91f5fcc023039d338e028d72142df40f5484c16d", + "0xeeca13bdc1c0f8fb83c839277efbf01e13bb27eb88b64fc137e876bc750c5e8a", + "0x1c16006c6abfb954121c52d04797ccf15a1ffa6df81d70088fcc7cdce14730bc", + "0xa8f70bb282ae54297c053fb0781f4de76d888d3f9b5144b4c6dbf40e40652c2c", + "0x5fae325f5e511c10bc6f084897665c0fbfd3ed319f2e2c2230a4563f5e22caf6", + "0x6c8c138b8aacaf293882b71eb3d15b5de6610ee192816be02b7a048bf57b0a37", + "0xc05764cdc3bdc40b0ab31f55863cbd8b7bb2206e49de9adcc05f52fa6fa98c24", + "0x38ec63286c922eed91e1049fb5bfbfdeca387fe8dba9f15cf6ebb3ffcb3c2a97", + "0x7214dc68ee2c70357ffc20a5074d1a952a4eadac92f87f0a0025d98a896afed8", + "0x8a723d4ddd08df26a6c0cd5755e03d2641448f0440e2dbfcaac5cff7a602e202", + "0x9567fb04ded1384f2ad1cde98ee4fc47e6c85adeec299952ffe48e8c788411e0", + "0x2db99612e0813b685b023f596c66f5a8835b76c54fd0fd8a4a4036266bc9fde7", + "0x6f1895f5f59a5065ba07f7ada8ad706d861b6414d2a0fb80f4ea1a437ce79af9", + "0x338f901d0024719b2fd7b74793770471e049f55cd421c021d8326a38700d4b06", + "0x56c0494b5617c4f8146014381cce5a7bf281774ff31e6d62b66aaac9488799bc", + "0x0c5365039c79856fccfdf5f7103ff2d9dfe63224d323009f364e61b716e8726b", + "0xf047dbeb0fe9062ac0339c104b8c05698a373cfacda540e760105da80d46c36d", + "0xe905e3beccd5ba7666f7a825927400e51fcb9271ef7a7df95f564181cfa98ac3", + "0x15fa4d3d0b5dfe1231edcdb9e2fce7b3af4f6616f6b36fa989864a3f9d928287", + "0x8f1f7b2ddeec2c7beb8b1991cbae9e160ab8b9955ad38727b4c54a841430ddc2", + "0x3cd200ea95174cb21d1b2f36f20e9a53528636925365dced2579fca38d5356c3", + "0x255fdc3224022b132381a13a678edc07300b8069fcd9f21c47d20fa53180ad4a", + "0x155fd13b7e4d8864d27ab0194a89dd23b63d17eb8b72aae64f6f7519f3c4101d", + "0x40f3a4e9436b85432633bc85ee8d84f40ae928d8f9ee8837478bd9f6e050d46f", + "0xe5abc38fbb49e4b3674dd42acae031dbb4bcf6874bf26ca0c7319fe2a519d81b", + "0x7cc31f9b707830adc72477ff2ab79ea168311d0916bf2754e13daf01d4813e30", + "0x19d333afa0cb54a5ee3745cf1156e2daacb6e8f65b03f464320d4d33077c5c06", + "0x38791f1a32f4028172dcdef9050ddf5e83f03604dc86dd8833b65d833e347ec4", + "0x53caec8dfaf64faf8ee9fb49b9d439a1839cfd2a114e3ea59e80e5c924b0973b", + "0x401faa9732506edebd8b33e35f5054a1ce443bcd3f2b2e2fc4d131851cee8433", + "0x24280a731445dba6180ff7c0e99982c967541e21b5e46dbcc52e75e10b198d52", + "0xa61fdad71e4fceba924a9879b2ceb789a5161e9fa75df55303156bcfdb66b79a", + "0x765cf16a2d32f2b63f0b418ee2a46a3b304466a57f6e190aafce53053b925246", + "0xf2bb839a01d78d92b65f9f10ae712ba4ae9fdc187e5f41cc165d3e1bf21d7a37", + "0xfcf2a12414334e043d436e0bb8a2b0e9a0c5e8d390bd0947f737a261d8e27e3c", + "0xb85aa727377d00d02551ebeee6ea4180c8ec32518b208750890aa5c3a7927d8f", + "0x2da1a4d44bb0ed50267a8f7988b5dc7d9a01b621e863990b5b5f2006a1980f9c", + "0x0f9ce379a089978484ba7f865dbd8224bba2cec1e3274e477faa3d098e861daf", + "0xe4dbc55e6939aff20fb0b052ff19a2098b7fa4b69379b8d72462a22a8ff00546", + "0xbebddeb98b2ff22f6677176b065eaef5846fb6b78d77c0ca14929a6a8db5df62", + "0x2028557352218dcbb7a6e019be318d57acde6df729af6c4db59af74a4606f253", + "0xda6f0ac6e72cf93bf863af1e9e80f1da1c48ffcef6d7caf0fbc59d16780f5cd3", + "0xc3bbb6df580ce3a65e4fe1c675dc252fa693f70361f7039eb889ee7566abee27", + "0x371c7ee758803a6858ffed0313e1f778cc1c05b421583984ead810bb4685bbd6", + "0x7fa797720e3f3fc8b0e29a3058b07fd30bce95705bdbf0a976362c1e0b3edf6c", + "0x7dc0a39d699c351a188e485e5dd1ff85c53bc8a91866b34078c15c304b989b35", + "0x999e2886bd5f6c7c32ddbc08470ccd1f4590cdc460a845a0ce6ef49354c9d207", + "0xb25308afe1d597488fe80a19a5d0ce2204a0d03f79eb301f69f778fb13dd0c34", + "0x767809b36c8dbac06bbf20bbbb7f289f55a053d67e6f36fa94218d3d97212623", + "0xfa7a7c8bc8bd8af5cc6c8aa0259a64187a7b78cd93de0ce14ec13df9b2141ce9", + "0xc11f585e553400d55c7a4c3e50f368e615ed5adc3c0e17b51e36a10ff780c395", + "0x8b12c9644197b3cd18543bf57473d48e76a9877dcd0430d1401e47be8cee2ead", + "0xed66cd26d319267898cbcabaa969a20a5f72012e9f9891f30f51b3deca75fda8", + "0xb5bb169c156368c3ef7af609fc0fc57fcc34cf33bdd55abc2805cffe5a6298f5", + "0x134fa3abd5a48083a735a1fdc3c261a56e9cc1a3c51fc889298463d040dfcbc0", + "0xb7009411f50f3c68b77424ffa4e1fbde8da1ea29ee7bbe60c35ee0bf281cf3af", + "0xe9c1cc94016e1c4fee612a5a84e1cfb267ad3613ee087549c2be29ede59883c1", + "0x9aee62d9e40adb47b5390467e2de8e26a412f2d23e7ce07be29e120e73107c86", + "0x560f92c67de947b45e68badb021a1a6db67aa40ab15a9c3d3af6caf077741c19", + "0xdb78ceb6ba758cb9519c04b48ee5f13aad1bf74e219c6793c62a2e66eb2ae486", + "0xf23ed67dbe442d5d0df10cdbc0d4f7081cc9deac7720a7245ab487df5c436b08", + "0x4963e648bb6d493050b48e5063c30c8eecda734b298ee1911b2d494fe200e853", + "0xf77b9ec5dcbebcb725001af466af4b51e6df0f56dd888955d8bf11ceb613acbc", + "0xfe1844dc936a73c836f70bd3ace2f71a1887679f86bcce0d8ec051f8395d58e2", + "0xce072d500d2a3abbd538dbdd8809b7a8de9b16ceb46759c2e5c62d8335b9ac3e", + "0x628480dec741850e8fc78b39b0012e21d2210ba21ff506303b3a30ae7120242b", + "0x5c003242439be0c9231d029329366a8ebe26242e3f7d79216cc360f77194b996", + "0xcc9b55e2949e9f1fd5787b09fabb7f48140743ddb4bfac049d53c07c6901c936", + "0x8c809a16fe0c1c49d5243d7c808a00b80d090e76af66f139cf6ecd713b664a2d", + "0x297f44efa90f5a5c9b82e83d9fd972e0db020e128ec55b769268c1a90ee1ff98", + "0x14b10e0a6f2c4b928235a5f904ed196e8f2f0b7caa6cb22702ff301b0df9fdbb", + "0xaddc83c036d1c4a53ef9779196982402dacd2d18fdf65c59281a2707045d3403", + "0x8b1301861c953e3014841c61bf82c5a29e2c2f275c272c45145e1bf75e11bbe3", + "0x9ad184b5e60c0bd82d1e1cc97c0bf9342da816fdc6929f64c2f47f20cdb8e9a0", + "0xc0a59c2f537d5c7bf8c5df55f02fed2ff08041b261aaa41acf62c951a1c826b7", + "0x9284511705680c802e137409d590c84ae7b29c793d06c596190cf1bcfb868808", + "0x10e7c8f871f620e2a85a36874e58d8ce093a47a2472b5a91a5f18893808491a2", + "0x6617aa1817809081a7fd620506fa60b5b21ddb2b58444108de37ff279ae24ac8", + "0x2eee26c860c64ac6efd4c9490d2ad09079ba71e4326df3f44af24b4e8edb1e7a", + "0xb902f640d25c45aeca0cf43e382976fd6e69fc85e440d589e95d959ccbd1fdb1", + "0x6446d62f00c80734166de70f3567619b72900344c89b2ffe1eea9c30941fb74e", + "0xe1fd088edf1f823f441863a1ac3befc256a20c0aa1735f9a3143a948984ae301", + "0x2095465f0c5b89694f404f88734c02a989e28a41e8b8c2034043da962ac97588", + "0x97f70cd16dd81987bfa047b8944771331a5c31b328064dc8b56fd8b2b38d8a89", + "0xa18f31897f4bd29e1b77525f4458990e8bb7608a12221163037a55f39e7641fd", + "0xebfa2dc85ce0486ab35e5a7236f5747a3bb972162cce1a08a88e8775217581e9", + "0xc2a10452948ec591e4109be62c0d5a8bfefef2134246082a61c1d996f11ac4e6", + "0x4c24ad9e32fcbd76d0d78262e816b427ecf946ebbcbf7969461baf3435a022d7", + "0xc533d00b4a0526cef84e147aa77a9ad4f6787eb4f838aaf0d539c33ecb769494", + "0xdf6926a0b2c8a72abf58a5e309fb236412d541b33fa8324bb2ce92fb0d0ceda0", + "0xdb89855b6b608d1c71689b46f0af66bd918bd98d9653073c9a875a6dc1f7a273", + "0x72b64c8154a8365e8905ef0372608755b70608af7ffa588da0978a59f985d0bf", + "0xc1a4486e65e4d5430c4e63ea471b52057fc1a2fb4343459605fba4e764143fc2", + "0x557443144308f0bba5bc64fdb1deff50eddb5728d64da8b0254ec63845095d47", + "0xc42ea586d77568d096e8bd45289fbb4f42e89176a59b143b5cfe2893fab27db8", + "0x7e880ce359b0589c85a219a545d994c38d1ce05bb365906f41c55c06038e635b", + "0x3daa1c97b81387cc076b1251bef684defca282480002265fe122e99769a0e84c", + "0x2e04dad2a0e7d29fb5b4a357af29d0cc6de6831940622bb59227bd6cb200f0dc", + "0x542ef39a7f12a13bb20cce43191f018360554e56d624b23fe73e452d40601bc5", + "0xe77d21c5b989e6848b7145ceeaf96bb3ce53aec82783124efb8b64ba106c7adf", + "0x6d1591ca6b8988e6bba0fd54532c2c2791960e8f3e82a70d336cc3a78ec8eaab", + "0x0a8390be2eaace41828986333caff47e69935549d6012054d8c5ad8383f041c7", + "0xd90e8723f2d6eddb7f7bd77b01be62a9dcc86fd701f21fc456173e233ba5cc6a", + "0xa21bba87e6683a9e16ece09590fb96239c34c64c5f94e421f16a21e07d4d07b9", + "0x80b11c2f9f3dfb333dae65e77b155f789900096be59d18aea7098a8431f57903", + "0x52d749a1e59a55474f013323cba83e31d37069383a2e8d6e65cbd741d2e8eb3c", + "0xffc5f4ebb7d58d1efac8831238950ec1c7067dfe61f91ffc9285679c21ab17ff", + "0x6ee683f4215196416fd9703ca94ad672f13ae00464d1818478e02cde6bb70982", + "0xa1d9b5d02bb39166ddf32c9cd08f405104f2205d1ab0c7e54aa181f29d827402", + "0x5a782d8541372e665cdbb2b42f178681f40b2d232f73d52bd54765a23cbd5418", + "0x76b8a5648028a7cf9fc4c3eb60697a1a08b6c2f3b81811bd393c7608f7140ff1", + "0x20248198f84d13e945335ff385ccb3668a64225ecd1712412b1f6f224f8c8480", + "0xa922a3c4d2707224fea1639492948c91ec14ddc1b3ee46e03627544cec57dcc7", + "0xa4a95f2d10a2d809f8fcb8f16cc6f8179b62fcb26b789705d0686bba1845489c", + "0xe8df8182eef6fdb724d192e0254573c829127a4064122c9507a1735c009ff6b9", + "0x0dd37e064f7ae08c0207e1dd7699436aca14f9e5d39436e31539bde492a2b1b0", + "0x8453b3edb890a8c6b6a519683a149565ae64920f168a40b35c383a8734e9945d", + "0x59d569c95da5ef5841344f6de16e262afb86039ed3419fbc92c5d2ee13c1beb8", + "0xf154537d82d894a8e7b4226339fcdc953a4a9a11d1213c440166b6a58fefbf89", + "0x7a422d65f4befd89e1a7c2da40d482a6219169e5cfa309a364d1ed0663515146", + "0xecc79e782017eea87f640bc9d9ac7546aaf34d21adf1a3badfef6c48aa76211f", + "0xec44728bc6c94a2763b466d212017f2645c7156518ce4e3ecd485499be3ba6d4", + "0xc9a98ee4d90084697a5aab3665104dd11ef36adad2c21ef003e40e485ea444c9", + "0xf8a4273e27177619d8fde9db3c0659cd5ba9c084f717b697eba3e9ee7dfb1bbe", + "0x89fe4ef0342c6ec695cd14c518fd4e9504dff3f084a802cb0905fb5f6d03d6ca", + "0xf659cc0c0edabecac9a0d95fccb0eea911fecf4e53b9bb3b28e6eb9f9e83c682", + "0x548e708e7a2a136ae6ca621502fe690d6b1e31781cd64123fcbae8a373c11b2d", + "0x1eb65d47369949fca2f497a11f19df8d33fd8f5ca58b804cf504831d08f2fbd0", + "0x494b951ddde767f53900fa2f5c7d1f0dd8638d7fca55203283fc30049ff06196", + "0xcbd0b45603ebb72c7283fded1302eb15a46016ec46f2a64f4a9d7ef59ab6429a", + "0x99adb9987a54647d7b02aa589268bffd35ece71e82d99419b93ad2d67e071c83", + "0x73f4eca410495d4c91d9b979ec8dcd8a575ca89ea089ae3f09199b1a8c3ac9a3", + "0xdb421ebd89476a4cba795edc92e7138433eececa609c17b0f808e9f3573cd992", + "0xbd858de7472f57e2ffa0f326efc6f6834775741317057a4d016d5a95d35a63d2", + "0x54203ed14df2da3d572b61797d9287bf245f9939aa25a2bf29da5db6f7738738", + "0x2ce99eb34c785227f2fe479ad4cfefcf1c6df52201478fed66868f070789fb68", + "0x3ef8a4b6565c6a5840b235d759f7afd7837f5ffbf99640e1587a0ca468376add", + "0x42d89367b255a60f260b889fe98d2add3c77955d5c0aeca0d6f587b0d7709ba2", + "0xe04ce561b160f5fe3beb5de71a97f9f69817928d6138ce956701843d07a78903", + "0xa1c1d23fabb55d905627b1dc61cdbd2d657b981b3ff205f64b8ba04b96b766f9", + "0xf64bd7b3dc213d170be5f21ffb557affe15fdb8384e598c7a262eadea8812b35", + "0x0f50953c45cf831988de2e75f5089cec774b44cbf37391f83f4550e026f758de", + "0x5855905648b09a786527b259051cd04ca511d373849e794dbaffd751b6d47fd5", + "0x209170773e78428bfe4d424ba4b20e174949c1c475f1dbc0e3a77739cad4014e", + "0xd4d057271afb9983e24516e13f690d3a5946ab0bed28e294a5919782298f95d1", + "0x02c16a3265a5e3bf8847e29e57fcc5f7138b3ab479067c6d6d682d2904442069", + "0xb1d1a67f9eeec0a9e8971b860031ec9f71c0b83d2696a2041d0e8e7976683f2c", + "0x813cc8abc863d66a7e60c7e91debe714dbd50dd8f51d6769fa083c561b6f1292", + "0x18f0b5bfbb64a57634088b9af13f06030723974c5176325db9dbf71443ece8ff", + "0xbc2511f70e93a9fc24763c14f37b75582df78cc627b934681fdad73e5f94aaf8", + "0xe04f4a7390a9af34d31314e7610a051574dae583fb31112b468e85b230b08a27", + "0x68afd2ab749095cbf8cdbfdea79d99cb69560c00cd1cfb18992e7bfa278ab60b", + "0xeda982aeeabab6b0f305564901941794984ba5a752ae48f01a9755fbbc3a43c4", + "0x394778dfc7329fc401ecf8a15109b23b8b8ecbbf4e7c800b47cf9468eee95986", + "0x9c0b1978ed25aa551972fd6d90180463d5a9539c06ce3adbe3b83bee26a038d2", + "0x46220a848c83a60e656085cfb7f3c977d8bcfb6368e53fb0877e8a013ec1c3f7", + "0x71354663325aba30a19ab2f2125f9ee901c7d142654af898e6f36e62b9d47d21", + "0x701674d55517850c17882abb2d702a42c52a26e4f341ea33b7204a9245bc7fa9", + "0x13723d73f227a389518f9dcfd81ebbc49a8edaaae8ba63c9765ec62bee0c4d85", + "0x61f9b96a2f3980056aad14d9906835a5a13f0894c530752c6ab0a6a1b316653d", + "0x31fe952a648a9a2f7b8d89a3a57758be3cb74028076237c70318915677885b0f", + "0xd566d66d853468077573024a844328a58aa8ba989424d66bc135db308bcfcdd0", + "0x5aac4e8b1bc902c7210ab0b56f8b58eac98893d2c6d70dd33bcaf63b97cca60a", + "0xc570c28ddf514637c8e07427b895f23d52be931a492220d6bd3dc3d200d105be", + "0xf7f7bffad28ce00b8254d4df4b5079cebd236de2acd9a253c09636c9036b99a0", + "0x59ccd0578c26e64a359d45367b64a97b97f43a85189a109ff8bf7d9acb871dca", + "0xa9315a3b2e7decc5a653c7510f5ec7737737a325767c469b5aac929b4581de5e", + "0x576ef478c948410ac57c074cd25d5d7da97e90fdf9bb7db70a866931ffcf1ffd", + "0xa9ca2b5a515934c38c66d2588408941f1f19f0b898c6ebdd777b8b4110387311", + "0xe8481a5871b10cc7c278c090d0115811824941f119f9e66a391b43bbfa2a6ded", + "0x5dd99890bc491b58398406dc9b16226cc47c207882f94c2a58330579c16fc256", + "0xa965ccf30e1cbb5fa76359622da6e8d979f3ec487e7f788399da9c3b8af4853f", + "0x09113412961999f8d3e80628b8d058a3a6f8416f4be682402b91047a73e69b46", + "0x725b185229d9ae3b5a1c2c15c2e5a9154518df50afafb8c100020e875233a7e6", + "0xcd871a14e5672abbbb45c142a44f937b868c4e265dfa68b10bae64076c68d7ff", + "0x0a257cf0c92e10a16c8fea72fbaf2e6f56c840f2a031589b70a5492f0a9944c6", + "0x64848061f987980ca330eb74b640663ca391cd9735fd2e8bb863dd42961ada7d", + "0x51c27314780be532857fcf9d678d4ab05481f6c43da4527aece3c39a4ba6975e", + "0x78de86801da812219bd71e972e621b437bcdd23ae6a2db4139d9b62e5c40a463", + "0x5c98c32dc0ed6d507965236eb7a718ace9678f6f12bd5f81b68ae44144a15d51", + "0x3725833155294cf2ca6e1b5d272f0dc57130ba6e3a2df55111900f7caea47818", + "0xda487e7cd0f45f93431237f604218ac3d9d439607037b153ce985ce92d16be03", + "0x3dae2a9c0418a46d752c7cb5a1447f8b4c3788788bd4c6b85583c3c149eaf1f9", + "0x53dac7e119929c41a352b46eb54ba52ce59ed5b7283d0883ed48d0f562bef921", + "0x7e302413f400b0ab38f202140ff892e93700c4484e8cc132d7cc115606684cdc", + "0xd21bb71e163b1b4aa2ffd0ce2232cab26b8002a999b901a03484bfd6253f3fc5", + "0xb0284e9fe043f920de245b35e0770c75782b9bfc81ef2ede04ad382a51c6daa4", + "0x9d2efeccfadc80b413720f27779590b366edfb599d81efdbc366846daed1b77e", + "0xf39a139bbaaa2880481a3aab168fb350db74e3b6d6ac34159b1ca4af4d47a850", + "0x51bb2f5edef77de7906c0816826288657eeed00a1111d79df311bb904cd784c3", + "0x071529d3fcd41761d977a0b344932013fb1289eac00d2ba19a3ac5e91e9281c5", + "0x0fe0a5f987e8de4355bae9f7eff1a664d2d2175af90bbab4eef82f3c2dd035bb", + "0xd1094c0c293d5678e7a05b7e537ae0040ba4202183c682075da12c6e02d3f4d9", + "0x6319ffec1f60e3b4659329566b596ec0c875ee654a8fa2ce2cc7b96aece2038c", + "0xe8fc2d78e8023adb761ea580001393a9e0306fa84f9abcc9d6f5d8875db9cdf4", + "0x7e75553809968c9e97b2ca64cb05809e45345d91daac452989a55dfabfa22bec", + "0x985fde0528b9843d4e76f2c23f76731ad14d8fa61f4b8e35d2a32cf7cc31a568", + "0xb0b679f35bbac65ec2f7e134dedc76d2b9f23a14c70faadb2bef1d914da6d791", + "0x1586492da00013d3c6ccaf65690ab7111ae6a83d3f9034d6c26d9d8072eb464b", + "0x46c861b96700ed966bb9b6ea6c5e87e188372eb2e08a1ebaa01d0a46e91b3cb2", + "0xd0457c63e7fe1e0992d1a617cd04a51eff1524d1a18afd66e71c04a321a7c999", + "0xd4863d6fb4d8cc7b62568f3960da84ceda8fec5e84fcdf031af7099942e93148", + "0x4b47db507a812eb9db6b6b2eae64e2b1ed9c51e6877e44beea9132309c9af199", + "0x7ed56768a2fa6c29f5cc1eeac629f32e017076664d5739fa62fa55e3138b18c0", + "0xcc7b6315c0006ae1e93701b345b83e01ede46164f8ac0a0410f5d1a1b0ae63b2", + "0x242f2b4ab0febb86bd74b9da83b1efed9949a05d3b19297f928a3501aabe644a", + "0x8e1b7b621ca8b594ed4b10b52beffa8079eef58c3153943b71dfafa2bc6a7a22", + "0xce4c217d7ba4180883f09301d1a77e9a0c44cbbccc099658dfda1c3eb715ee95", + "0xccf2da237cda4519c41dea0a3067bfc3870f3a6ba073d44999ea3b10bc32c5be", + "0x0d83386aa9ec920477eb85492389f45659b57be79678df596a0781a1405bb6cd", + "0xc74c70ccd1d4487e4f6a8e77ca09cc394b6870e343b4285ade688d1b6df60e03", + "0xa8f22312c6ef7a0ff629dd0c64739f055dd09ac4245c913976e4e6c168f8266b", + "0x9c116ad329b4a3023c5c7bf711c3dc4dc0f9581d68847354b9ceb57687a76643", + "0x292024c45930a03895ab4b1e7478d7d784eeca1f5d61fb1fdc03eb8c345963fb", + "0x0b21a6dac04948393361c6be1abe46f5be0b28ba158893702fc80b0aeefce2ab", + "0x1f5799dfe87f6ad4931696e36b3c5813dd740ac1d025f0db490cdf3335af28c5", + "0xbcf97b72036215bfc439b55440103e37a7931531795d93acfd00d078e6e88cca", + "0xace36522a0c56067bd29df38c2d1e620b9abd880a37425dbb6f5ab857f9c5743", + "0x90c3dcc279a85988c6e9de3ea871bc89d54202e03355bae21c63a4d866a4cf89", + "0x8aa5e6a53075c91ddcc28fc72170c4af931ae9cd63d512b596e9863fed4d198a", + "0xa80aed681718e923660067910680e3eb057e3de6acaf0ca99f005a796503d0ea", + "0x96e8541615584f709fe77778589ca0a17f07770da17089f976e8b7fc302ec77c", + "0x8e2f41b07ad87192b79e3d96c18fcf07a170cdc9b23bf4624b8eb80053a2dc37", + "0x16543b7ba202f359d888640cace56e300346a475999a8122667c48894083dbd1", + "0x7107ab2fca188dceb5e4b0a44eb53252c54da2dba0aefcbe00625e689c2b5bf7", + "0x25f871a59182a4b0f043159c7a716562c7d063025257b89dbda19f5aef68e9c4", + "0xe70b7a990644ee1278e92f3ba1cc6a9a40b3761d8973ee4df91d3e3bd3ad1a4c", + "0xd9948dc162a681b4102d82d01faca492bbf057d2a0ab1ad1aa2d7ad2f5d8d591", + "0x6b911fe9fa1b430a1b7eaf963670cade7032466eccf1fddb6afa9954316c7378", + "0xe3453267f7c86550138eae575f5874fabb4df7cff52a9b7498281788d5be2df9", + "0xd1de756ee8b3e650137e2f1f81be3cef8389fa685a8c2606edce0f470c5b94e6", + "0xcd78d6840591a94a41b6c43486738e3f9537ca7fc529b73c77403e282eda5b05", + "0xb6107d17b47d368d236930768d2329917a155355a17c244e9b6a70df8b899d2a", + "0xeade2b36e555380abb2926f45a8809ae4bb9ca9fc4bc5c2848b08a6fc157ebb0", + "0x6e907d42d9292279e00b5e3791646cdad8bfc5802f02efe7a2bad8beadad3832", + "0xddc9d4963a1708e7114011f41b7003cbc351fd3cc6907638138f968aacfc2b3e", + "0xb9702fee4e5e00b451600c2f6479ff852f41cd760ddfedcaa9d42912d199da8d", + "0x6e0b2e6230e55b58b0caca85b86459fd94a17dd2427ed23ef4d7468e200b436f", + "0xf0965c9e876cc2cee03a67098bcc0bb8ff91c29d110101d05bdcb06e21a94eac", + "0x79902f46ccb4f63b07dd38c88a495b2837a0a984ccf4f2643bd817f353e947b0", + "0xcee76907124f92bda1e5e492de67fcb0e1900302f69682f5aab251e55ea7df0b", + "0x9df0c40c5e452168dd9debad103645074686e09110a50d205c8941d27d14f74e", + "0x4128d10935b67e5dc21e8e40e5c343fc4c4a716455abc0dad24578d4aabe402f", + "0x1b49733ff37e03ac5cfdb1f84a5d93beb0013dad0adf8ff4435b44b20dc0dfcd", + "0x31d0defb61c386a751690bdb4f32e6377ae2a761e52511e524ad9e69961fcd0a", + "0x438cdb21294f0547ffdf5269eb9099cf52c66e45aa235eade26636a13694c90f", + "0xff42d94f2f917a3c4ab43d4375a9bc63a396f3fd120f0295a4b6597e53815b44", + "0x6564791af7389ec58bf575435a3ff1e0d3ce0955c7dcc3b75cb4c85c1a1c8b46", + "0xcf988277bbaf273ae926cdcc57e88b9a2bd916a6d0edb1d7cd0a92cf85d98ad8", + "0x45b8aa768c9ed9d99a3b12cea4ebf803c458b908a65f014a779a79c3d31020c4", + "0x2d96dff93a3df327747c6a2c6e7c08612a9d40923207d8d6d52dccf33caf8661", + "0x9dad452c7da8aa798c9489ba142710769c03e5ca3701673649baf731edb41e4d", + "0x6418305ef9d02d3382450684eb222c9761e94b66a933d9ef8d833c08ad4c6b9d", + "0x1f58fc05ac706d32ff31ae9dbd533c1df2481b1976be571efe22f8810e7487dc", + "0xa9af008f96370a80f1034840d00e072a391d523065ababe94eac561005c02408", + "0xa0384a9854110164b17189b10c9b6ecb22718d515256d12189b4799c1b7460e8", + "0x17f88aa7eb0072037f2b6305a2859c8100a3e2c8dcb6e13d8b58e01abba31292", + "0xc834fc15604decfb4bbc68987f20efca8db47e1d3fbeab2a1f04bf2151b4366f", + "0xfb92c461809fbb8ac4abcab126229d5d25f5476d6f732d27ffc3e31e2db18e4a", + "0xfcb1cd8040e7bb860eeb20cad1575747c9ca129192c8aa69a9cd373e24b1825f", + "0xd8efbd48289db20663d5b087c678025a232fb83c4be1731468ad2f10f69afb8f", + "0xeb5c8eeb8c1e6bbc15df061c358ff7cb5e89e6e3ed51eb63805bb98f0121c683", + "0xaf9d7a05d1d1c3c9d03b008907b30762a435df18c754ed1fa27c9c84a8905953", + "0x06743818d15eccbc13397607121a89575a6da7f9d23e36b07911fcc516e4a9e1", + "0x32a05f9a1c08b68500074915f04daefd0a6835adc985558b62c3b2867109ff18", + "0x40e0b74757199b6863f97f14fbb394b2bf518ac06d8d499615dc087b2d105b89", + "0x09736a30759c20cfe24bc34a40aa85eb511a0f49021934d856588181969dad44", + "0x3dc24b923a7c9593ec6b77220c873a06420bd8f5ce2c2768364074457bc31cdb", + "0xa7e78dfbf9fff15ebd110198711b24f35dc7dc6cbed06b5008036570f4072abe", + "0xfc51a0ea5862e57dec45581827c35aacdc58c6dc410919b1b47e3ad3c707f630", + "0x1c5b2600a9cc29f7d3587a5aabf29b27e9f85acb99acff6a5316312a713d1f77", + "0x080a076a84bdc34236149a6ce92885c0b28d5484c80bc40b7207c45a1c2487fb", + "0x7fd2a3a08ecfdceeaa56952968836be5e8adabcc7a2a00e2629604db5efbc14a", + "0xd214eab26d637a7820a0babe4bca0ef9dadb0482b3847a71fae571f44cc93e33", + "0xbdc71731bd7440bee58f131d47db5c2d4ebe39bfbd9e2fcbb4970a7fedd631f6", + "0x617e379b135d0265b15679e464dc7fcbe696fb8afb64b6b74cde6fcaee043ac2", + "0x96ba4dd6b5bcba95f7d97f6bb3dbf6812825f5de86e12f14dbeac7041854d8db", + "0xef77cf072d0edbd8d5243ca73384a7c2e58cdc3cbcbc5f8895c65c62da30206c", + "0xe75c1cf441c9dd52a7185e3c1f1e6850fb03bc39d06d422da1ebc81afba7b910", + "0x5bad1ba4e6e0a7fa060cf8766bf8b3500adfcbcb922368da9225a36e61e7a469", + "0x1ded514f946945a7f04d26757ff39d9731d8bb28ae304d803bab9a484cf4cb8b", + "0x40a6f34a19594944e96bd5df119c1a06a2615c04924b7b8763c4d9d5c0b8363b", + "0xe0dcb9dc1ad2f5653c369d9f25d4f9058fb8c512e5efd208b814e9fd45540550", + "0x1a07a9808e43a3c473d1e9d2875ab32ec2eaf9ddec432f711554503f927582fb", + "0xc196ec42bc1603eaf0a2348dec8d850d96dd4c275bbd3de356e5a23519002018", + "0xc793895f8aa0e9ed1c22f0aca3b1cf07ad1bd69445d9eb5d51c453bdfdf0dc72", + "0x1f0312147d7bf69ab363ca3a3b9b5a0e43316d7e2c36be97fe0553d2d3225fe8", + "0x09d8080e41bce3b07fdabe7ab36d0f45880c0cdf5d2119930d61233d1d079751", + "0x5863676dae69ac932a7a463e93d312365f563a59acd4086d7c60b61d56438b28", + "0x5c9d57ed61a4994fdca105841fd91eebad100ea8704c9a12afe488103daa6177", + "0xec9c5ef3fe34be04465270a7a215848a00a31324562e97c3d94b7b799b6474e1", + "0x4ee12a6911ab23524291f800c361490221460ae9d72085ed69055126b3fac836", + "0xfc6be696f5c7687c511ba1fc8f4581c792e17876eb968bf5d1e7c6555259b98c", + "0x82ac807f85d8c430464c8fa8f6eadf6cedd5707e8b4aa653ac66f85dd39bd1b8", + "0x08ddb03882de2be4d7ae9165a41746fc76edadbaedaa6d8587c0560c5c989ac2", + "0x7f1e6e84f0ce5f9bdf199f579f4c57a8d35ca5b4bfde55d20e2d7c092e6249d8", + "0x7caa4b3f32f0608e86a112afb9425831ddb735bb5b914599a11355102de0ef65", + "0xc52c467d635c36695e1fe850976745926250b0bcbf12835ec344231e326e7bb9", + "0xd31f10dd9effe25dd19d3eda5863f452bd3dab36cad1cda545137aefe1971eab", + "0xe3c9f6858652e0eb2314c8019fb633a14716a3c130b767577b2a28ee7af0a581", + "0x39a476f8a5268f38e24775566403135d6cc26e46a7480eec576cf9036e96a9a3", + "0x78c798b3ef7f7054b427c22e2d6ec9ef54ad3edb12edcb43ed46fe63c624646c", + "0x2d9eb24d4922203e2d55292c4b5c983b86f56c23685a3a6d57af191c65a06db1", + "0x434d433a6316106fe94059d2fc0116b7181f13846df95892d78261322fa724a6", + "0x5bf38bcbc125fc6feead6a7cffbe6db1674a1d52f4a3f91a29833a730b711218", + "0x852f05410a45326c6118bd9ba185dae319464ff3c0a603a2ea02290646bc53b6", + "0x80db0d9f5a7f2e02f3c19c3553bd0e3151fab7f36f7d899f29770e9d440a8073", + "0xdaec85979550d9dbe8d86e665ecebfb2b055836f1691aac6d64d1379d0c39e7b", + "0x1d1b18c8b2bb47b70c276a0c32fa04a4d7f5b8646c28094422faf0e177bd1b8f", + "0xe248542589724264685768bb7108622542c2d6b2e4659e2fb97d17ef7256f1af", + "0xf095b4169b0e1d33b1c24f6ccb835f8d0d6af4581f4f34feaf96d6713d70ef65", + "0xc24267de7db63ee856dda7184d50cd71890ba7017602191c3bc44e2bb1a1d4d1", + "0x624dc6dc69c1484d7531688ddda389e0ca00dc09210429d6c97b17a0d4f4e9e4", + "0xef3610a3412574d14a7549c5e992ce9fd54772f820b9485c5689e135832692f4", + "0xca58354e960aee45575f4d5abd2ae9d7aff32a7b1bd0df6e3d0d22792030dadd", + "0xbf7b2f80533f34efbe4f6c6395fe8eff19e08c9d964e619e35bd161c4e08a70c", + "0x85482474a66dbff699ccc3756dee5fe88e447448d44fdf2627bd488cc8abe984", + "0xcc598f943c693fa06111c77f475bb528a08e859b2bc6f2871f4ae50eae40de4e", + "0xed41aa8bcb0330da03b360350601f68752dc060873c6f0fe53cdc4f3c8da662a", + "0x047b5d2a97a701b76115ce5b8d71bca40594d9e163752db3e38ed8c6b0448ecb", + "0xb2ff504219c1b24b1483a7e671809202713f9b2dc888d1b46df2878ef830a8bc", + "0x01038d50899f0167b59681287f6fac87cb53dbcf7b4992631809933afee11870", + "0x306c6b040960341a198c88b01bb0eb3e2eac36b483c343de16fb8cd6f318720f", + "0xfde3d4cf83046bcbf18e6a7df3857c9e1bb75f441a4265135837085262814b02", + "0xdaebb2b71d2443003e6efecdbcaff086d0d725c88684787110135bbd15291833", + "0xc0a0198a6e57544f119523402f97c084a1afbb06f0b4d2a41bea0434761b6054", + "0xdcce26167709e6cb4fd29584c83faffcf76c982c5e17726fe4dbd1105bab7439", + "0xad717a26abd29eeb240e986e635fc0add4a6f7c8c9ae116af49b2e81b4eb62a1", + "0x47d513873b8c72791867009b293b401b7ec05cf87dc9f9537581805768369d00", + "0x497839c4688753a5db5eb98e7968e9ef363ce85cb275d40c3dd46b6e5113c3a4", + "0x3aad7265aa7bb39710356bfc3e6c555725c357b323fc281b2763a0f0267c8b8d", + "0x36e21dcfab3aed1c7134789149da4d61b2fee5307f033013380b892065e14991", + "0xbbdedc8436db019fba5aff87ed3c97a78ec2af8b2aa390f1b0f925064604061c", + "0x8dbd104b838055f34d628ff1fbf097152483fe53e6d930ae4a02d37648b758d1", + "0x365e37d424fb7ef1048d0f032f75e7dca20465f0709a3994c6ee903b1818a726", + "0xfb32c65070bc2f46ad8d8378384adb8bc3dae96dd96a8914204c607ce601c3de", + "0x30fe50586990daf14e84ef2d337f0819faf98f0bff730c77c547d34c20ff14bc", + "0x8b2977d229646c3552e4e6a7657fc3372f0a9e744b4fa11edee9f5ffbab99e60", + "0xca3830b76e052f65833a3c8c31c98bcdf8d81f74952f5c4ba32ac8f4c3791d38", + "0x4a8a34bd2ebcbdd69e0492a9e784263b73db418f20f80ad6f1b3ea25702c3bc9", + "0xe9730415f60bcb2f412e676d768ec3e25af7d6439517497e7b8f86950e83b5c8", + "0x42fb83f3376821f23f3316d9d01ad319bbe6b6cefe1dea1c2cfe89639961e668", + "0xfcc901dd86c62e3b1da4af67bb1729b28ece9efbaabd086810151e908218920f", + "0x1a40ff9ada25ab7fc14832c33a3c75cd0595cb904eac7d7a521c67ce75db0dfd", + "0x690eebd8fdd05117d5a4c7335af0c487e4ba70c9352a8c03ae7c8c53963a82ca", + "0x47582399dbb91cacadaf022957b48abe25c7f301a1232587ac3f0298bf4f03b8", + "0x900fc815fba237e026a0f27de6af96dd1055351b7a78df050e8063e67a03c4ed", + "0x807880d09bd8ce9e27b2a7df7e22c46a3f28b81db767a08269006e27a776e0f7", + "0xda996478eb696f963ea50b28c899293f1682de5bc56297b7f14bdf64e35003d8", + "0x630a1fe703d16ec4eb67043ff86c2980a956bbc45961ab343059b449a58016c6", + "0xdddd65b35951ec094cf2c01e505b4545845bd4a1727dad0eed5592e3f91323d4", + "0x6d6b2560db0d26b56f0ec336215ab3ea430307aea23e94d11ebc7f8ae0476ebc", + "0x942d35f09119613dc505286bd8e5b692c5b6ab6b456bfde3bb5e60e6875d41ee", + "0x2336d4efeffd6e88b0bc6e7b2c1759b35a7147e8a441568d374deae1c2f9a964", + "0xde9da773da3969677a8171d1c20ab7cd5fbac9ac5eeb05e161dc3f62c5ca841a", + "0xd4f4fae337a4237f02e8620fbbf077c8d39864d543244f6ea7d08a68220838c8", + "0xcb59a0f2c5ab1feb68118a8c59aa873813a0adf65730f2e937814bec1e149151", + "0x256f444bbb37350ca565dd620b71b28ea15e53994f2eecb394a0881ffa42d575", + "0x5349078ec5fa82d5cedb4709ef0a2354208a7f85b37ef7054bb687ec8bac265c", + "0xe577d5e1dbd5819a83089c701a31df8ccfce478ef9655fb7aa21399745b5c59c", + "0x2fd29cfb8c1352cc78d930de9bbab8ef007d0541d8fd1a8db7cc5cced076dc04", + "0x6ff610d29ac82ac1a5b92ed47297c6213c90146df4d668985d9d157891e81a54", + "0x376e36ba81ac50e32e314bc8860af7624d31307d6af0b1951c7bb03ec2e4b0d0", + "0xc2af74f9c437ef0f7b89b0663d900a13e98c5da81aa5020404a665c211feabd3", + "0x4de6b756c071a6e93acc37ff7fe513c585667be3b64c186c6e45ba2b3d7ae131", + "0xa31a0bfe97be03ebffd4a7f0565ff4372d34b44aa9b9db8b3943cfe2049a25f3", + "0x2a4135dd0986c731ed35cb770389b8494adfd6fb9e323f8b3c62e612ce9ae7ca", + "0xc5a683d3880f1d34d515c753f0bdb68750984df456345a7649fbd3f723539ce7", + "0xc89381d12ff71c930dcb24deb043c3837e6f8c221d986babc9a37585a724adbe", + "0xabbea8d56c9095aec399d7188aa12c8542fdaacb2c25b440d112778c3c8b914d", + "0x9257be6dec259bf4650857f8b8ffccb42d6ef93e55127bc23596ec4ca543d63d", + "0x0acdfb858aa8dc8e693018c2fd5f1d9d0192138fe5fc461284b0f737edb857f4", + "0x8d9507c1f8c22256288db6bed77a16b09bf2e83748503e5d04bcb971c2f49bde", + "0xb5cba97b5e52ddba979b4e74b1a02cf0a423fe9232327ae80fd935d9b2923305", + "0x5634d57b4b9c7a5ed15aa70d59b102b628a0aa47a785f84466ba549b60e49706", + "0xc41bdbc86fcff5dc2a77cc6997b99e75927096c3d56baa56f385ca8df583f6a4", + "0x1b81a4e0f85fbe1520c00931736061fca9a08a8b7f7dd94a65b863817326a296", + "0x12d983159015d26986b0b673451fb362496530a550ae6137f92251f99db2b290", + "0xb6f0dec7ff4e61da0006c02164bea709ac4fe11c20257f154c6a2400acbeae6a", + "0x7b98792ba33a549d893727b0df38352c0262de5dd3f34716e59843bc2588eb4a", + "0x8d33bd97dfa8b29def7899dacd161ba8b52825c281611e5fe3abecad7e57c112", + "0xfb15e7a292a8df0e9c5bf0be2f97e30f81dedcf47c3035c49f0a124b0bc82a25", + "0x6e003471f1c803451676cb993c9d05fbf50d390b8774e4dc891c7a76bd6810f0", + "0x6a5291b1e97e6423545db5831efe391e030337da2a6f207f71484e59835ff627", + "0xa6ebdbc3a608f5cd3e8e6238626a52ee541ede98cc9a8133e7c3ae18c0dcb6d9", + "0xb1b60d7fa6f641156dac04c81d1b5fa640d6790239235345d19fec323abf5d70", + "0xcb21b419047253c8472675a31f71aa694fd2753cd53125f3eb33fc7cb2bc0d1d", + "0xca6444ed3205fb31e0ca9fd84809b725e99476428a7949bc1bbc27bda16e9eb3", + "0x86ee41c48989906e9f5444a4b0862b9e55cae62512f75d1cb6126ea79088a386", + "0xc3d9d6c407c7254854407004426a0edb3b6ea2a9e37f4b3646b0573070f5387e", + "0x52979e891b3479834488cf0da863d6fa051c3f5fefaee825ae8f605db7a4bc56", + "0xc3921490107cacd64b454ce5cf113e868d32b786c00a5582930e5dc93a24ebe9", + "0x4b393efe4ee6de87a9ea89b81d7e5851f2c2d660cde41d22fa1a6e8c8d0fdb31", + "0x2c5b85643df44155127113d73c6c7a30d32e81dfb974ad18b676b82e911cb6fe", + "0x55b84b4c5cf71bbd5fcd9c9bc5130f7b0b70828ec142e9980a1f8e6aee36d0eb", + "0xdbb9f30584c3548de0bba916766ebfea6eaeac0efdbb81e9cdf7403138890115", + "0x85aeaaf7baee871ca9949025ad5b28fd704f0b1d4b4bc702fbf2f197463cacf7", + "0x976056b44f1af84778b80657a52779e4ebae64606253fc2e5502b1b8fc3da207", + "0x3647ad36808ee65e944f785f96eeb53182c0c6300893656901cbd59c30c6aaf6", + "0x159e33c4c437853e340c93bfd494dd4bfad9336e6ce4b55c4b488438672efb22", + "0xcb07707c4f0ce2ad6e62be5e3d9f7ee256ca7e767078a70860f7a11d86d1f969", + "0xd89a699a681bfb1d98e349747faf9b77b2733652ff252800d11a1c5e42c45805", + "0x66487f37ad00673178dfb2785ae9daf32bc6cbc5025e18c6791fe562e4ffb880", + "0x5314e684aa9d1c10297945dbd2258ad847c67c9855d3f3c1ed5a1121650c647d", + "0x5be3a4672b03615e7e2e980d0c68851cbae4753bfaec77f69d62fbc3f69f6a80", + "0x9d59c9afd57f37f565675c8730494238a7ad62a26026adc8c644274e615c8973", + "0x76c06d84cfd419b2465339e377186f316f0231c91999d2069f965350923a2ba9", + "0x677364bbe63180f825bd178974047c40d98e28e48ac2e43ef23f9f863aa4ae09", + "0x90a7f396716df1e03cfddd6c91a3acdadbdf761d7868403d1ebe2affc68a41d4", + "0x44af61cb5be5bf4cee207c7e2c3fdd4951c98385c530a2af8a41e96b18e60ca7", + "0x010d2f7fbdc7d82c47b33d66a5f3b8d2d86255df3a27c37ab44b1ad192ed344b", + "0x4b66f935d07a0cd83f0dce67e9cb7338cac9c343763af39fd4d5317b0e223d31", + "0x95788a4c1ad664283ce7c5e986aa45ffcc3f3ff78342765c0a0537359795cede", + "0x1d0cc84b5bcddada93d89a0c8165e0f62975e2e3f42be87cac48e286e8a58593", + "0x383c470137b4b3c0d5442bd5ffcebff656a0f6f93d8316f97ffa2530446c9a17", + "0x8f85d0673e9ee21c9d74cc3a5e286fd9fcbfbad8a67312bd9fdef4a84604ecbb", + "0x856f549c4bfe8c101e61f5f6907294b186c467b53bf1e5a365ae4c1058688b53", + "0xa02863faa09cc7e8b7d467a1e49aee2740fc72eded6b372566f7f24d39d98c61", + "0x6cc6b1d8eec2d925730f5b0d7a53a7ec5501e75bbe532d01ccf9ee4fbf04f2d9", + "0xa101c9828116728e738096a5bf3693e4c6034567280cf79f301e9331e8c0da20", + "0x08a8d10878ea9f75e586eed72d9972d961e0bae3fb18cdb59b97f13d4573e937", + "0xbe05d30470150602f7d2e7f880bcca34260abd3004f00176454275f1f5ba12b6", + "0x2293224a8b616daf818331ba7ca2984eba091d7fd2c5c021ce1ab8891d1d02d5", + "0xffd50a8a3afdfe098a5f7d8a4df1d98989c6f2154910801b44df299f3a9ca970", + "0xb2bc8f78673c10a805d2a02eca6ecff625108acabbdc1f0c083ae738a6bf80e3", + "0xd3d7800d9ad71590207b86ce8be28af5d3b844451d26335843345235adb33482", + "0x19a2050c8fafc25c023fc874645146c9d69e58cfa62c55d6fa6e414acc7230ef", + "0x1607618728cf21588549167c963f4decc154c39b9ca7535e4ae2898424a5b9d0", + "0x77ad7d04df11bf2568b6b4a43a859fd0c41019e3fc3622011af8bfdc9f2fab39", + "0x8a2f2bdb426c94200183bed7500ef3a5645a936b2b69de6607d5e0809735f3f7", + "0xd31e090eff9d737da218d052287c7bc575eba68e4c04c61afc1bf71fa1294d46", + "0x929e93fc4bba1d6824585e9c63c00b142aa010954d2659557aa2abf020aaa754", + "0xfdc40de28666194855d21df5466739de17b8569a6416cf8e06e6a5f923cbbc9d", + "0xcf47393b9ef0fb5f68c4203c01cb52acb6d3a7633dada6ef171fdc5f70ae3e4c", + "0xd8c41ec1d0a78a2310a1e9a10d69017f91fd73c95ba26743d118f989d29d6f6d", + "0x31c3e809f24ce309488c611bbc62fde0394852c627502be078bba6e4a345d5e9", + "0x4f3ef90c7a078e74d707cfe628d9cc23d2e592b25727f25ef875cc7926f7b58f", + "0x53dd78267af64a3c11157bc09f4c16603bef5423b46a736b3baa082029d409d9", + "0x2c8e9f60300fcddb98d044686dfdc94fb34df87b0088873eae57540d07446f64", + "0x7100344f97940317ff6df6a5bc8e22bafcce7aaf46c8621c2dd0f6bcc3b6898d", + "0x8958726b7851035b1ea0f5889ff74280ad428912b5273752b9e13c627411f4a7", + "0x6ef0d28e7a2e2faa51cc8e06bf00a4ff182977a14a3f45ab71a02869d21cc9db", + "0xbb703737301efe6a34ea929b205de1536fb1aa5819def94ff5cc56e872b3e825", + "0x69614a352941e7e09adfabb909bb9619232cef1ce8866abf0a4c43eb0a255a48", + "0xfad7b1630f6ac59bb9819cb0e33c93838d44cbf9182f598ce4bfabb416153aeb", + "0x2a4c80b6f28493e4fc78ba4b604c927a80d8152aa13e6bbe3cd5487354ca5451", + "0x88c56bbeadf8e475f8476663c308678c5bd7f5673fbf20a154b478ba0a83993e", + "0xe7265c624cdf5bb984c24466035e418a8ed08e5db12e76dbde40287d11dde5e3", + "0xddc2c7e6d23361d39cf3bd6af4b8125ac1f2d32e68f725d77144ed14d19a4ac6", + "0x8adc4525b31039f9d6b7fe2ce7948ebb389ad0fe1b2d0d9ba0675101377483da", + "0x92104f08380fada7c0cac602e66c4d754e703829f9272e126241262fdf7423b9", + "0xe7ad92563a04b8ddc6aa93079a456339c5e631b5e00274b4512d16b28fcaa0ea", + "0x05e51bbff3db812ec3e64f34bc4ca899345b69d7511d25d2b8c05a6f73ba91f0", + "0xbddf31021ebe16aac248f3167d34fb9fa00b885c0e859a1aed26f866379b4762", + "0x87d4a8d3a89be7d5eb725a472c7105451d796ac2e8d41c7089c4604b0908dd3f", + "0x2f01e7b47dd42062a2ec8e4961fbcc8db7ff6575cc82751afa362b6ad21e6907", + "0x8aa4b672c4a537b8c8cadc5900b15c87def5cbbf585760fd080c6369894bedfc", + "0x795a0298b19a0e660a41cbc7c772872f95739e56e95f3b48c6520a5c5e55eee0", + "0x10d0342907960372382e5c3a7ec2dac0e6f5c2bf5f6b57ad548a31f9fe11c249", + "0x073b3efb41e2e904a4e83e01a1b1b34e7b6bb082f41e4f76aa38b55de5d84a2c", + "0x12a10cb67c7337e71aaa7f79829fc0abebcfdd3077ded20de0460e100a1b6604", + "0xd76ad354d8ca67f0b7b33e9a87d5b8c3e9aeb190b160c01562976edfd341691a", + "0x0b0129b4a178efb5cd71bc65ae4e8288ac76449c39b2827284a8a59a53a8b04b", + "0xc9702a1ceaaa255e2c7db468857d47f08538280f704e595270b3d1801905c33d", + "0x67b6eeff27327be016b742cad1297b0a02459e4e5c1b1e16e15932a18698691a", + "0xfa25b1e7d3233021414f61158758dd1721838d41113866cbc763051f16417966", + "0x51af765c6a8b3aa1537da71d29a9bce4ec6a3beb83eb2451bac170d307635ea6", + "0xa93dedcdc389d03b011add42daa6b1aa4c77065b776e8ed2de3bad78afbc1c8f", + "0x278a468d7e1da09d9b5d017f180bf14e48825f9ad09f4238114f4746a5c29168", + "0x8969a4c15171d04fc703d8377b03ec827ee8c29803eae6692ae52d31eb18e055", + "0x69fd35b051fa7a280c6c0abbf340c572f6022c614bdd3acddc89cb0495c5c75d", + "0x2f148c2bf404ffb3041043444c5e589656571f42ff6b101f2f03b4afbc3c1051", + "0x24913a97dc2244e58f154efee2b772f4dfc8bfc41899c66b2cfcb49b5bf9970c", + "0xf8aa8972332906671779ed9639ff4092629758028d02f77529d56a9c89140915", + "0x78c99dc9c7f1d356ffcd80cdde5559c8742e3186b293ebad19f5f5c2ab172949", + "0xab301f68fc9ea59de054f4a14102e5d1ba312416870141319bd846ad804bf9ee", + "0xe0d75a30786e55aa94fdfade60676c098664d4bbda32f01467535b25f8eb2a7c", + "0x6a55d687db9a48b19fe238bd249fa58d7d963ebd156c32bc366f8d65a71526b9", + "0xb640570971229244b145c01474ee04a685a40bb51758a4d68310b4ce63ccabfc", + "0x1fcc3851ea21fb8ab94445b36830318b896edccd64c2d54a3001e198f639ab0a", + "0x70504f1c582a0f3e7d6d8ca8fe82cfbdd69b606cc000d34ddcbe0cd841cd9eaf", + "0x6fcd5480b8e6ae07f38c891d4202402fce91c3144f380abb041dc4cb61485380", + "0xcd817e8ea14464d8a65643d32a4ca07badf0330e96c9e3b4835e982ef2e32667", + "0xe6f62abe81088e3ba52c653b7d748352ac6248a8d1a0dc61a63a13b39f3adb3e", + "0x61a0b71216d09ce57e739a0690c7c833ab74a41cdc7c0a136a5a261da5d5606e", + "0xa5cb275a9a6ab6a127a2ebf6afee6d6d3ed802ab4728ab3ff7ac12f4050a69dc", + "0x97b3c2da2b3a9110705929bfb299b69f9e6d3c05cfc391dc43b339f6994c49e3", + "0x273ca1ea98412abc4d162eec30d669072ca8e59c24ebc17d7b74dd42721b1e06", + "0x392f8b4e7d706a08828684d868acccd647e781219f97477cad4e4755d5feda93", + "0xf3b821c71d040e10e515418a21f73a3ef0ef855cdafa99240e60dba2816e5cea", + "0xe527f8c605a625031c7dc74793ee6d1b1554cf9d5d344347a4a2bf5b6824f059", + "0xbc5e66d951bef421db1595db40e3638a2b8f253a8387bd4d43ded54c4c0846f6", + "0x7fcdc1fe31f1891fcd82c2eea392274adfb26ebcd7ee915b484d0c272838d2a4", + "0x58b7888f6776e36d6c065b3f8de88ec8de76f224ac0f15dedaddc36351ced36c", + "0xbf5037084ff4124e311de573330f6e482621e06df744c1086977e6c7465521f6", + "0xb76efd283b00b528fee1857ff599fbeda6a7ea648c62b37590dc9a1f8f872e5b", + "0xd2a86a75f25cae510761c30a843069e889d5caad4fb45cdc1f0caa80c32481e2", + "0x5fa32d5dbb1887ecf3b93aa544496b8d7af7aaa2242ea50ec96cc5c07da31c00", + "0x8c6894e707d014dc7a2639f07101fb1164ceff5687b3ea1af014e63318113c52", + "0x018a3d80bb4ea6edd284f6146918c905cc3c1c754e9694cb04c6e939e2c3e8f3", + "0x763a1742e8f9e998fcb5f0e5ccf9bf1c0c58a299075ceed7b273e5155ebd7a66", + "0xeec702dcfdef81a97fbc330f028427a5ec979081c3ea6499ef1f0c36fca59c8e", + "0x18ec0a483c6bc0ef114a9ce6f4dc609ca66167d6715b32720938a180889a6ffd", + "0x5a948e7fdc5150ef90985ec51c833ba144efa1cba509124273492a4597ab5923", + "0xe88fee3b7ce1ad4a6dc608a3a5a8412945290c97371959c740eb3ca74c65d254", + "0x2dbc9f004a225f235b5710f22f0f2c77c75455869c50c311a5617e4b795a353d", + "0x3d402479e699d0317ef4b93cab54df4a62d183e628c5b105455fe66c90c73e9e", + "0xc9f150ed85090f0df6b7939a9ad1496208e920fd927728d739fbe5357511b56f", + "0x8c34fe488619a0d70ec30c41eb3f9008ffe47f9c188e63461a6a1448660cfcb0", + "0x1f2db08ab9b278038c3dd9c36b2d279d71000758748cf089283dff7d04e937c7", + "0x98cb2dd0ca201bf90725b6efb8dccbb6d05776b6833ac780aa14fc44e901df3e", + "0x0d0b8e72e7834f89638a466420fbe3e2ab5e2893b7d9c8c84394caef0c45a468", + "0xc054cfc39bfedb31b8c7949b2ac1bd6a07b36c62020188ad336c6039efe1032a", + "0x8f25593a99b7667087b329a8f69535db5c695abd92fc16eea39322e28a5a7577", + "0xd38c37dd354a85a0a2279a87a6f2742e0f5c7aa61085ce608b9bd8eadd7201d5", + "0xe38245a68b4746d911097fc0bdbd0094673f8ec345d789b77850330063dbb9b7", + "0x35a08b8b3d7e4852812693b611e69972fb8c66853bc3b06d6efbcce14117ebaa", + "0xed25487bff2f3aa0db580f6f6579e0fb30f2bfa72de70e3c480d3d77ce393093", + "0xe88653f85db98d947ffa42a789eb9fad86abb4048df4df70dd4b1f94b8726ddb", + "0x500343b55dc6a2a74bea48858dc8dde4a091b9120782d57a9807f1db21ef9a19", + "0x356340a610fff9b3999ba7c20e2fe65500f5defdc8852b4320223649d7591627", + "0xf59edb887df597825e2c68d7f8e8e58320acfd46a31c904c58f38c4084488a95", + "0x8f94067314834a0dbeba084049c6f4508038238795bf45bf623bbdb8eb2cfecc", + "0xd255abad0c2f585bc88bc9db4211cb34353764af1121e0f75709670be507e946", + "0x3914fc87ce6cc781590078758aa3330449de03c6479bd5996ffe1ca533b7ea1d", + "0xdafbeafb230e2e8b44f963026475acc1e7260e7de6e817b7ba9f0340f6c27f50", + "0x7fb53cd64dd1045eb4efc6fb24d4b609db52bb342529783de0b4e44b5b3d3b81", + "0xca94b25fad418cf1eb161a6a3d269b8e3e2224ca95d7d79e903c1c77ee14a020", + "0x7980f221287a1574111ebbe83bf8c5aa443a93e3ff95f5d51da3026cf6606a9c", + "0x3e103b573e171ac4bc2d19ec450d8ab74c696f1b2cb444975a612a8b3f4f5ee9", + "0x45a7beb63386b87bc180332345f0f08eff981871555a5bea3265c312641fda00", + "0x3a779223233d6ed94bc336dffa268cdae36367c7f08a8b0204ce2d79521b707c", + "0xa9763a8dec8ae703b006f71f6b83a034794a91649878b6bf752d55aad4acfbaf", + "0x654869da214419be4d42aaa1f8964a867f24f5db590ac4823ef13c278e7dcfa9", + "0x3698360e59cd6586b0242b8a30e28f9ac0b20996f24607a0e3826ffb743011da", + "0x85a6b0319f93315c1a90d5b44ba88985e1d628c6bde9c370f7bc5e4ff21c05fd", + "0x3f6c395956cf1646cd0d29daaa38c04348808f1d4b4ab9b10fc982fe7f7859d5", + "0x382629e494c41827cd2aa72222335ac3a30eeebe4b4aa96c46c7b7d030cbcc90", + "0x1bcd92ac47810169deecf5ba89398ccfce61bce2575758a0ab4a2c8f85058422", + "0xd0b960c59bf7ee3f06f26d6ad1bf16d0800338f495573a18a264146e5d1a68e5", + "0xfeada9fbcec6d22a9a7e3b0e643257a1c6c827d53553997571afd49eb80c4bc1", + "0x647bdf6ab4a88731217f8610b57c98daacd424d89325c6bd0f2b1a090a7bf527", + "0xb67c9cda2ceae27f1a59b38215067f902bfbb8adedd10a3379dde408eeed0a5c", + "0xeab82329a4d0f75125ece37caa4cb4e3c2a65f9fb39722d28f9567fd09a94dfa", + "0xdd94ff13aeb4191c18446ebdcd1d2449824386b081ebcc056f8f2d8972b0b105", + "0xc9319c95ccac9755526ec36a88d6384f288087f994d66e3e00759b9981652d0d", + "0x0b4cf4f195c7227ebc79cc647cbcf90d852cfa4cc1cc6a305fde8ae870b637c3", + "0x25a7434a908f27b204eff7221d4c3deca22c20331c5aa650a1455c863fa6b422", + "0x2bddd823ea545f3aca6b2fa00a3a2c83dd358eb4cc4cc40b1cc7ae4167bf0f78", + "0x18adf129bd6f7bccf32f1b5ff4cf8d855f17093a4eec217aacc4e0c96e6e06ff", + "0xe0a2c9da78d9fcde12fb306b339eff25b9f29699cf292e59ac50c5553a744b46", + "0xcbaf7f6c3d2af021e9780fa1fe40eb2126e7aec616537fa5d2746404a5753ab7", + "0x8826d7342fa3469ee3ade0d9b169542d5cefcb0edfef48e14c320bc97adcf24a", + "0x6274f27b101ee6f88299b222ad630e3bca648d86ca9f1a6e96fb811656dbebf5", + "0x1811856349dc02b06179e224fa22fee284d367674339407f1af8afc2d4940491", + "0xd8dbaca1f92be6c60dd3637d812f27f82b5a29adada0cc07f36257add080c3b8", + "0xa861c65b35da72c78d5948f433def655288ce2d3fa2c314de9ddab022b0c2833", + "0x19621786ddee5d87bca26828ab9ce5dafd613d2443f2469d87a2764875c64d53", + "0x62c927df988349a637fab53cee5ae65c81bbcfa6bc9bdb4723e7bbfb81760489", + "0xbd07c71513a8d04aa90a2ad6c2bbcb320cb0cc03ca104c2aabd7dc5d49cf7873", + "0x7bc71b4726da12ca677435e46dae08b7bfb2c2a8f3a3c5b98aedbf35bcf06e4c", + "0x858a08cb660417f9c32218d9e1cd0698d60b40b25e185f62373f7747eadc1a79", + "0x8962c42bd8fba724ddad94d51776bbac5a77fb98a68d7993a0c01fb83da6bd9c", + "0xa52f685230c3ae71cdaefc5758a66273ede8c4be2dc3525f911d42a5fda2de45", + "0x62153ab8a4a28289e73bde016a4fe58811cd02e5d659cd9f577c3611493eec63", + "0xa30e5e6005b1a0d9d4b7e86f7203a8139c26c729509469b3f8050b03bc39ca10", + "0x5ce8d37d13cb9a4d32db0b907f035b29ed39b59522e8485d1e4495bb3dfc1572", + "0x67719bbd7f98e2869713bd54329da3e3733f411b29a1193db3fc4398c8505ef3", + "0x00f2dbf1944283fe0f820c499c52a4ead45c5393f30455a28a2e7fa06dddfdf6", + "0x6b6526b0c31b074ff0712dcc57167dd50483dbd7250c64a2d93e126c7dbd10bb", + "0x36eea96f8dec2bc06f364dcb217264187b4541ee750fb8d8fecc1b2126a52a64", + "0xed6890d6723ed588fe2710cb30561aa92c788e3931c6baf1ded01bf9793422e1", + "0x5ba666ce9f3a0cfbb7b1bb7a309066164d4acee27fc19fd565ff55b0611bd04c", + "0x6e2a394127418f2825a8fde981198256797ab14608373bddf13a71062ce3e4f2", + "0x72f4b4f67f06f76b5fab3295a7e56e0f7b7e4185fb383807005a74ec01ddc50c", + "0x0dd58d0c0eddcde1173a19b9a4f6ffa8ca7f400e2300d0af3722f41f0c9b3f52", + "0xfa7118a28e8ef78bc0156a6a2fcba9e81544c91fba55c325ec4794fe012e20b2", + "0xc49f629ec1453253928a8eb4bb5cf74f0f0442d86d0d84a7dd0cdb99d03b3a71", + "0xfebc1806fb5560b28bc14b704febef947911904bcb665fee2cdeed790855466e", + "0x6dc18cb8f447987b1a80c1f4795de09e144e12407edca405dbcc288ac719e94c", + "0xa35b1a31d28f990ea63ed366caae0f75871076d22357cc66a87a999a6e09e127", + "0xe186aba91e09aeaa77f470cc71bf8bc6b18560d69b399df8ead5fb63989a3b82", + "0xb352ec9a9cd2d2ae801dd10bf737588e4620a4d6c636455d33124aa1e5361400", + "0xb12c148effd6855c73c44a78dd9f939c7e687fd44f522277ae4a1f93f53d26dd", + "0xb86482d56ee61d400cc8d9a38224b8ff94a6c9beab33a6edca746e5f0b8f6dcf", + "0xa6dff0601988221497746ede4a09c19d5a7a62737b0f40349a6c24e8ceb1a469", + "0x837e26990d18a624aa08b87e97d608e7f4b75a99fc57a77d130f1c44d417b1aa", + "0xee1bd06e75e4930f67c75358f64e43de6d854e7add62b8d802574ad808690903", + "0xc0f1b5145d241a642bf06baf7dfc49949df0c10afbd8e8560a6d06be3b760b19", + "0xef4cabe0abdb9273e38dbb9e09a63c0d1193bca951d82332d45d01f260fe8717", + "0x4cf2bfeb5beced066e4b7f79615091a2f81e50bac5c8c2d9ed2ef2ac888d86a6", + "0x9ce4c946df64447b7ad033bc7b5f8a62ad50df16853784b8cca241ad5191bcff", + "0xdb5fa1651fdde9cf52b418c2b070ddbee097136327f6b818b8bd41840fa8f920", + "0x45f69323d4e6c4294b382019053ad089572cffc3839f3fc8ac1f9924a0edea32", + "0xb686d73075b45237319c2ff2f743fc2a6f60dc0dddbbe6f414daf712ed6796ca", + "0x34750b64a414231766d84ea92a374932d885d95a18be77d5d16d1b94efb048ee", + "0x6beaa04579373acb926103909f7c03ced095df81ca87452e6d69535dee549eb1", + "0x50830466f05d582254340f6ee211d4432cd4020d4be1cb7830141bec8cad8481", + "0x5c9c21a5a614cf3cff7afe70e35fdabee67c8e90782ef0cdb774d909de3d1509", + "0xf0f07c550a8e6b939fb24ea1de8ce1571e8d6c329421e8a3c897d94ef3198b45", + "0x70c0a4c9b70e9653fdf91c7020a5118b727322702aadd318809ce083ac646aba", + "0x0cde06c1b9d6f5c0b895fbccbd8edc839d9bc21af4bd206f3f4c1a28f7e849c7", + "0xd3ea6feba310996dfa1a6e4e10eb1c4c4edc0fe0d3825553deb601979da10fd2", + "0x7ae5715186b00b86b0aecef3b0d487c96f4cdb4a94711f2237ecc185a29013eb", + "0x1b2828b6d94ea3e2ecd3ae0b417339148710af02a5054f256c217b67f8f55fcc", + "0xcdeac54edecef790a8c212d86c45ee9e097927a04ebdb13891e5b94370e200fc", + "0x9869b5fcf70766bbf76223cae9ca3b8e3ed7e01c065f475f29fd5eca977816a3", + "0xb80fdcce699c4c07b0265f35467da77977c33a558b215b0b9211105b6cb2eb97", + "0xd5d9a3f5d8d9faead565d5de6fd5be3d5a85621c09f49bd3ed7217d59e63ef42", + "0x226531c505bddf99730a2bbad5a84856f3ebf64833368ef14626b331ae882046", + "0xfe6a0ff6492f8e2d0f27785a71aae65868c7b7278f45ac9c13031c6933e5ff58", + "0xf0d19b703b6e7aa0873ce3a64d77fd4dab6553ab6ef5c8db4ccb360d381e4ec3", + "0x1a6379ca31f6704f9643c2944c38c4894150029be5953205e09a5c49d5a83666", + "0x5dd3e7414ac5b924e9d9431d4f69e87901bd066045d6bd0583e92104265a99cb", + "0x7417614538f404ab719354131664f75a5565934fdb35fe2b329a034d052aefab", + "0xbdde0aa58fe227c3a8e01f0d3ed21bfb13145c551cb3b75cee85f0e62c52825b", + "0x25b1b36e72306d5de03b22c4f4a99c94c67b1d7275fa7346ebc990feafa95819", + "0xddbad1f32840a3155a3a17e4710d770b0d0c8d4b9c959b434da223b66882f8c1", + "0x4ecc783780b225cfceeeefa44dfcb4863e4377946511cbebf730b77857ae1379", + "0xfd15b7b9b6240bea86a898d11cfe6d3fa8623e416857910bd9b4213331c4276b", + "0xf710711f4f26da985803eaeb05c5b07e4147e5ddcf61f400a3cbd141299ace37", + "0xc9b5c5012c4f380ff6b25bfd1b46dc97fbf71d0cd25a7eaf799ac5f7dd3f2b18", + "0xe6a1cc39b7dbd7c2a5ba211960422d65b87fda2f38d2dc309f06250f7b8a686a", + "0x19556445cac490ab941f7a43e65ed8856d59bcefd50f15862ecb2e14840c9d04", + "0x8a7fc62d190322fa9fd9a2a70937ad05fe89160b9cca33ad287fb6c24fd0eb32", + "0x9aa81f8a637bca3e0c43cb0d961dd5fe175a3c1d8417a61fe059447dc27dde9c", + "0xe45922992cb23f9b60bd5f3e3687d7c68f39ade4976aa17791d880a2f0068198", + "0x6b4d46adddc2335abe24e9f969b094a0495264607906191b38e0a176e9e280d2", + "0xf5bad7f048acd435c6d0017165ecd85b376fe9e264523b186c3439787fc7126f", + "0xe6029636af0630d9d84718419c0d540cd6738237cc3c5138b189af530bc65e7c", + "0x5f93c70bec8a8cd6f5de0d7d929d70a978d1dce3fc693fc6a8954fd0c2c0e739", + "0xa7aa14a7b0b6773c552eb1b8aa66451e4b368e51d6711902f932e80a7d54fb76", + "0xb48effcbb7bf47c28a17318971a9ee671ed249ac1932c86b1748715d78fb5419", + "0x38fcb78dfa98a0d2bcbd6e883a19d8d8a8db86e9f021b9fd25f5a309b3e91375", + "0xa16e055ffcedb90aaaea09441c16c94aa90beeecdce9f90888e45e7915e49115", + "0x4d536f2bd58b252a36b77738fb4b6ec932d914d27c343a77c3a87e2b37cac722", + "0x7f8e944dffdd1d797cfb1c9484f757f9860f61bdf5bc369d4ec26b740109ec0e", + "0xb86ec6ea0e69c1928fbe009e5fe1da9c938c36581b97130474a1fda44a1bd294", + "0x268d430425915224ec7453fc7113eeddabf368a6e60c00af6af4d46147a5d434", + "0xf2f2a68002878abe219f5a1f1a13bb2b2e84dd2d39c685e2868068c4b613ce11", + "0x691a1eb375b6b4e66c3dee0f03c15a847716a4a76f561f4742f7a7774925f6a3", + "0x1e13e49ce69ca70e4bbd74b020daa2851d96ded8279deaedc846339739eb790c", + "0x058ece03bb6385a48ea9eca0e35e5853ab040c6ca5ba372b2045b0597b426f55", + "0x2f2b782b6bce115d03df9c13c6a7adb7413531ee9568dbd9655bbe5ab6b06141", + "0xae45abdd224d09b9a05a4503cfda3d2e24db0cb597d370e9b5d5da2e37111525", + "0x3c51f84f818ee4ec36e79e3c42abaf50973bfdeed693f6d0f42a2b8c097723a1", + "0x642d6459728b8d6036beed800d20d59280b8d5ea2e210677ed04a5e7973fc1a2", + "0xfd9ec30b1a0d27c8217e3bceb75aa545e659609ebc144b6e4a23fca1d5e90d35", + "0x75e0526f30a2c6c6ca9add64d1c3ca20ff988f22db1e6fbdbeb4dc982bc8f0e8", + "0x1f13605cb2f94d3c8743c8ad3eda5bf7b2a6d3c1c117945744aee8b8ca3289cf", + "0xa62c5d59536a4dd61c0403f85be6f247421549ea7b251e44c21b010a3ae4a76a", + "0xce13aa4fe702750ae5561cbc6f2bcbe8b0d979f7d1751c80d48fafe85b9125ff", + "0x4c34c6c651fb179649b65ee60f93ed64a2ca11f6699e06f9e8e8087e60f81a3d", + "0x53a18b307f80340116beca13bbb10b05c7fb6d65cc4bae466aeb0d40d9da74db", + "0x62897236794db02fdb58a255f08c7abd253f2885134e64ecbbcd1a2e20154705", + "0x996a4c7e9143b80e5767fa637d5370b94591ee336e0f23def3d83f7bad0950d9", + "0xf7e28bd31a3f39a93ccd647030680f970a358bcb84e7a555dc16c6cedfedfe22", + "0x54793ae31a612c9d3d4480b110fe2d2603484db28336459606f672bb0e01390f", + "0x9635672405c8519bba38c1a046f309958d3ee84ca9cce5722146725bf2ef933e", + "0xbd69316d6df7de8a3191030317505d4c4cb6ca8ff5bfd2fa517b76329b912fe4", + "0x3cbe0d66905ae6da05163c24ea90012b8c3acae38fa277f2d8c0e7547a9d7410", + "0x7de8ffaca8d51bb4e59ac89e4b45668c1065996374537204a57870494304bb38", + "0xec1e60f536cd00ee2eb039c48f2100f86743e20e9e8911fae2afbc27d03212d6", + "0x643275d0c81982562e1168553ddf03756d6a813ad92981140879f886133d7203", + "0xfa9a2ec8e05caac288b5fad60462e47fdc64d7b15a0a7f09032431195fbf6e92", + "0x69413e7a6027e5d92d2288b5f028b9aeaf028c3926c779432ed15fac245d19a7", + "0xef20cfc76f417979ce7077c979576bb534f5d5bc5d052af9311cd3cd4d2175e5", + "0x6e560ad9ca9d868231be72819523df157459ee5cce76fbe643e9498369b3e585", + "0xe7739c40398901cd392e091c3a89eefcde07f9bf8e9ee7fda288e3ab24e199ce", + "0x3ff97067449cc13213dab1a46bb66a69997ff1d18efc13d22673145eea8420d8", + "0x1c8b79f893de6e0b46c6f624b1976b47de4ad1568dcd90486dc8283f570bea04", + "0x9fd5f70a4b995d6507e6a42b48ab18f94ac1623e81a147b40c2455ac7ec5ad85", + "0x69373e6e19f7128556c1f21660ea17556e02a530c10bbcfb2de5627fd8e07b9e", + "0xacdbf097f72170bc86f923b172cc4315a8e81cde71b034e2f8fcb9d6752938f1", + "0xbbe3ef5451e45de728039133ee6447b9c2c605aed3a8f808d547ce0412a84a51", + "0xce506260a6f1a254d233e3b32246ba6b0d5ed91d384f55d1253a28bba8534c09", + "0x0a9d69289d09eb6b010640e7e79256d585d73e3dd6a09701c5a8aeb80148e3c3", + "0xaea8a91738082e2038f741b2b66e763ee4490db3e219e7a13e573adc54574d59", + "0x954fc41b9313524ef8584d96fc74b8f81dbb5ca23d7997498716250cfce8d4be", + "0xcc551b51b81be31d97868efa1335801e393b595cd9e4b303d3746bee55869f16", + "0x77797967766e311fcf5d4a3e89a08a7def1b3561346e3f7815b20ed609d505d0", + "0xd2ca2e8da6be2144ce29093e936a59079d9063f887335e7344a2515a8f0827d6", + "0xba3c00208b678c67d753904474b980e77ee05935633697933cae0feadd4ffcb3", + "0xa9f0edc2d5e83dd6b3f6a8fa6cb24f5a11e290e9cb0f671e8dfbfb66e338ac5b", + "0x7f4944b4fb1fed2b17011748925d7d3d88c6a4bfe3331d03da00cd2303afe9c1", + "0xf8961b65f1d6d7be13006a64bc4094d57a6b44ca314b6cc136172e434ebebb50", + "0x4f51ef2c609c7d26d4323cd169dfeb667a841d646a8174830a34370d869c8c71", + "0xa45c68290713fb2c841916ea5b2b9bd32f3fd1c004328b99ce07fde9ada41710", + "0x3623a5202ffa0877e3f5050afd668810e725415c6ebe3003b866ae80c54590d1", + "0x688b978803343067b7004c81f391f8e32bbe6a729289ee2d34bb2cfb86611342", + "0xca75d366a63824765081bdec6292e4605607b1a7580451eadf72efde7135906e", + "0x19ee65d9a8ee8246ae0f0f3c769ecc7b2ad30763872c10a48d502514b30c46ce", + "0xbb08f5f21189afd3bb2049b05d0e6486ba7c2f06ffd968ff7c81cb0071ad672d", + "0x9abdd1d768e82aa8ea6e33178ba898f8295679c6a27c13063b15688720354919", + "0xe6092e5410ad28586c919c8b28cc213ad00d98f356863cf18182532386e4b615", + "0x22ecfe7c8a242323151b1232d30264cdaebbc3540f9ebd91b7ed5b79305293c9", + "0xb88a824d760f95bb0849c1039ec0d55b0a5685f414e53006b918742f4ae29266", + "0x02766f872ed3b29b795d6276beed7bc06f900de45d2333b07776f05d4aa958bc", + "0xa7c8fcfe9b14231731b904f255b56038b711ca83928c86e7224d8930f3aff9c3", + "0x7f992f4b04e56a4d7e63339e5647dba19a7686253f23b17300e238fb7dbaf020", + "0x66df9c89dd28454097f8d3c1c74db2f770b1dc2ac30b77fa6935efb12e16b1d7", + "0xa61ee0699ef1f5e541f1dc14117dbc210d9f36987ac5094394f5987f6bfcc1e6", + "0x2c45e5dc2953619d479810eedb7ca9ee5154ac9f78d639efc05c61e6c60ceb8a", + "0x762c10a410896623963ee11e20cc0ff22aa3a190d7c6ae92ff8071ed2d772624", + "0xab87f1244ba144a65d19dc78fc21d9a096e81bfeca1a4ca81c245d72d91137cf", + "0xa25d89d0591fcc9599acd434a65c3c56beab1602cec01160b1ea4a83bd7a980b", + "0x47ebd358245683f93f0ca6aba8a68dded9926ea691b08fa74757065af6d5d74a", + "0xa0ced4565fd4da621b5fa8793a527dfb87f2ac0577a7e4d7c1130ba2824b56d8", + "0x53a4c9bb0de061ff05bb41356f89d7776164ef279609c0579e0bb60d46f7a1da", + "0xdb16dd0810092b27e08ea9d58ffa0dc2ab9e0244f038ebb789aeb1910ccb1d50", + "0xc0f2f502541a18fc1237bd03b704cc40e0795005b18ef174ad05580588c83767", + "0x94252514f5049544c1a1f9424940d9ad00628fe879222195e7e943418719126a", + "0xd8b3bbd5dffa897a5f0899246cee2159befa2717c38a42a0019bbe3079d44312", + "0xc9218c6b8a4e717d044a4a25e0faeaae12a822bebf8047a22964dbe9ea7fa58b", + "0xe5e9a54f1f97724ccbec0ab1b660de4373134fdef6566723d25f80100e11cd39", + "0x68a65e4b75b51fc1db5549b95dc302498e76fd7ab360624d39ed847dc0ff870f", + "0x9224d78122627202226721b229cfaee68e61ba965ebbe244b5f31af820cdea06", + "0x24f4ab3878d24b7a290bf841b4e7172b7c8ffc05ca7d610b36424275640fa75b", + "0xafafd828658c92c1bf7f0fe6852d278e35661723a0fb8371afa6d7c79f886e8d", + "0xad3cca1c6bcb850b2c44064817f31575d48c56ac214f55a1134f907c495e2a32", + "0x98cc755ad41cd8c7984b103a920fefa77a208b5739d3a14c58d4829f925d975a", + "0xc99b328941a669e0095023db31ed38a45757a0a3eb4f7ef32cec80f0cd354c95", + "0x7c616e1f233cc33555d6f5f43884e385c3af408a586e32ebd52253f1f376ce38", + "0xded9c6184a8f2e426555d10ba5157612056ee4caad0d78b9575d5f3cc5d2a04a", + "0xcb1a955d0dff31d0b2164932d7f3e41e0bc033d353fb80bac5b931ac2b22a5b3", + "0xacb110c37539a77c5bedf5f116274839182d44f5ba45b52a08a0d87575d3a228", + "0xfa9151e46b2fae374129f5592e2350f40ebe194dbe14403cc0dfe1153cefd964", + "0x43982605d335a36b1a46e6dc072240ab39050219e4f241666d4c88a96f480a7d", + "0x2364261ec4ff16a55ddc406d50c1343e439ef9d4ac29d52c0582c95b796013e9", + "0x173bfe3a62c88d2df9793dc247b09d379027224c4287fbe6bc2c7c8d624fd86b", + "0x9573d72cf4be5158a7039ddf51074bbdf912cf044130cebc6369e20c0fdb9594", + "0x1c74b9c52d285c62684fd3c7e58c402be0ba4b6b0a7e50a67401b3020f5bc57e", + "0x21b4c16200f7312b91c3afdf72c99f57a1a28754c0b3fa9420ccd79230eb0175", + "0x28987ce9d2d35bf51a5b1e9fdfe5ac9676a3b7ea0175c89ec84edfa66fcf1ad4", + "0x8e0c39870ca2944a19a399648f16776066726c54a86391579f6ab72b7ec0d47e", + "0xb9de199f2be5ea32384a74c56b06393c51685aec5e52eb8360e8e2b5a32c892d", + "0x9b8156716b03f820ef52f12a68229e716f2c2c1017e08c3b7e77be97c6d0d4dc", + "0x68c5259cee376134bf35ce33ce5729e059fc1052e7c134d1bfeb19c9b9acd0c7", + "0x7a3876b9ac278cfbcdd4830880ef438a430cc830d78f6cc005eb4781380522a7", + "0xa487271258604ee7dec9a306177d5216536f9d62ba20dfd057d60f046b8e4f74", + "0x7f5bd998d4ea80cc0830bbbc0f1b015a198e1d48e58fb03427e45d7e1d805e6f", + "0x680280c7ea2419d4c9e909aba9c469e8ed7829e69a8101b1205df69edf6493ca", + "0x403ecfd702230060d50d1473a243d91738e7df75c4f76c9fc8359a1eb1e866e2", + "0x59fed28f3f4783b297b66a7254eb2a089f082534ca12e8e39243b527cec98c6b", + "0xe05f2b55e5a9180fda374df06b3ad23063950b5e91a3e8745802ce0dc3ffe1e6", + "0x9b266d0df4cb0bd394ca42108e6167d4bc2bd56717ffaa467126cbedc2edf17b", + "0x49ad1b4b721dc959b911767980557a70ba8c616ea5cef04c2aa82dd4b7b4fab6", + "0x584440e213b2551c6ad58ab9e36e707f892888fcc14b15ff789d1084ed0f9a29", + "0x679fcc5e202da23085560424a550b0027f3954a98c47ad80ad2baba5f0e8f3f4", + "0xbcee5d17f10c56fc1bb2cf1b011f76232b6b90d09517213868822e573c8f90c1", + "0x783e66e42aad8192058086573b8babc38951813ab42e97c52738e8ca6fbe8798", + "0x56108248a8d19a507bcfb1d34dcbe52dea56bcfe39bca5fa100501beb6539fee", + "0xd487860b420b5cd5f6e30783cb122dafd8f95f8cb490fb41d7413ba242b50927", + "0x6cb932740f9ca018fa81068501b073572b59094e08c2ba40dd1fac3b9736a0f2", + "0x9213b4cd1d643ad6e6dd78ecc50901c3504f3228bc38480d4e2d80a835d7da84", + "0xb9827c89e2c4ded0193f841d1d93ba9a50c125b165b6cc578ebbb59e1c1e3c2f", + "0x4a60fbbd3d4cdd3a5afaacabb91d9907b54f24cc2c0b472a102ebbc04c6e1d5e", + "0xc34e850a8ba61ccdddc521b6c78889e8f44cf842ad051312842b727478b0dd48", + "0x428440624d658328e7f71e2b244f6ec1d76f00bcfd38ee1a6505041909dd9a3c", + "0x86187fe09c6da9685ddf29a8c707a8b8c07dee71af385570a9f7688dade56860", + "0xeaf224bd9a1646e0936a58ec76bea3f3c15b0905ddc1e42a65d916790696f804", + "0xa0323441bb548307f09abf7c633c0939af2ba068d330177702017865126fe665", + "0xbaae7f994479b34cc6c3a187ce69f769314e4b16cc75d8db676cd471539cb8b9", + "0xd6a97586d7d492d4eb7d4207438d3b260927913040e665b04dc16fac1790b7aa", + "0x93958dcf84bae3ac5abbcf8d663b512bd4698e52729622ecb110387004b3278f", + "0x726ebcb9f4402bcc67749b9bf0e898d6884a34bb88dc42bcaba0928b99de1ce4", + "0x7023076f7ec758a3e7cd7084938e54aa4dad0733c6f7ce5bd3f9316671afb41d", + "0x7cb1c651811bb0af1a5a20072295422f10108dff1792df72fa7300b228d24a30", + "0xc67142637f2d4e57e87562d3eb21d1c9f00743393b8741e2a48cb9c1e7c92501", + "0x3d1ece56ece2a5a8f9ad8bc6489fb9e7d4cda7aca8e9cf787a55e44d40c0eb08", + "0x222a3adca2d078165e2a23f7f5b9ae308ef2d1ec5df16e54c1d523b6f12c9c49", + "0x8e3eddb190424b16d955ef2a352fa69d0c3c91406903e20fc93baa163c448494", + "0x08d24146ee54b8685ac2bfbb67b2fc2d7da0c8cc1b31343cf83e36a076d588ea", + "0x029b75327ea0a6607c83b834ae5afb64fe7870d0e65f0411f4c0011d1bd304bf", + "0x51df1dace22285f5e23451d54f792df6b7dc901b15140e0227b883fde1bae7bc", + "0xc3cab27d73a2321c525e584a726f1c2ad950dcbab18be2c1f7a4e299c8c3a2cf", + "0x432581bd4637fec04aac93de42524f33f2cba4621f78a8405a2b41a4dd18a2f3", + "0xd0557870826a74c353e934ab21e08e35081ff7879f8b323e2c9ebeb23e3e3bf4", + "0x31fbf4768d13bd4ba011c0adfa7ec2182485444299797cf7d51bac3c2445c6a7", + "0x2c17643506d7fd5eff17b207aaf55e51b9cc67c2784db80b9f135a52625c3323", + "0x1f581185e5f13fb76ba2f381f37c1498400ec61578e5d562519a1fb7247b66c7", + "0xaa843b8dc6968a5fb88de5979d4883dd05bf23ddbf076d148547941ac5cd4e26", + "0x650486edb00e65b08acfc08e7d4ad89a9d1237463512af6aff53c7daf16a1725", + "0x234ac9fce1857f817601764d452ac136ae3f89d9f3fd5ef4253120faea881de4", + "0xf568041a9ee5d4ffcc8187e9d6149f282a4d329f1516d408ab6106aaadae74bd", + "0x3ff2bdb830235072ea6545663a12174a17a2f5efa070568d63a734cd70c3361d", + "0xd3678c705a33a9932e625164726fa3dbcb3fad8835fde4675223acaca58b6c58", + "0xe865e21f5e13042da52a933d94e447b90cd93c7b2acb0d9abe223ea5aa268214", + "0x14fff852295e2a1c907aa54b3472c88293df8b51ab2192292709bc92585d5b06", + "0x8a48c21de13833a70b1f91128ddc9819ddcab4cbacef213b0ee63a72d0c87f47", + "0xcb0925187bb428b7742600ccb0692612b49ac9c6ac289055cc668be17d0aad07", + "0xcd9555b8791abcaa3b670328e82ce9c9cc265241d49cd1c77c167b4abe48f3ee", + "0xd2c33c47d9890500febad6a4e2b78a9740917d47a228b3d10948483274cd4b5b", + "0x7861de7794ab5d325fe5b78ed99413dc5976d541555a0304f39be7d1302d99b1", + "0x3a3e2432c3bd72c53d8ed99ab60b5e1a53218fc08ea62f315d05da7766da5b15", + "0x6905579f8ac0193e528b0f86cbd679ff4155e32b8a6fb4a1a0cdbda543dfb81d", + "0x5f0e4686fd7c5ac11413571e716b03dde138c444606d44244ce4d3bab2916107", + "0xb1627edd75717823e0824e3e3689dec2dae9692c91a611d5afdc08779d65cdd0", + "0xed51b24152f2595ae3200f4aeabe1a72c2c996f7574db1e072fed52ec531775a", + "0x4202fe9aa1fbcd3cacf8c1ca8c616a531a1c13b63578925c3fadf66cd02fb62a", + "0x3875a92a2a1fdcdc0fea135aeb6bcce59cce6a493037dbd9ca3c19f6d96cbb6e", + "0xc865ea4be94423d94a6b84cc9f31cd5eca878e461d433ae3275512e442c910bf", + "0xf28c5b3dcc1f343561953f64ec545c89ced8b509c396d1812ca19e2041a17055", + "0x7cbbdd412cfb0b140a1e121cec554a418818bc17f80c1df69a2b43228c37f82c", + "0x1ad7f4a3431f8d2e5670ca885797b7eedc9d5ec04577e79a81406c2e503d0431", + "0x76f07c15d91f17028356f09f4407c020b5b9548f3c8e5cd2de0b37989091f298", + "0x75382bb178f190aae8dc02d266e9fc07b2e4faba551e619c0434682439e0269d", + "0x2b564f0a6e8eb4f829cd70ad7d97f379bec1d2326508e155b8d8252b9c2a305b", + "0x8418bf6714467d26e8341aaea2ca1442cf34d86fbbcd7c3e63da0e895d8b29a7", + "0x5a17e1b9ad15058155679d701e90f92989b75f12f02c7568dc31cfd8659d25a1", + "0xb21f76fb217213c6457654149dab85b87305fe3bf83b1805791c8dc2376e1268", + "0xf3ea43ffcdd0302c11fcae3551982e90af2f748b9ccec50b04e8435327cfbe99", + "0x4fef91b730cbedaed0049e0dc36bf14360256dd2449e3e925178cc46d3156697", + "0xec7074e2607bd5e0f228af7b73c7e39aad72d17019c2afffc3ab647d78939f61", + "0x53f34be1711c68f9a765da967c60fa39b72df4778e8ca7967404492f7a353910", + "0x6f0492df8bae724540b7a1462371edd74c4863c2c8cb6915a86545a36f06f77a", + "0x35898b077c19c49dbdd9415a6c3365636e9a8e98e0760d8b537ca12d5329c9b3", + "0x1a1c020207e42587d674c1275673584f0e239e8c1f2b4f6d8c98c97338bc182a", + "0xc46a3a7d6be035fa17a55b963030326d25c01542f4ec5cec431c012e5ac6d52d", + "0x0b29f6f0e29310a49fcbf18c8783d1dcee2997a62cc19e9c20ab524e6bcccd89", + "0x4b6a5d044ea31f51124c3b8f4c4a58eb9e7c922444d7ceafc76e9767ec2927a6", + "0x003e2e364412086eeee06b7eab2489e258aee32adf9c8700b3e33cbe8c594d7c", + "0xb1713dbc4a35cb1b3f4484eadc891d745dd5584f97012ccd5164f5662bf12c57", + "0xaed111e5b0ba48c69b8b765c11d74e5554fb0655d29ee73f8d38a52071bdac1c", + "0xe7d15702135fc0b830c65f60f74ef407291a634610b39d1dd6538b18f238654b", + "0x30d7bd4e83df5535c96391a6e4bd46d4081437db2911f8cba7ec40d3d626da37", + "0xb659fe1e992a428c553596567583c5aa42a297eaa3fc5a73b2705b03eee588e2", + "0x7174740915226124623dda7ccbe6a559246b8162cf5cc942ed4d1adf7ba86c06", + "0xf2847d813669654e775dff15b5484fb78f940a61f170021f0e74e5b0c4ddabb2", + "0x1acf93e0e1d6af4c48ee251766ef1bb2492fc25f94471265b940fba3ad55819b", + "0x3a8946be87b92d13f5668a3d48b8258c6c8d585c008d5a42ff460ef14a3ac6d9", + "0x104838e64202e4a90e8e8659f0508012e6aac3d75ad48be54fce69c1b536cc65", + "0xd80fa0b84016cfc95a15f4b01d50ecf4b06c7affff144ba226b24674b4a7b96b", + "0xe67240364fceb1d0b730e15e03aa92e1d88aac5c064da3a9225533ec3f7a3cee", + "0x74924dd757f836abaf12789a0f241dba89a42f310282f3e126fd88c96184f299", + "0x2998899e920039c7d933217e35af122b0e22d8fb8de987d5a607d31cd29d2f03", + "0x7e103626c39bf10a4b8eef446d6266994c5f841748307031f70aa23a27565a45", + "0x16446aff8ffb1ddb6894a7f62fa813d7c92c8ad77a797f388c9102055bd34524", + "0x8bae81870b92e523bdce4153102a4c46a660fa36e40ff0228043efc956adeeaa", + "0x0d5e765b9a18172b9a374782f22c3f7b1d5c8191c5b85f99539fe4728a8221eb", + "0xe256bd6c4c35dd174b2119941bcf44af1919616987b3fd3f2d2c67a56c0cb727", + "0x515b83d93a92b76b4d341b75c5b087509045451cd4c97c4d8f753f606df4048c", + "0xed27094e0e5a132112ea97fb3e870080b8a79c0b24e874c7f93dcad5b5a5928f", + "0x549b8ad126d1256023759a2e2258b35faec200d467baca8c37fb616c845977f3", + "0xea971d1ebe07c22175addaa244ecc91b2412bada3e72b5c437300f34c3ba07bf", + "0x3a892e84b04f593005861047dc80db8291fa6bcd064079b377034c9f68ddde20", + "0x7bbd6284646d4668a09ed02df281cc9e0d8f668ed1170df627e5469fb1892037", + "0xce47a83c1c1239e1457b46356719f525efb37a5a60a2e5acc135afb784acf00e", + "0x7d023404e05a3bbdd246b45d6af0af6cecf6366798ba49f220d5335d3baaedf3", + "0x5e4f0a84c2ea318e7711dbaed10bb0941799d4f7f5cc1042af3635c4c43369bb", + "0xf20c0ef0af68d2cf69e09e241b0211c32264875aadf5483677e53e221ca90573", + "0x77ba703780e366b14f7ea143c2319911c97397fb2a35f4cbff1486f276c483b4", + "0x1dd840bfb6128f00c5239c3164375ea008ea7bf5dc953c144f3971c72fa13050", + "0x0ca150e42d75dafe6437aa92ce4bc59557a7baa8eee01697b78b2bf889ddee4b", + "0x470142189b056c2962e3169f119ac26b43579a91aa27c61354ec283f88c4d205", + "0x61d1b32df70db397fda56f0035968f9d3d2bfd2fe1c3e7ee3dd65ead896be04d", + "0x4cbb9a330c46cbe61c2242813d01e4b9d96c9024c82a817d4b4c7118f30dac5f", + "0x8252357b329a1e68a32c75310704b51974b750062567aa88adc165c185a0633d", + "0x9d3aaeea1952351c07167400958033ec5136e884ebacc52b829b51459746326a", + "0x7a3abb411568a0b5b40909bbf547d5c39c53e839ccd68a86fcdf015ca52ecd0e", + "0xb51056fd9332adc740bcb96d7132c749abf02f1e281d676c451904f3efa38320", + "0x89d4bdebd8b6619a5d6609cd37c4ee4fc544df7a86c75d5f026a065a5053d7ad", + "0x7bfd3be6e1d68dad69c38855b80b289dece0a79ee4b9c6d0dd36cd4eb20fc401", + "0x0ddd4151934060f65f7fbcb7fdb2a617aee279367d4085e10674b16d8a5e4426", + "0x65ee7d3d96e335b086c4f6f5b8e5a93b4d0054f3f264c666acd39bdb86781ff2", + "0x79eda3ff5ecb743404c332e9c8710fe2c22e8233568e27b98e5e13021c0446a0", + "0x117ebf4d1e01bae39b6f95b66d95e057160d2177d24d26d628e5642b83250efd", + "0x29c35bf3a4cd0fcfc685dd5ef82bb23a539bdfa06907e10966829ef2c56d8854", + "0xb30ec9f98ec0cec48714d80d6322ac6badb4d0293c3beea4540da8f1115e0e9f", + "0x9d0ec950a87bb27eccea63196e9c4be8b91ee8cb8f14d58309c317124c8875cf", + "0xc3b5819646075f997c2fd4f79b7e7805440c1ae294dded722ddb22ee7fd7a099", + "0x098cd76c6dabdd013f588a48c75336631af0d14ed3b7748d12c85a7e0e93a313", + "0xe01ccb6a5f21f3c2a1c3761e7700ee64b7ed6192aac8b3f0e160f7b9d3bd0ac1", + "0x6ab889153a958cb336577c13db174174813360284c8f4609409ef57b7240565d", + "0xdf67e4ef6e11e4f52c052820d005d857c0eca882878b0a71bee7f22bdc629d53", + "0xc60703dda6612fbbcd3ba479f28c169b2049d3ab1f597c558149bc062d19313c", + "0x6e749f8217a0a51a926c88060c8d349ccd85d387c802c40b20cb87f51586df1d", + "0xf29fbc40017a9bbfea1c28a74c3063af72a510f9c99c0e981c3fc9d83ddc5bcd", + "0x76cc861f436ee8a3f1c07b644842ed5457563812f60756edaa4927a047ecfc43", + "0x84e7eadae3bfb61d67e53e00aa45449f04bcb50e215835687d63665d6bb7df63", + "0x8deb4b71040ffa0c5cde5675af9b8f9f4982a88bd01981258e871073e19c759b", + "0x3a7ac758caa8e2def1d290c066fad3d7daf68ebdb7f1d5b5230b3c94262315e1", + "0x9319124b08501ed1b53e06290face78c0f7b201fc8f812f59b469f6fd30581aa", + "0xa2855c6f26e090daf60fd17c4bcb771fd5611b9e1413136a3fd21eea2be7a3b2", + "0x82ed06497f1bef352cf027589d608b622569559d29f3cdf652f68cbbfb684c19", + "0x74321929990b5436cdd6e0953bee4fd5bc02f84e19c9a3bfb40addac61fda88d", + "0x47d4b298d5335cdfa6d09c16cf23cb98bfa4672a0fbafdd784590cb705f14daa", + "0x3d7863b734e1ce7d3a7bb0c955704106649890b4d673e744b8aaf8ffed36be6f", + "0x14abd96e4b25c3583df37755c51e384087f639fd5ebdec4fdd50d49017cb90db", + "0xbad65145878c7c313373306d6321256f8bbbd06cf58126f79c356e7ceb6d0301", + "0xc1f71b60be43810973082ae2a0c690e738992a3613b7c8286eea6b211b1b459e", + "0x1d18d20cc0279a7ef9921859fd3d0fdcacd66ee295f0e5bf6812346fe54a014f", + "0xbe49d176e2855dce010fe941b6098d6ef74e271ea846644072b6e508bc239044", + "0x828eb859148f295e5a0b2ba813b43caff82afbf32946e0bb211a6034b93ebfe5", + "0x7402137aa16d58ebad277698c5412c5b756796150594de6ca0f392b04b7848f8", + "0x58c83c4de55a8a562642bbd571d4c23a8847f8bd14e99401680337e474c05fb7", + "0x213aeb2dd7b400827c08dd326699edb7c5d1dc2d10f2f7cd43f4f3363b3a053a", + "0x7c4b1c80296fc55182b032ce8786473d56688777b4603313f990685e6512bb02", + "0x5857ef59c14c702bca8c358b55a2a67291064849e320363f484fe6552d8a4ed7", + "0xc4f927602edf49bd2f50c993bc27ebdae82192ab786a734679b6208b9d0c480f", + "0xf5756d9aa1f0f203011b0fdc18279ec476cd24e9fe3393e870326a4922c8b6f6", + "0xd3d892f6f4ce7862ea7b47995f8e80264f460792682632f8bd2cb01c67570181", + "0x347baa7431a293543af9c144f83b2b8d8103118c81420d61eadea1820903e9e2", + "0x01ab0e1aca21b0875155eaa8eb561ee417127a3afcfdb93dd6a0971e410ebd35", + "0x7c72ced65914db2173b71ce0e3f3ddd08f1dac47bcaae0f9083b164058d5c056", + "0x77a88cd8f15083f876b0f6f928fc4effcd877c837fc2fdb58be16f8172cc7784", + "0xb40653715c8da901293838858c2173213ee3a49d9e85619686f2e2c2ab839c6b", + "0x5d3f9e2521cdc44f2effd25d56778790464ea1ad23d141e93a30bfda7157c9ab", + "0x3e0beddf45d506c7c6c25f5478074d54d7f28f627a8df2eda5db1543dd1e834a", + "0xee28b0e24ca590a5a1655ec6415c1f57dda0183d6b542501d1e964dc61ea3d6b", + "0x3932f898858fb695d39a02c641eed26246be0754b7cedaf91518ee8a2b051fca", + "0xd9f7788a59b6d6e43748e1f1abf8060bd23555fcc5c9b4987977de0641f28fc6", + "0xd5297bfa280857285d58a24f591fa5a7c4b575fe7318cb531a445d24136ebac4", + "0xcae4abea8b7698ae9e55d133a676b5cd611698492fdf0f7d24ae3decd7d1a389", + "0x0aa0ff5bd3e0056d6663bd54ca7663aa2bbea781bfea228a4467f1d0192a7a94", + "0xfc872737974fef46448fab89d5811a61d8758aeec65b20c03a006a98e3754edc", + "0xbe60d4cb85ddd60c07bb1584456852bc36b72cedcd63d5c9b302a09b14cf1bdf", + "0x755aa31ceb9213270dd40124315d413cb053474ed4a60253a5d6dbac512c7744", + "0xb970b237d42706d556c9571b87466457d6e2de4d63fb405c9c7fe3420f35839e", + "0x977e976fa982e2a5ead22edd3dbaedad3e6ae885f00c0f48b4555c63802ee930", + "0xb4db2e220ff78e7a91cfd2cc31140f27d45b2043cd5147e9ddb9fee77c57a5e2", + "0x063e555581897db6caadd7a1c3a1a2a87719f729b0f43b9da7cc86460237cbad", + "0x4405a8f586646aa49d47073bac9c864c7346119a977cc5a154aa6ad70a50f894", + "0x87e09cc5759cc1b358d20955f97ff0e403c31a06d1f6cc6dc96f51a80570db40", + "0x432c4d29b6908bfdcbf466e3ea1cc93b64a6160748d4940ae6f95b45a804916d", + "0x64d99506de841b4b8e741f021be26327fe9d7ed2e4f0f635dd4043b7b174fd26", + "0xfd40a7dcd533928a2ee74ff589ae38231b84e72d7528e90a8c904d8762e07c4c", + "0x907626552f68f88c36192023bada749a6666f9a0b295f58c2e77515baa1e6a2b", + "0xee4c1ea1d8bca82456345d114085f34485bc44ef62aa60a4a74d7c2a0a681e90", + "0x81c59a12b3c1ff323be43f0d9d1fcaba87edbb344493ee1c426cb814b7e11509", + "0x11ac288f0d0dd1bbcfb335081a0ba30a74b6690b0dfb6290312b99450f257448", + "0x82194511f886f7f93b8b243401c34f80afdbfb5a78774b71a4334de6128c7a94", + "0x29f7f0319e09462e906ee0175dd3c10b09600a896cc909e2c0669a90642059ca", + "0x5f747311bd625822725d2d665a3ae4e3d39d0476bab0b4ab4d314b034bb4b581", + "0x82d29ecdbb2b66248fabe328ce0f441c904b0935f0c572fd860b22cef7037e29", + "0xb1ae4eac81c4df41cd26df2dc365a09696eaffb0bea906d3a24921666298f3db", + "0xab305997885a76e7adebc357c78149ab13191eac73807d6bbcf189ec24447eca", + "0xb93e7ee92ceda5b17d5923e967817c84239ae3dfc4f932f28f4ff12e3bba4b25", + "0xdcbea5c2455d6bd4c01ac3da32108436a11d8095af5d02382c12e9adf64ea941", + "0x379af62a4cbc14781860bced0eba058b58167966d5ae31a9545e80eeb8d63207", + "0x61e403db38f76e0d93baeab28958999670da2a94c489502bd2e3b2dc14049e64", + "0xaf921bc1dc0550891d487a700625147493f3a2521545f0c8e2b479578bf5469c", + "0xf18e89c738315e1e071a7595b3e78f142d5e97e6b55b8bacd2de3cd66f5d44c9", + "0xafdad2f30f695ef2e7a959b3c2189e27bf99e161e62bdfb2aa2c6a2cb38f4a33", + "0xbf17fe640225f213c991e813d23e532f5b28425d5e0505442522e7752c916d40", + "0x75a408cbad5625e898f00272476660c2638392103edecf964e17af303d35c67b", + "0x5069c2e3c907e243d4128b4d47e9738273f5f8c2b230b2172ab53787179a66a1", + "0xfb05bd9d9025de9c9b9c1d618f7e3b965b78ef6c05933ea01600e0dde4c920de", + "0x0348dd9d08fc716d85e68ce68508f7565daaae39ff9cfd1242bdb7be4ca9eadb", + "0x356e5fbcfda0909e6881beaf83310addf858aa5c26987eaf6226bec120035557", + "0x2c86f13922af8b1d58416b1fe079176167ee91df9a494396f13c1961b71b1826", + "0x58b5511b329949547f268318f4105580adfff4f25769e50e418bc9a418ea4494", + "0x3115256a0d6e2991da187eb0af2060a4bdb8afc5af246d9399b7cd5861520dcc", + "0x9512ff6fe3a05d2d322286a1ba4eee64c2bf00d7b868b98000cafedfb0f7c963", + "0xe0a81678dd4ce59096b25a2d1d0e56c3610de0b2044655813192f97b36e71f42", + "0x9a796aaf1293ff33270ca51338eb3eb4a180b37a9a6e8e960c310de6cf885f11", + "0x4fcdd484426e7c1311a334b8250f700579b4a62604a4ebd158a1263ab47e1253", + "0x52ffcff66546b02f93ecf999bf048f0e8bd80616e0560984b65c7f946dbd33db", + "0x10b276984aad9404c37747daf9afb88478894e44a38f33f645f9da1f165192d5", + "0xee534544d636177fa1974cdf8f038d807653d7f4841a3f1cdedd39e7fd58fb07", + "0x18ebf306aeab781847e0c3da286ca9fd3cfa5acb3b68cc8f0b96cc271bb5172e", + "0x994e4471831fefd58bb7ba9e03c36cc1449b03841f03dbe9fab64fb2084c5a54", + "0xca6c753d0d81b8b693d7ebb550e4d2718b495f22739930957fb17cbc15cd869c", + "0x351225ff4d086375ed5fac1c0ae4c6cf31752f8e65b8088447d006887f00a42a", + "0x4773707163e4797efec803c6b85afbf8875e789b3257df2b33358774d8971a0e", + "0x6424bf0fa6621a2fb9c166ee73750058fe733ebfd2fff232fac6bc73b55e6357", + "0xa5c1f44a899f63c1450f8ad09055fdf96ef84220fad238727ba0b04d4d6a3754", + "0x2b03c1dbf99334ea961cd71a89d66fe760dfe87817b4880b34b5a9e85c2dd917", + "0x6b13ade490bb62ec4276e334ae01628eaf41dcd7e773a1c13b25810535c4f4b2", + "0x7719de48b8d8c359f0159c87e6fd1dfce479bb886e4b002512c4a3cc2ea6bd05", + "0xed248d16dc7f1ec4f2c7c162149622109fbdf7dc68d1ccbeb90472813684e36e", + "0x2469f1bbaa3a55609ed6d005293b9d332feef0fedb660f3b09734687b48ed88b", + "0xe40e469aea7e30348e37b7c2459954ba02a4968fb713cea60c4bf9fcdd3bbc8d", + "0x66555b4b6a22f8252c71ab1f044f3ffd6474b88bb62fcc55216dfd94f457c916", + "0xf9c6bc9f84e7d0c31db16b7bcd54954427b4b43abb3af59ed122239c2b9f1d07", + "0x5d0471159044b364f1c26fe60154ee5cbbcd87a3c9d5b1fe86b5990f1c095dcb", + "0xda4d4cc6682bf9e162921107d9b6959a0fdbb779067ed659bb5140876527add3", + "0x7025c5eab4bbb5c5a0c8a7e6b845af8c9c3d02ef962e68bc0d0ab8862e2c3562", + "0x6c49e64964290c82a76c34a204bb445a0a00d68853900097325ba2c0c2ca5900", + "0x00e005674c684df70927a02e34cf1dc29bb341730abb46c89a764cc82f4a798a", + "0x3ce484b749d7f4c1b998f50bc10758871fcf426c8d70271c023b0fc45107554f", + "0x76900e52ff88ff356bdf3fcfd22613e064078fec47702a8760d85ddb592111d6", + "0xfc4979821c684ffe76894b18686e80fb3b67c8c317a22d3d25644421ace52acb", + "0xf226c6dfdd8a4d2a1ce8254b16d4ef99c48085fdade102aacb883d3e56e41a06", + "0xf858bca588f24f7efece3e03303ead92f66612723a0f68b6d1a871634974b8fb", + "0x672c9adb58bea50dd89e5d41196c93f4ee712c65681c918a971ac2afca43557b", + "0x1ebfba17221b1b101ab5119477cebb8fa6c2f72b9e282564dcbefdc8aca27688", + "0xec5ec768be531c250cb18850b92217ab32e6b8b9c080d4396f4e03518d328986", + "0xe12f9d598479d2462e429f4e3e249f676b383e51edfdf7ec6006dc23775e1372", + "0x93831b7cf4cc14676927d3aef0ed451dc1cea97945774d397b0588cc06be33c6", + "0xc5548136a5ad06f9a92ff95739223bce42a6bc19a92fbab0dcafcd9a4fae9511", + "0x7f6d793bf0692dd27327e1644cecd04d2dc0269c500ac192b504fa0b415fc23c", + "0xc389a64653eb7f37a0101cb3a2f989bbf03f0f6e07810883843199a33b5c8688", + "0xafd6cba91cc7041ea560ae01f5178828c8b934f349f1f87f6a22a6bd4b68b2d6", + "0xddaa7e0081eb38fcfa889e04af7703bac86baaa0f40aede815da9376657122ec", + "0x3b7c7dd378b00dfa18fc416fe471bfb07ce82c113591e4d1f2ba742409788302", + "0x22152aceee8ac16057189e13f89d118c5555d1061c6276634177071c4e85f4fd", + "0x82bbc14bc483184e2eea54bea9f105d69dee2ffd8d598a181e9894f0c0419e3b", + "0xd9b019cf461627e2142b04ef8cd394f14ef76c3abeb8de18b24e4ed9451bdd2c", + "0x93f6304908849980c14193a9a28b1976193263962bb85c18c45ec0e4c98c7dd3", + "0xd117cd674d8649fff979ed3e20bb63ad3a0bc7395d9428a8f7bd10171f5793b1", + "0x58f9a406c5c1cda4207f4f21def9118b4711ea39d8b93786f03458e5f32b144c", + "0x0120c549d680bf513e54793ad1794e34fd1748897e9b04d57ff8f1f3638dc926", + "0x5340b317835453c590fd71b022f4c984ecdc7e77f63ae694d50531a2cd8874e0", + "0x0a15038665e01f512ae7f9a5eb5d94600192470fe84b4fcc30e43d13a2c820b2", + "0x74815b0ae52ab519317e97cccc47e0b29a3e811451454adf7dbe2e5917497109", + "0x9221b6625678681475dec3689d5aaaa73e1098fda3786a72e04e04591a79c91e", + "0x7f7e9a8e73f9319020ea8ea7186c097910ad88979e1885a37989e1950e4a6c21", + "0x331f70cebd073b64bd396a96084de6da235b99eb18e9b3a608f7674b7c84dabb", + "0xbee7c0dcfaf95f85e6c58821f4aa09dc31285be7dd79160ab16cd68ac16ec96f", + "0x8b9791f9b84251d68b2125b61cd919dee74ede9d9b272a313cdcb3a9a01ec0bd", + "0x4194670a50bc7fb2ad1bd9fe60c3cdbaef8a7f9d5338ada0f4f9da97ecfc33e8", + "0x84a52e69f543539031ebb0aaaeaad905243fdeccfe87f58f38afaa0ff51c3641", + "0x12bbf63c2c6f31b2e57005cf99d7ef172df7ae01581e487f7e405a2eb8b2712b", + "0x6e1c0adfd156c3a64e0f342e0ef852d24780bc0c132a680c4d90bbd83278296a", + "0xf47713191d8afe922e2ec776edb9d9fe421821ecc2c51a4a5d1934e2566b660b", + "0x3d5ab526f48ea24e0fab729855e6fe4537ff1f4a37d423a797f261e936cb489a", + "0x999b153fa9a46778f806bbc1c110293f3f983b85195b55114c4cd605475c01cc", + "0xf4c934c4caff6611fa407b37c7fe60110c5b37ca6476f7da664110ce606ec887", + "0xa0e3ce8072926c2828384be41b8f2eaed77b0abf80b85bad1ac4ecfe50a29d52", + "0x1e0fafbd1b5044023a711acfbfd67f706827fa538f1016dffb14d78d742133d8", + "0x6544bbbe74274109833f0df8f5de938e5020f642f59dc15f44ef131e71364168", + "0x7070469ad96756a3b8eb3edf8af72c34426fd54b543a50bf90f7df4f9e6cf502", + "0x17d3adc89215b44e0ae066793fa92aac625a4625faac2f1af0dd7443ae88263c", + "0xac82f48569287d701ce51f0fb8d9ea9b58389bf1ccb14f51af0150ae5520d067", + "0xa345a1f7a2b62e083a9145bf72156dad96db87cadbb097eba49c1dbef37e7678", + "0x226cda69f3165f38c62fb320575370763c38ce1219612c8fb780d62e3724edc9", + "0x90066ef34898e0bed612ea988b9d7dba8d2752e5e4433eeee338ac46d0ca0e6a", + "0x13a52bc644a897f92b9c04f92153c3af7cbb7a8c8322eec5d2cd7acc955e5f14", + "0xab1151bb1fcfe04cfb138f6115007798156fe6ca34bd2d5450e7260369c46cf2", + "0x1ada842caa8d11d6ddb1f866920ce9d211d12681f0cfeb1fa953412ee72a6202", + "0x0775361415f30fc354811de5a09d152ddea119a45777e324bae06f605aac9a1e", + "0x3341e88e37257fb40d904b52a555e5ab4da77946feee8d0180bf0d02b84b2743", + "0x6de86152df7502a805cfe3ea13e6e92fed6591bb6807bf52ca6cc1ad12581960", + "0x2df8c525fcdb9e3338521ca003ecf34c0accaeb1ef8e8a8c53a4760e2a2f76f5", + "0xbfb79ba6c601d99fe9da4fa5d3156d43361e19d31cee9d8f6d86ccf8fca677ec", + "0x242c88cb05a573e013355f668be14ac02be3366f4529825e970a824b63ec955d", + "0x28cf8683b9301699cbd52ccd2e2382f0214b5375d45ddd1f512418955cbc75e0", + "0x962491665ead2c0a67a89c9cb10a95df482bde95bda60de9f9e26640262d8df7", + "0x89d44ee38abfe8a782b4c8ec4a15fb613da1fb54df1216b401e2b9feb5722640", + "0x22c65f9ad5d54461e990a01a32b3c0b816cb76fb6263916c7439d3a38c1f6e6a", + "0xb9e22056d59bac9dfaa70f3cf7e882ec54d12b5c651faae9db639d514358b19d", + "0x9e87bf3cf128facc840148f5992319455da79eb5b073366ab55935927325deaa", + "0xfda17f28aacb58b521e21980e1690292ec53ace1a331eb3f3e39ab47891b6818", + "0xfc89489cc181a41c11db271d24d745c602d021175bd8a3216466222f36beb894", + "0x70a368c3eec8a26721407652dafb467accd432a781c38c394811d4165da0536a", + "0xfdaacc8fc0d6a88b09f6e82a854eb5846b534cf709f74412a52ae1b73eb71eca", + "0x64dec3cbd894ef0acfbd4c756c57d1158b8735b9daabb8867a8fcb314c0d46d1", + "0x717f95c3cf0ea9fc9b2aa7da862e67dc5734dab7b901ba843fda932c2f4635ab", + "0x9832bf9af748a6a9f92fc7f808a10055c8134f6b9698b7a22c65889629eaa321", + "0x27556bf6b3b9f142af4b8b164dbc7320d838fc2035392f544e8acf891993908f", + "0x698c66e02954a0a3a9e20531427de5e111324dd63a3c17b3c9ff381591b209e2", + "0x15df8156e8722be5454f3a18da8f9c327626dfcadf8a43ca7053c2343b688eb2", + "0xc9012320a383a0daf25db92d3b2551542d09365e52ae17b0b8aa164804cacba8", + "0x3ec2163f659c467408d6885e2ebab399bcfed5e82eeaaa18ba9b11b6a7092c67", + "0x7c3c061c68f913425190d54c5b3085edb6f7b644938067a22d05b07252a2a577", + "0x65e7a85d7c9b44b46249204e20f5ced1725aaaa46c298e3103733116023af990", + "0xec90bbf55a1dc23fd2dce20458e9dc4155d40f35a6508476693f8f33e3c5c603", + "0xf5c3fb3cd7defd40896125d0b0651ea51faf248b1074630d8522267773f70794", + "0x098cd8401364b469a398ce063cd4c0dd245780b80535dda05d1cd318059a0e15", + "0x36a2403988d8284e774c519c6d5d60737de41f5e79a3e68b21c6e3cc31d99e3d", + "0x24c048089205c06055be2af692e5695e0b21c862beb1d2c76b73453be1aea237", + "0x4c6bff0317e1d45668e67bba2e4abd69fab7d49ebcf25b71596eb00b7da022fb", + "0x751d9aa08945bb12fcb312d8d9582cecbdad4ba10443a11c76f2336354db309f", + "0x4d15a64bdfcc838b9673813a073e6dca2e7cb8eef5c2ca9cdea367197d5d77c0", + "0x1857138e6b90b38417d9524923c4afee7815cb4b0a023b5edaa7e1b5d67e956a", + "0x9bb20548865f77267249f8934e8a7ef78630ca2b1a698c20a1831d57c40663d7", + "0x05f1132fc8f3e9b6e1fb8a798324249eb5aa7410e87b28549dcdbbd981995276", + "0xc62c8b41c48fc728ddda25dc5f7f112569b1ed7fdd6c9cb365012b6c92c063ba", + "0x36a336dce4c079c097c13378010261ae60d7614758bb1a644c1431aa535fcfdc", + "0x861762f37bac1e99454d486daa5586b7fc16ed3d5f8a3d4ceb76b2430b07176e", + "0xd52e37befd22d62f41bbfe77d3236bdeec8c1898b66fa74b8cdd6f35a9b02d76", + "0xceefff0fe45933ef72a62168b853824feb4af74ae82804fd635a3cbd554994ee", + "0x2743e9884c5b82e2c96f51859c4488fa62c174285a884d8d5fe37c134cb460e9", + "0xd14b5c588e28af7b69c0f62a2de16a19e10a89b4e0b77fa9eb2220de12431049", + "0x7a6720ca354c4749f0fd338049b84e2c018bda8180885e137b43aea736d013ae", + "0x33d57d2acd57e925d5e72e9a9d98bff821e9c0c3f3ce0862b5e68d1a81578509", + "0x0376d061cd94b3add12e0a224fc702bf0c661ed7540388fe2d1c0e45b33a9575", + "0x1b7f9abc9e995ad6d501085bce4ec8cfa283a6c818f172361839a03463c1c823", + "0x91f920bc30f075c30faf5ca2800a3d98ce11f1ef4dfa59d59c48b0e3c72d77cb", + "0x12bf80752456d779accd274428b53aeb15a1f1a47c0f85150ffeebc3ab1509fb", + "0xf75bc818dd47ea5e36a4007bfdcc855d48e057ffad411bda1874c4ea9290560e", + "0xb3373cdff2cee48761a5646faa2f470bddd2dd7f4e5b3879f5c57233581c11bc", + "0xcde2bb6a64542ae77dd1823ee1abd29e5bbdc9a8a987c4cc0c9e961ec01aa64c", + "0xac9986cffa116e9b974dd5e9eb8951b6ee7ff8feaefe33bbabd072c492098e52", + "0x175ce1d341322690675405440dbad5dc80d5c62db7883bd58887ae4e8991040c", + "0x2607c713b1a38c26ed1ba5574fcc1ec9e8e68a7c269c1cd687d4afb71aa6607a", + "0x1c83dcd846cb1ba5a56311a799bbf6033d3846b62bc022fa8c78a2f045a36b6e", + "0xf07919693e20b7f9b50c0745ded6f76e3b2ae6fd301548b297eae87c4f096d19", + "0xba1e5393889501428a866e4e1f1181eefe7ce96c023341b9a724f243c20efd98", + "0x5c8363770a2fcf8e6e2ba1f384769100490509fa776a609206177a4cc91baf49", + "0xdc1a4b1c138f9e7157f7fe476ca93579f77b436b512d7b1a92cd40137fed5a32", + "0xaf5630fa700a41ea1896d8745c484dc51599a45f4420b155f532acaf70159930", + "0xbc42efe8ef2ad47223310e252763f03081e72d3b0fce31cb8a92e535f918cf7c", + "0xb3c82090aa8e61d3cf66e68324b89bf0c8abb3a90a7689fd0e2af475eec12796", + "0x0b9292e757146f5c82e38b8c704ca9d17bed72c8f05abed2c72e4b749ca95cac", + "0x1f001856caed8f92c04803e3673c36c1e6d44c54fe5a2fa6dadc0f647ce5a5cb", + "0x4f5d9de1ce98d143c5e4230da545a92ce2adef539b28b3ea12b058dc50516396", + "0x92eab7aa903c1c9672cd846dfe59daed08bf7eaac3649acf82cc10d257c4ee83", + "0xfe53e9046375699c9d6d1e97f5394e4d9dc47247962cb12b1f19b14280c36e68", + "0xf2b4013bf20360c30a02719ac84a1fbf1d4f2f75a13708fb33698b404f89643e", + "0xa2c42fab1a55e7ad87d3d6ddd539cc015672bc7d9945a0b095d321ac5f2d269a", + "0xaa19e88d2f0331d9eb6982cf6adc3867765a30aacbad4636c6c14075debb3f14", + "0xdad3369b52216bd1d5670937e8d02011be203600f9e0a5971083478a751c158e", + "0x95606ec86211580a457dbd3ce345582cb63fa1e51bbb26e0fc7f66b346c5b165", + "0x3724ec7e644d1c9217a4530be31b164d132103e137d78ec65d7d2b331a58e176", + "0x3c9a30656517e28897e13397a1aea4320ce012365186c3780c284284188820d8", + "0xb1e5c6e1fd3acb6071ddfa21930749088701625cb28b632605f428034eb40599", + "0x16cab690f62af9c4532518d5d44adc79294509e7d468c8320ddc6a2af947e00b", + "0x77dbcc77ed87f3abfba8593ca42e5566509be4045df7b1360a147380f4923a18", + "0x50a81427038cbbfa9d80e7c8bf81275e87ed12329dccf818e97a2cf8fbf18bb6", + "0x535a32f20b009046f36d7ddd94803075813f018dec533ed87cf106589f1a9365", + "0xc09b4db18f62c39052fe388f8d94aa894cfce591bf868dfdb6d9598015c373ed", + "0xcfd40ebb21db79e7afde2605d7fa23eaab3db5ed9c0fdfa3310b80e839c3d687", + "0xfc99454fc2feecdc233ddfb15f8248d2e5c3c3b47c928a4bc47347cddf4abbe8", + "0x6591ce7a1118faba148011194404fca2a0d6731171ae29a287fc00aeb02adb66", + "0x109290c341c44b3e85d45d772853217e13388f406f95ae6f1127d574ea12ec53", + "0x623a639e40ebb08f05055465be038aadd7f8db549f1eea2ef084afaf199e8a66", + "0xbbf06223a713f88a1f571517792c0af039985c8f15e0fc803b7dd7c464595715", + "0xac7d49ae849acccf45e6318e4cfd18c03416b9bacbde64ded23514d59b716a97", + "0xd62497729af1b32f0e22fdb503a750c85a10299ee966e5c5ab1ac7e71e5524d0", + "0x29c2cf3cc0cdb9799e0593902ee453fba917f096f7eb5d04418ac292d9d40463", + "0xa5524f355a9fd8bfb4bfca14fcfe58d227a0b8d723943ae925bd88613f62927f", + "0x558f4140defa8a45ce60cd2297f60656454fbb1306d416229d07f27f18531f93", + "0xbb3506870630199af605f63e105c9acc9de29869b2c67661f3278d4d33b33d5a", + "0xc3cc4b6e3d14f45f0624652df9aa2aae5bdd6e9824a06df6d66572afc3ae7dae", + "0xe1070ad4c886c4e4e118541e6c140926d2b2463701b293527a91a165418ecab1", + "0x22fe26c7de8606e08d7cc1e0e37a7061c9fc50da3581c1441c0331ae32fa18d9", + "0x71800db5261f61c5525744ada55e570bcd2820eca92f30bb2e83e3f08e03edba", + "0x032839dd738ec7d5e43b84ac14adb11bd08660921c1f12932cb64ffd0179d343", + "0x85a762a2ab18668af249733829cdef9e3787bf2d2e6ab9938644918c0c1b51da", + "0x16d578dac1dd575ff991c2d25e728973c1ebc2b61a3032c8b85b62258667bc1d", + "0x3f1455a483663459733cf450c0f0e16678eb1f5485a6cfb6174630eac026ca6d", + "0x029933e53cad5e16256663fde9bda097abba5d7327e9c0fab07abbd013e14ea0", + "0x657b61028b161a1a3bfca40928375621133b0435893dd1d2562944ca85afdb05", + "0xf541e675935600a62e60bf5bd98093ffebc0169f23629db977dd8771958f3cb5", + "0x8c43b0d7c2293e089724fed36851744200d9b87b6600e3ca351f3f65852e5eaf", + "0x07c6c657a80c5718804544332c2f68b445e8d7fc58f01a650d7a476c036193be", + "0x0d38f9aa48346458b8ec0710b28869f4bf979abb80a4ea0464cdd9da659e0db6", + "0xe39b8a792df028169115125cc8466701df553de20d1ea385f3249a1d1c13703a", + "0x77180591ba49b6118cfc4ef772aa9a1cf2b3d1d67be1f15c308cd0727dfeb068", + "0x088d7d35f2b14bd5d0a1b6f3510ffb4f8ea2d054f3f6b99de8fcd7bc7dcb37cb", + "0xdd0bf242332c127c0e63e535ad3ecae82588ca70eb04973ed89e29a81a65a17d", + "0x218dfd445fd02c980736856e5af70942dcad8a0600fb905f0b4684f317ce4f19", + "0x1574b6fd0411b9d22f10a2d19b0a681d163c7b969e9a608499ca06414e579434", + "0xfb0919cf4bb52733e14989e7c4de84cfe6f06baf792f7936f3d3ea00efe5712f", + "0xceb92288daee1a5e2022206783d3d069b7bd1edc00d3fb6a5841ee1cab207e47", + "0xe2cacbb8bb3bf3877506499ebf8e8ab83306482f87c24ef6ba95dd40a68ebffc", + "0x373dd6cf736c6623843087cc276480576edcbfa873cc8e25dfa6f4ed396ca9f2", + "0xf7872e8c04a5766a8773d1af21d79e63004240b9f9caccbed57f58162e4175f8", + "0xcfe8a827fc4c36fa63990b95b90c68a684d4b792d20b8d786a4e1b1d13d3f935", + "0x7641f61df9b6f40c57815df7ea6ccadd757094a7420438ab310bce4642412ac8", + "0xddc8f2276bea73f13a3b127eb637265190c5655f4a8ab75cee2fe739277dffa9", + "0xd7858cc623ace8f1d0d22128da9729c9e9d3f0b56ef3ccd33464c1096d4f5811", + "0x4230798246b8939b83db483d395829d1d306708d11e783e507dc1e3b49490b3f", + "0x89209a8acd2568a49a7e623b5ef5f43664c41b9d7923d0dfa5c5ef6c7b8799b1", + "0x104b1b2826fa7d1b22770c1bdf6810b5e72d384ebd22cf9faf6ad3f348beb0c0", + "0x1a7c94386ce7d3028d3370aef277d852a7beb4d10127701cc5ce10a1b044018f", + "0xb98519653520206971618cf9b6ce2c1df8e9f471e8889c7b5d57d274281442d6", + "0xc890e325cda72421b2aff2785b0d917b02722e48d7d4b04b0848ae112b2676d3", + "0x571c5944b46c3f9a0cd2370864355d5a8a84688094cb216cf525541c36c11396", + "0x0ce2c597798c13d44ced6fc8d2a25f2e2570f2042a2563a5b9e44e162ca34852", + "0xa6fdfe84cb052109bf80190a9b031b8ef4af89fee72171477eb0cbe77a231350", + "0xb3710d99697ad3eb32af332e1e1466ff14a36eca12f49353134a3ebc89673174", + "0x46dc128448fefeb7356c6a2d4c7d2d067c04aa1973d6d5dc5d0001a08641ef4d", + "0x7e29853c2fb2d83356d63ed3984a068aa77570352cb488982f4852d52a82c2f0", + "0x796684dfac249c4ff804ad476035254b150ced67fd5090a870d684e7343bde65", + "0x3e8e5a22737865fc518ba785a18d3fba861c131411e2795920a1d8714ff76f90", + "0xd60787dd997a22b2faeb6e3257613591f73966e39b477f196566031d7d97f79c", + "0x143b777a1ab7f233c88ac126fecdd2b139a73d27c2374a14f59d6b2a3d274c07", + "0xa0423fa816199bacd23116e13196c2dfea68467f0bb7211a54edf40cf8266a23", + "0xaac1db2e966c0786bbb0c426a40327cb230231f105a27e99c8dc8d5a776f2aa4", + "0xa5925ea9ca18ec46e986133e5bce4381b4bdb34a2929da9266d63fed308330ad", + "0x9486ff72244d82f0521aa89bdd4e4ef287c7c8b9f11919fe5e169eb680162bb0", + "0xe5590a8ad9f00a25d6b1c7bb7972322d4c7aa0d168c2d64dc1c1a2cc3e1b2c5d", + "0xa4d19ff7d20981880824a2212a5ebcde16ed294a1b486648eefdb4e61985e628", + "0x42008316906fde068656372ce9cd086d98cf48ae6c8ebef4cf2c318f6196ee42", + "0xd997400eb0679ee898e3591f612f12fe62a8a512e9f29bb5d892828a717cba44", + "0x8cb77326590d26e47866b96c7b0d4a2cb098e9c3302973c355d4cc6b7bfb9a39", + "0x5aa47047d8dcfdc52cf5eb6850a29e18bdd5458479a62ce73e390da48019908e", + "0xb7db162e7bd3eca38c26b81c280060e0a80afdcb1b1227f2be53a104b7bde92d", + "0x6118fb183a607ad2ba7977b23d55a13a13c23fb4d42ffd025829684619cda56c", + "0x57d6217b90c06b85cb935a7e662a0bfff6bea628d67148fd77cfb6d4aae46b3c", + "0x8f6ad6d46e34c419d675f2e11fd9415dc0051034dd2dad492992cab39a4134e0", + "0xf02b43c671a09c3496057bc12d546331de2bc68cb18c64c4562a7b4ea09400fe", + "0xc0715798ea2098d50a16240d7764ec79ef0a888a46acfac383e72d2e50c6fd45", + "0x3f87cf2fb3973cef48f8727096633c517030c4fe3b80c8de5c46b7aa7688a7b1", + "0xb3eb15c04da4ed796f22c6f9a6d9b650e49092dd775870ffaf4538efaa9143a0", + "0x0858a7432451452d8f99395811d8b9605b6e493875cd8f6efd38ac933f843c21", + "0xe8d6f6cbe3fcbcf1a8b670b57045c9163e28e62c2301518667869fa6154778ac", + "0x134b94a104a8fe9c8fb5b74d01e8137b998f9691844fe8f6a22634d967c70c29", + "0x5ad0ec6ef0efeda0f2a0ad2a693eea176358a6298e0d16014c86e17f45a91418", + "0x1439519977d98a556eb1f32924f6206faf316ded77c7e6624e68e139f99d2ab9", + "0x50095fb3ffea338cf7304154c4603c41eb187b7f19d356f1f97a12aa4009557e", + "0x40d1b045015f62509696d3e0c71ac234ad594c46814d04d7cdc76f91d848de89", + "0x5f1fbf6945d348a53089d2c9d3feae12b7b2981b33ad5242eeba5d8aca474211", + "0x016e294adf2b7ed329e71d054920efc2399eaa9be90ad0edcce1a1ecfda74b2b", + "0x13dc29c28adef710976342863d04ff778fab90c34b36932cdd41d176621c517f", + "0x3cdaee5da98612994b8ab88c32601824112c15dc74f2438fd6dfcf26697c6041", + "0x0792f243e6cfd99f708f30d1dbacebf43a69e3fea671a53eab7580f7ad0cf896", + "0xfd37acc097563f9dbd330592b8b0d84e13460aaa9cb299efbf55b87911a42171", + "0xccc52c8e84bcf512e0641a383bd59565a91d7a2cc4fce191890e17318fd550d8", + "0x42c275730ae7b7931c354cf6825876f09bcb721ef2a49423c7062316c2d6f2fb", + "0xe7fa209c2e52f36d1142265890f2d4cf6a65ef6bcc9aac8b98679c4d9fbf50ca", + "0xbfc25b3401aa288d08193c95645a23509d7f91d186438a713ea7422053615112", + "0x59600d2e03b83317882349f9ba9a29e378c99f5d400b66a4a61dacc45a10a06c", + "0x5bb42c1dcab25fa7119605ee2b039418433659a9d44d2607423077735d06d646", + "0x1c88606c1fb90348b6639e0b5ac351aaa7be9d8e7a54949b04115be31c19b210", + "0x0c3688bb4e69ee1d2f6829d207ce327baf2ad913755ded680006516f29042f0d", + "0xe416bd0839a09b9e043cba3cd29151605c8713c0a87060e721236c42dba557cc", + "0x47e198d26bbeac4883a8faee1409f01cc5bb8f4a3e9103b3d79452a8d0d7256f", + "0xdb13ad2d508c4cfd32da5d0feeb2ccc02551f5f0764496849c2ef79d65f81e46", + "0x28b168561a00f5b4888fb3921702e178289dcb4ad8ff9e6a05f13c7b2063fca5", + "0x2d15236fc32bf37335549ca7b8aed0af93c417dd58ac8943893b37b29c9be194", + "0xfba066e3e867af94ffb35c83d90f91dbca703d2b1e1270d3134adcb269e1d3aa", + "0xb39dc5605015af1563f509d43ca979c0b2e91bfcf92ceee5da72ade5c757cd2c", + "0x3944c7239cb201f6541d75c7d316a48dd13d574e1ddf4176630e90c67c05a9b7", + "0x2abfa889595997cf93345c17b16afec7b1935c25f489a9908571b239dc76585e", + "0x73ee344a77f74f57a2a3fac1ce4bdc060910584adb0188cb7c80c2e31b772aa7", + "0xa627e9f5da335b70be159292845e084fc845263843751fe19f9f1e2bc90b919a", + "0x77461a4012c70824575618bcb3a0d876752b3628266d30ebf032ee0895d6a934", + "0x3c8fd955012a02303155bd221e5416ccaa350c6bf53a7a0fbd481cd48f67aa32", + "0x4d6c89db5620f12ddf98c91597b6fbcce717feb4774a4cfd0429af94ae4ae329", + "0x49e687e61dc125632cd4bcf99284545ee457755ac8908586304eff9bde1e8e09", + "0x330f578fa2bb1b92f568d94c0ddcb12aaeea8a618dc753ab8be143cd0356009e", + "0x30b04622465e3bc19178ba1fdfb3e0c9e552248614357c2372a4d64366b925c4", + "0xcf73d465019666510b2f02790d21d9fc5fd1fe7ca6e670bc00efc0b6407777c5", + "0xfd7819a5d0a680319c54034683f153c89ef8a5175132d82a20e602645cb5b54f", + "0xc9dd44245feac5089313f2940d1d1a27dad3350ddb33c0d32190b44382b99976", + "0x777ce6cc23757f54a5f25323a19731ab48fff867460631afa8119d77d32503ab", + "0x7b6734afac66e9bd705d4366fe75b25ea1033a61dae0075e8cb3c3d7f5383b8f", + "0x2a47d485b255bbe4327c97e996704c9a613ee3dc82c43eac266f36774ca2b866", + "0xb6d6659eef76a48ea53e89b2b44291f908aaafd6937942f0fbf4bf7a80249e17", + "0x8fa106b3bcc701e850b0ed9496a8b3331d1c7dcdc236f7c1750eab30a4eaf5a9", + "0x7f5c12db2b31a5739529dadc239b677a7bc44a9bd84a54174556fb7c91bc4e40", + "0x17f82052564250a89d1693e2c11c23f945051562d9e95d10d9ce07175e8e258d", + "0x48318d87fcd2681f1cb40c94137b43ee955602244da4638b1f182a7c6d75e964", + "0x0f85a07673865086c9637ce92bd1ecefaf9399830b12e65173a5243c792a71ba", + "0x200f34e1e23a98e581457ce0b9667dccc207ef85611258971b40b543a477b32d", + "0xb24111bb847669bea0ebd5b5cbc7c850d0e814577ab5291f7b6bc3a570ac8cdb", + "0xfdbbdf9c55f43933d30a61497dac581c1c999f1730b1fc884965099d4c2ffdae", + "0x163d60e452407f19083203274a9a4b6681bf0c314f48f7cc09d2e4fa4ae26ad3", + "0x7316ec58ab0a808fdab04265125af16582e75c4ecefb70f6d23eea42e072ba13", + "0xc3908756583f8b291a3ae74f4abb96bea69da503887a9b5db8dbfa84d361808a", + "0xbdc3969cabdca434e5a1ce565075d3dbc4ca918a385bc60f62ed7505f1755074", + "0xdf98f4eaca81432edfd51d138a6b85d77f9a219e7565f4987a5b8f34bba40b79", + "0x426a0dfbce9121ea7babb30cd7e8f74605dd781a844403be8def56b45792b7f6", + "0x617cbe91494aef61910ecbac7233faaa1d580e2f1131be446a2e8cc0854849c1", + "0xc68bc3472fe90e10606d2f3a40c117e9730140107b423e5225214998145d7c66", + "0x84c464268ab6581830fb5281310016317919ae759f8151de4e1454c65af27eb1", + "0xa0376b6e3c691729b059e3779f18d52d7c321d528f33f59b0fc37ff34dedb0f8", + "0xe2c6cc9f2c06cebfb32f4eab5e7589c7b47310e44aa577c32a6851c59b80a824", + "0x07a018ca5dbd9d3611f24829000e27f828273988a957f190df6d315706bde47f", + "0x7deb3005e91ce21304fdce15a13a7a001779b7f021a17af7e889c1982c35f2af", + "0x2cc679cb44882cb685ec9a8d9ae3058a61e646c26c6635bc12068820615f450a", + "0xa5351381cac3b4c897825ff5acd817fa2682aca353d6c5df5a0736f940772361", + "0xa8afb3dd19f6c9aaa2b94742ebf50abedf904dd8b513991607e5c5b59539b0af", + "0x9a95f3ff3fb05b834539d98cb8aaf9422a9112f5f232b6aebd3153d7064fad3d", + "0xe2b2dcd9f84e3d913ccdefc439c650036708ec4e8e6d71c57d5a36e29007f00a", + "0xc1434b636f30b48f7a1db83cd094fb46455044a6ca8ed9996cbe1b0586353e56", + "0x32f4583854febc4ce209f90fbec4af4ed5da4cbd06adcfce0683853d7645b43b", + "0x70f338d6a745fccb2700f6632709f8b94120810d4bda076d38ab84dc5a4b60b1", + "0x1ca817244ef70d749235354dbe73bc02adbe1a9bd679531c9529b7f03eb08ce7", + "0x07a568e8a9b53dcf9fd6e7326d4b1d5f243f0dbc49f3332cd1331db5b9f4d49d", + "0xa0aa8b4799e91b0c2585e073d43988edfc581decf56c64b9083f9692956d1f9c", + "0x0e7f230a15895a83f437782ba8695ae81699c84429d30d2dcd22d842d6a36143", + "0xaad29638bcd49431591ee0dbf117e035c35cf0038267e4f2b3a484e4791f4dee", + "0xbf152e8cda2dd12ca52aa7cff7ddebc4e54a2c78bcd2bf6a158f45257333a09e", + "0x7f7fec07a6d7b2200c3e9b2dc66c5c49d2f2badd6604cc5aabc63a3ec5038375", + "0x8ea37350a5d0c81e11b76eb29d269025d28b26bd29a196330465997b3d82e1e3", + "0xba45a6e6042f86544892daa1a7731b9840a9171d3d834926d4d5bdac32889873", + "0x3269e10a8871a97b07dbdcd20eed5cfdc8c5e064d576dfbb508ee4082582913b", + "0xe7fb5297849c3d3eb0b3bd068cd2e9dfac549dc43a44c65e3b2005ba391d8a88", + "0xe42cf98685e159d10a3e4fbc19b6df03d8ad42d0f3d398f826a806a48a87497c", + "0xa448b7bf0faace82dc4255364fd8fd029c5c5d828888cb131e649472c6150775", + "0x1043325717080c977ddb22086d496de9b3308ccc7452665851839863cece60db", + "0xa1e34e462ecf988dfacc1aa371f1b188120ce3c1e06dfa06f639799889bbf5ac", + "0xd4f33c1c390ad6244e6c3b6699579f2f351b1a0b583550fe2f4b189e211c9c30", + "0x4cce900d2ab1dc78e568fb63e02ecd06fef0cd68d7cfe20cf9fa657b62a94dc8", + "0xbf85a695d507b9fc42ef3f81b76483f70f9e8767534a0ff35eb2f3315798d72a", + "0xd96ff1488e2deab994f27f204037bddc099766f1955c916003a4c632b48aa500", + "0xc963ce4671607cec2c36d8050318cafce4f835f20b5a859fdca14844a7e3a456", + "0x2e5838f879f8f698b3a7efeaafeb7ba324940aeb3f8b5bd16aa5ccf8737f4e63", + "0x0fccc49208367d119399101e5e0b1ee6ce5ef0f61f4a9f0389dae06de2038efa", + "0x63920bc887a208585f3ff310990c24c8e594942e371e7c2b59ed53f4d33bd1cc", + "0xd675a402fca8c1f1a9d977365c5269b93d963eb832ca1adc45b1b0251897093a", + "0xbe37d401abe3adad6d87befe126ea1883c4d117ac85b6c27965a1bc320f1bd30", + "0xe7182036132dd24e782cdd5fc41bd0a31b36a3eef1327ac211df3aa5fdc9df2e" + ] } } diff --git a/ethcore/res/ethereum/musicoin.json b/ethcore/res/ethereum/musicoin.json index 109432e58f..a7cc956b47 100644 --- a/ethcore/res/ethereum/musicoin.json +++ b/ethcore/res/ethereum/musicoin.json @@ -128,38 +128,43 @@ } } }, - "0000000000000000000000000000000000000006":{ - "builtin":{ - "name":"alt_bn128_add", + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", "activate_at":"0x21e88e", - "pricing":{ - "linear":{ - "base":500, - "word":0 + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 } } } }, - "0000000000000000000000000000000000000007":{ - "builtin":{ - "name":"alt_bn128_mul", + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", "activate_at":"0x21e88e", - "pricing":{ - "linear":{ - "base":40000, - "word":0 + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 } } } }, - "0000000000000000000000000000000000000008":{ - "builtin":{ - "name":"alt_bn128_pairing", + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", "activate_at":"0x21e88e", - "pricing":{ - "alt_bn128_pairing":{ - "base":100000, - "pair":80000 + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 } } } diff --git a/ethcore/res/ethereum/poacore.json b/ethcore/res/ethereum/poacore.json index 53b3c548c5..0b1f0f4677 100644 --- a/ethcore/res/ethereum/poacore.json +++ b/ethcore/res/ethereum/poacore.json @@ -35,10 +35,9 @@ "eip211Transition": "0x0", "eip214Transition": "0x0", "eip658Transition": "0x0", - "eip145Transition": 6843780, - "eip1014Transition": 6843780, - "eip1052Transition": 6843780, - "eip1283Transition": 6843780 + "eip145Transition": 8582254, + "eip1014Transition": 8582254, + "eip1052Transition": 8582254 }, "genesis": { "seal": { @@ -52,7 +51,6 @@ }, "nodes": [ "enode://6e3d1b39cbd2a9c4f053a27e68fd90d0bac83691dfdc4a13c59f2555078a71e63c5daaee5a82aa6db500512760a5456f86076bf8bbe8011c27c82ed7d6f5fb26@45.77.140.210:30303", - "enode://f4698ad485a027497e1cc992bb5f7cecee2b32a44c47202738d8d0eecfab719541988d0cbcbc5ea94c6c959e5cddeb85fc6ae75fb63dc3bf87cdbe9e6f615e9d@206.156.242.64:30303", "enode://31dffed97f8fed1f34fe66453280a89cbeeda60cf28f6fbb212ebbefd7c7566a02c1c7d5c00bbbb49b9fa8a49f157e0f786f379ca9bcbf2fea24de70d70a22b6@206.156.242.61:30303", "enode://6bdc7553ab2e4914cb47774c1e6d8c8f47ac7c3981891f85f65d06f208ea1bc4d3bf982b330950e0a0cd127efd7145c4df7113159a1d4a06ed722e6c16d0ac6c@45.32.215.190:30303", "enode://872d82a24144bc007658fb6fac0dcdfb9b63aeb05ef563a06d0186f2d1e5ffbfc5c4f1244891a8a86ef70682b9d24382e654b305224883698862e2df647a4d23@45.76.236.247:30303", @@ -61,10 +59,47 @@ ], "accounts": { "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x0", "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x0", "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x0", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x0", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, - + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, "0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { diff --git a/ethcore/res/ethereum/poasokol.json b/ethcore/res/ethereum/poasokol.json index 8ee91c90c0..9caef0bc94 100644 --- a/ethcore/res/ethereum/poasokol.json +++ b/ethcore/res/ethereum/poasokol.json @@ -58,16 +58,54 @@ "enode://8e0af07c86ec36590bb6368e7ad0c45b6dc658f5fb66ec68889a614affddda5e021bd513bcf4fb2fae4a3bbe08cf0de84f037cd58478a89665dfce1ded2595c7@34.236.37.74:30303", "enode://f1a5100a81cb73163ae450c584d06b1f644aa4fad4486c6aeb4c384b343c54bb66c744aa5f133af66ea1b25f0f4a454f04878f3e96ee4cd2390c047396d6357b@209.97.158.4:30303", "enode://0d1e0372f63a3f0b82d66635ea101ecc0f6797788a078805cc933dd93e6a22f7c9fa51ab4e2d21da02d04480ef19f3bbb9a2b41dd1c262085d295a354bb8b0f9@18.217.47.209:30303", - "enode://ab083db73da15b3995ac9c68035cdb32901835a823cb848fccb672e43dd21f14428706118d6fe5b921d8e741f122f35aad0255bc86807b1d17bcfa1e86e40a14@165.227.37.104:30303", + "enode://875e1bd1b98019a5d6d588c23f68534b75462dd6ecbb3dd058221dbf7aa923f0ab782ab93bb82d42edc9996f7f0816a318bdc761e55c02b95e1169cef66f7edc@159.203.24.35:30303", "enode://8e0af07c86ec36590bb6368e7ad0c45b6dc658f5fb66ec68889a614affddda5e021bd513bcf4fb2fae4a3bbe08cf0de84f037cd58478a89665dfce1ded2595c7@34.236.37.74:30303", "enode://182ee200ca134dc4d6390f3d5aadbcd80df0f7f24335830335d142573eacce4eeb919d30e82c5df588034e167e6ba6dd11187502ac9264a71005127f6b146a99@159.203.95.241:30303", "enode://b022ff70b5fcaf9596ae5efed99a8198b4ae0578ee9d17b733609d803a75cef95d3a2a18e50dca9a7c3b26139f158c59eaf8b5fb8d1d331c9a46934a78acabe8@206.189.76.128:30303" ], "accounts": { "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x0", "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x0", "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x0", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x0", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, "0x0000000000000000000000000000000000000001": { "balance": "1", diff --git a/ethcore/res/ethereum/rinkeby.json b/ethcore/res/ethereum/rinkeby.json new file mode 100644 index 0000000000..3945b88118 --- /dev/null +++ b/ethcore/res/ethereum/rinkeby.json @@ -0,0 +1,919 @@ +{ + "name": "Rinkeby", + "dataDir": "rinkeby", + "engine": { + "clique": { + "params": { + "period": 15, + "epoch": 30000 + } + } + }, + "params": { + "accountStartNonce": "0x0", + "chainID": "0x4", + "eip140Transition": "0xfcc25", + "eip145Transition": "0x37db77", + "eip150Transition": "0x2", + "eip155Transition": "0x3", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", + "eip211Transition": "0xfcc25", + "eip214Transition": "0xfcc25", + "eip658Transition": "0xfcc25", + "eip1014Transition": "0x37db77", + "eip1052Transition": "0x37db77", + "eip1283Transition": "0x37db77", + "eip1283DisableTransition": "0x41efd2", + "eip1283ReenableTransition": "0x52efd1", + "eip1344Transition": "0x52efd1", + "eip1706Transition": "0x52efd1", + "eip1884Transition": "0x52efd1", + "eip2028Transition": "0x52efd1", + "gasLimitBoundDivisor": "0x400", + "maxCodeSize": "0x6000", + "maxCodeSizeTransition": "0x0", + "maximumExtraDataSize": "0xffff", + "minGasLimit": "0x1388", + "networkID": "0x4" + }, + "genesis": { + "author": "0x0000000000000000000000000000000000000000", + "difficulty": "0x1", + "extraData": "0x52657370656374206d7920617574686f7269746168207e452e436172746d616e42eb768f2244c8811c63729a21a3569731535f067ffc57839b00206d1ad20c69a1981b489f772031b279182d99e65703f0076e4812653aab85fca0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x47b760", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "seal": { + "ethereum": { + "nonce": "0x0000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "timestamp": "0x58ee40ba" + }, + "nodes": [ + "enode://a24ac7c5484ef4ed0c5eb2d36620ba4e4aa13b8c84684e1b4aab0cebea2ae45cb4d375b77eab56516d34bfbd3c1a833fc51296ff084b770b94fb9028c4d25ccf@52.169.42.101:30303", + "enode://343149e4feefa15d882d9fe4ac7d88f885bd05ebb735e547f12e12080a9fa07c8014ca6fd7f373123488102fe5e34111f8509cf0b7de3f5b44339c9f25e87cb8@52.3.158.184:30303", + "enode://b6b28890b006743680c52e64e0d16db57f28124885595fa03a562be1d2bf0f3a1da297d56b13da25fb992888fd556d4c1a27b1f39d531bde7de1921c90061cc6@159.89.28.211:30303" + ], + "accounts": { + "0x0000000000000000000000000000000000000000": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000001": { + "balance": "0x1", + "builtin": { + "name": "ecrecover", + "pricing": { + "linear": { + "base": 3000, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000002": { + "balance": "0x1", + "builtin": { + "name": "sha256", + "pricing": { + "linear": { + "base": 60, + "word": 12 + } + } + } + }, + "0x0000000000000000000000000000000000000003": { + "balance": "0x1", + "builtin": { + "name": "ripemd160", + "pricing": { + "linear": { + "base": 600, + "word": 120 + } + } + } + }, + "0x0000000000000000000000000000000000000004": { + "balance": "0x1", + "builtin": { + "name": "identity", + "pricing": { + "linear": { + "base": 15, + "word": 3 + } + } + } + }, + "0x0000000000000000000000000000000000000005": { + "balance": "0x1", + "builtin": { + "name": "modexp", + "activate_at": "0xfcc25", + "pricing": { + "modexp": { + "divisor": 20 + } + } + } + }, + "0x0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0xfcc25", + "eip1108_transition": "0x52efd1", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0x0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0xfcc25", + "eip1108_transition": "0x52efd1", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0x0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0xfcc25", + "eip1108_transition": "0x52efd1", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, + "0x0000000000000000000000000000000000000009": { + "balance": "0x1", + "builtin": { + "name": "blake2_f", + "activate_at": "0x52efd1", + "pricing": { + "blake2_f": { + "gas_per_round": 1 + } + } + } + }, + "0x000000000000000000000000000000000000000a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000010": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000011": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000012": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000013": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000014": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000015": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000016": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000017": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000018": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000019": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000020": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000021": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000022": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000023": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000024": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000025": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000026": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000027": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000028": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000029": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000030": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000031": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000032": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000033": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000034": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000035": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000036": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000037": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000038": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000039": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000040": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000041": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000042": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000043": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000044": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000045": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000046": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000047": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000048": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000049": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000050": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000051": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000052": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000053": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000054": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000055": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000056": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000057": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000058": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000059": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000060": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000061": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000062": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000063": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000064": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000065": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000066": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000067": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000068": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000069": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000070": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000071": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000072": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000073": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000074": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000075": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000076": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000077": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000078": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000079": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000080": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000081": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000082": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000083": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000084": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000085": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000086": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000087": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000088": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000089": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000090": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000091": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000092": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000093": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000094": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000095": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000096": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000097": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000098": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000099": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009f": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000aa": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ab": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ac": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ad": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ae": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000af": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ba": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000be": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bf": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ca": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ce": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cf": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000da": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000db": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000dc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000dd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000de": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000df": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ea": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000eb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ec": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ed": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ee": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ef": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fa": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fe": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ff": { + "balance": "0x1" + }, + "0x31b98d14007bdee637298086988a0bbd31184523": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + } + } +} diff --git a/ethcore/res/ethereum/ropsten.json b/ethcore/res/ethereum/ropsten.json index 953e7fdb42..aefca8682c 100644 --- a/ethcore/res/ethereum/ropsten.json +++ b/ethcore/res/ethereum/ropsten.json @@ -45,7 +45,12 @@ "eip1014Transition": "0x408b70", "eip1052Transition": "0x408b70", "eip1283Transition": "0x408b70", - "eip1283DisableTransition": "0x4b5e82" + "eip1283DisableTransition": "0x4b5e82", + "eip1283ReenableTransition": "0x62f756", + "eip1344Transition": "0x62f756", + "eip1706Transition": "0x62f756", + "eip1884Transition": "0x62f756", + "eip2028Transition": "0x62f756" }, "genesis": { "seal": { @@ -62,8 +67,8 @@ "gasLimit": "0x1000000" }, "hardcodedSync": { - "header": "f90217a058893ba2a7f3d1625239b0ffab5b58219412b5fb51a608fc6ae7ff012496db9ba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942b126e450158f14add6770739a2e6b4037526817a0a46d5b8474c625b4efd3d1d2864d7790770737587aa926fb223945d55a1d0da8a04ff0c821428157d6a4ace26e17d775eac4f42cc7d777898ded413780207fda11a0777f1c1c378807634128348e4f0eeca6a0e7f516ea411690ca04266323f671a4b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000844737e14e834dd801837a1200830186a0845c76311499d883010816846765746888676f312e31312e35856c696e7578a0676e77abeb493056c28a2d8fcd1238da73a29c9d915441fd8b5e36f6e910fa5d8803afeb22c339444f", - "totalDifficulty": "18334236703652990", + "header": "f9021aa0a8da98b6ef1e12b6c49e85b0e965f1ed1688f5e3605f06bb3c6ce4f857aa0bc6a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794635b4764d1939dfacd3a8014726159abc277becca0d03c319fe68a91e22fb3b945a8dfc73b817976e29cf57e6c8425e6a02e9bf034a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000849fe1546f8350d001837a121d80845c9d55f29fde8302020b8f5061726974792d457468657265756d86312e33322e30826c69a04bf72e97bcf64717bfd655e2bca9ed1a5253cce5373268729161b1786ca4710488db3c50627f9321c4", + "totalDifficulty": "18787961645682286", "CHTs": [ "0x614648fc0a459451850bdfe353a932b5ff824e1b568478394f78b3ed5427e37a", "0x1eae561c582dbb7f4e041998e084e165d0332c915d3a6da367638a8d24f3fafc", @@ -2555,11 +2560,106 @@ "0x563d7efb4175fc12dab431175b5097186c2379a5aca1901e39d641d02865d426", "0x1a55cf9842f9008e0730ae9fc6af9f288edba323803d0ae787fc0fdda99be8c9", "0xccdf47cee7142cad27bbf224f0afd1a6e5178345cab510f2f8ee27115ab27ff7", - "0xc5b3582937ad993c5c234d059e6cd3b98f2fa4e3fe4ad591ecb6ae710b51fee9" + "0xc5b3582937ad993c5c234d059e6cd3b98f2fa4e3fe4ad591ecb6ae710b51fee9", + "0xd651ab199355d61c49e63259e6a20d17bf72b27891271e5175a24c23fb2dc29c", + "0x800e1e33b0cd48afc6f8f7c69b85902ad93e94bb290b35a862cbad67706a2f3d", + "0x57c7349a6b630cb52c3c1205165df428ed51e25cc167c08739f86bfa46c69e48", + "0xb393d362daff182dafcce65eda9038fc0c8908b3cb1ec1a1218570211c34e142", + "0xb2f49f7a836cd0db9e4743158ff80dd97d23de7a39a0438d19c79c355339c43c", + "0x3f46776ec25b5c67468c32c1b2ca02910a7f46b4b62b5dc5d0cc6b9d3381b958", + "0x754c4ea722e501668aa48d6151ff423263b8a4e2f33b9e44e189ee4e78462741", + "0x12e79ee2724763a8a7f9196bf4d0e855e0ae3f75f5a697d90a263bf562acc5a3", + "0x407b168fea70128a8090ca86274b0b8e7965f16d54ea2b3bbabb378485b22a02", + "0x0d1557ad0cb1466965e6ee86c5ce887eedf462dbec2e719c5f396f8ed95edf08", + "0x29c3a0db9f83698e6ae703174dbeec06f3d2055eb933799e4ae3bf73f4570dde", + "0x8ade20e56fcacb40f54259696bea1aa04d839b88c503d6775d7b4491e0f9e7fa", + "0x327ef0f173632c5049988b312b1f49e9948b02125f70e117ea127088191c32d5", + "0x2989c11c234b7fc5901e168d7adfa655ff6165098eb94d244b623ba43c6abbd6", + "0x10b56dc8f023de6a8f97696dfe2993b56156a9b35f671438fee5830f52b633b5", + "0x46cd37fffe94a01297f2dcef322ae72f58bbf9f58bc9f930cbf56e73f8d5ce13", + "0x2240214683eafc37396f3078446b43ae96bc576e45db650b953ff87a895ee7d7", + "0x0db4d500e5755cba5b962f6b83942e72fd1504cf52531916084852179669a08d", + "0xafc686a8325a30966db0f54b64a4e7235ea54e300d280a4d2a502651a53424b5", + "0x59d46f6fb8eadcf18e31c9fd0da6844d63a2dc19eeeaf9ad5b80113aca5bc42a", + "0x153ae496364bf7c34c8c967e044cef69e401f0e4aff27b04808e2c299dcf15a8", + "0xc85b8d3156729c7f8ff1989f320464144f4918140d608cf03e7dfd5b51ec2acf", + "0x78fd0613f6f5291d4131152225fbded5464841a119d854a7550a1f178a8cdfc7", + "0x763dc1a000b949a45f792515fed6af70047641fa3d7beeb50b141c27b4f8cd33", + "0x42567a1e6caadaa10a13feff343ae1e2a903564affacc48aebc14f257db58ee1", + "0x62c208337234d101cc95cb6be54c17631e26c956758493f5bb7978faf0ace984", + "0x7977aec997a3029025ef789d3492755c80c2d028046aae8c4b926f247e1981d9", + "0xf927505a0c29231ed187a884af15a82dbc48a1cb002f6d91496f6569c673682d", + "0xefd2c54f6d2483a3dd7b994d8afa5441cfffa956d7da6e81bbd1691e07ac7519", + "0x7bcf94d8927a39dd00558763cdd2edaf40d55728d720dccfa0f5e1e827079cc0", + "0x19c7e5115ec25b14bd85e3d368e15d2bbe60451ed9a02f03770a3e845521b77c", + "0x60e32d48de6979c70dcb3e3f068fc3632aba5844703d50851a34975338b3a837", + "0x6722f01dc1d6dd1f0678e5b527155beb0616e33887697a56ef4cc1bac642f394", + "0x59bf17368d69e0379f0f20ec1b1b856298b8d6b4c36354ee765c8a894e58ab9b", + "0xe2559e7b67a15a3ddfbf1ddc597a1309d1fd780fe26da28aace16ad31754883c", + "0xbf687ac704bf02a3877e72f738691bf5027c21f64c68a50235876a8d015ae682", + "0xde01838df621b7368adf4fda268c827dfaa6753a39d51956c0445a2244585ec1", + "0x4ba14d3860d1dee44904719e45a5bfe54dd1e4c9bdafd0a41279e432a021f2e6", + "0xa2380cb32538cc80e07fda5575ecd7b35e0c12932687bd8002da652ad8c16dc2", + "0x82d0f5c8421d6803e52e3d6a37eea0cd978686792a2f6d175d77e9c75fb4ad86", + "0x23701b29d07c64c998ee4bf8199d5ac0f3d9724af2544cc29665a1d92a6dadce", + "0x8bbd490220c823506e111c668f923d18addf5a23d9b5244103cc135c4335f23d", + "0x190506f2d9decb8f9423662f406e61c99606abdcb369e25a1a89c2bdc44c6158", + "0xb9504b090b276cbbf86349bc4dbb66b46a42ce6ae8d44d5cd7f39773fdf6112a", + "0x38fc273344dc7230790963dfb3dedfabe142c18886d6542d77ace8ed6d117c4f", + "0xc76929e9a3a984f6ab6395c4811f007eb6d73a86fe62f8a1c02e860769f2bcde", + "0xc4fc2465f71d06102d232858cfd9737e6e82311a45b1cb2ac203de80c881a2f4", + "0x34427ee5534de01e7f0510b87e6f45aac6210897472978aee3c051c39776c561", + "0xec4f3c6349dac1e7e43b0541b1132b3d0cc8bd422436f31832184d1aa6f9c822", + "0x024a848067a1156852c78495581392774b00f22e32021ca531afeab1aafb683e", + "0x9bdf793e30326a181d3d8fb3f27818475b755e3d1fea200d8c514cf17024979a", + "0x55a1d92354a31354b4b1d9366e98b27c0467b01a108d67dab7feeeda23f981d9", + "0x74614ac3de92173d07434dd80d83aad5c1d551127896298808ad7fba96051e06", + "0x7bdb77183ca1e7f50d292e50ef701ad3bfff3e6e28d36629c5325da03cb8d013", + "0x3a35dc3d12de1053d204410a577b9e5c36d32fbda761f797aee248c27f7dbb02", + "0x430aaeb1dc02bb792375d1702999cda7c384dde1c6f46ef26f1e26e5a55dfd87", + "0xe12805d1713ba730fec6aae824bdcd0a896c6d5e12b9bfa5b6e0a2c2be251c17", + "0x5a297bd3be2352e56136db83a76c7041ef825128152366b2d8f032abb1d6656f", + "0x111782d82f50ea25d684af38689cea53319f1a88557d82c57e46ee5e75f99c05", + "0xe12520cda10064d74fdefba22b5ff4c5eb95508f77fd7c8c3fe82fb89e165bf6", + "0x6af12e8f4db19aee3865c3d681073e7433d902832bc651b8fc3f5fd038c8bca6", + "0x82a4a2ce19ca3fd99007279d62dadba547b6818607800e963b3bc53c5541298a", + "0xbf3a444d1b15d01a29ea22d05e71021ee3581338ecc9e770ee23ab6549a19d55", + "0x745ff92172b5c83cdd69265b919028b350ef95a01c84810366d630162fd9b07f", + "0x6128cd2ff1be9e56396a676362a2049f3e670c70ad2a77be724c090fd4085f0b", + "0x8ffc6bf8165e52ecf30ec955d4be1bb093e6074c92a527382a8892ffa3d3e7f7", + "0xd65bc11ef24c0fa476640d9effdc57030a86f547b7aa79b209954a6abf4072c4", + "0xcd5b5e184a5c0d1c5bdd12f80736ed1a4530210b4ef5f35dacd3feba722a334a", + "0xa80657ecf79ef03fb919bf312e02d94ab528c1b5c3858332d9bf82f807b1c232", + "0xc67dfe4aca5001e97ba6f401f15b72be85ae45972ba98b965a6dd4954d5c2386", + "0x59201e892aeab9e40aef69945585b81b47a7444ed61ba6c6e23e006103ed7edd", + "0xf535c920c5316f12f0bfedc298fbad028dd84161927414b14243c4c5ddd4f4f1", + "0x66c6e42c8137c043eb49528c718b10e5dbad9164bd3ffcc6b55b4b0501dc507b", + "0xa60b9485cb54818e0b0bfe4faeca923915f85bbac0525d09d96f375d0b2b9f81", + "0x8f9377dddacb6ed605c8ed8ed2bc6e2323a4e5d0c9b29bccdfbd27f57a9ec315", + "0xc48a1940c424c2df4803ba8d5573066ce4bbf0e0fbdaa87abcb2d2f51b0a4602", + "0xc7bce918e9f897aeb1351d2c9cbc2fbc8fd674017cb25c49846b05d609f00ed9", + "0xcdaa86e0c026c91954c6305cb7ce6010560f691a2667baf0e95bc18cd3e067df", + "0xf131e0910a8088fc5b0b1d2e93e31632eec67fa88f75bc4f9c3c1b0a317e1d54", + "0xb4f8d72a85c4c2261c7b00f43b96d7d749d0e53359993f52517da36de4c9559b", + "0x73f84bb4774a81b39b3a10d18c7a2404d21f3efd26301dbb7c8136e96304281e", + "0x5559435a987f1444e4ec78b8530009e49c52431b37c7e9f80ce2e056d44e876a", + "0x070664d11ee10c4e0475a7ece219eb0e606e055ee0fa1266b669e593b5ba1d87", + "0xfdfafeba7b5551d1e2d6f179be5ddfdbd0350bd2e9dfea40e272fb608549e8c2", + "0x50a1356bab9b56d8ed46a3e8f55b8a16af42df6b15fcc68aa548216de484c7eb", + "0x681161a307552ff12175074601005bae0c6f7b38cfa6dcb87975a1df205e28d5", + "0x2b39456efc2e8863197c95a4d6eef5069612cc2aa6414f0991393ffa672a1a15", + "0x571b916a82371fafcb456524655758bd42b4f7b768e13807a1a995e642ec205c", + "0xb2821504201eea0e6040a131a709547fc9afb44ba7bfa6a188201735753ba3b7", + "0xb16a8af1bfdde1fae0e28f29c6db0b361840df4b55e73bddffbc1cc11bcc5584", + "0x1df38b594f536cee38acad293a818bf83fc67830fc71bc19790d7733a2caab60", + "0xebb3e8f76f3b6a95285154dc11d4bd94ac4c3a150383ed69f5373499b1983dc3", + "0xb0919ed300acac5f912f01611a428861db27ffb8129a80495f735f0ac608ab35", + "0x2ee321d9d805b78a97210df2977ab62b352705e308773b90e0f4e923adec377c", + "0xee00cb02e9b86978ae10b119924bbe6c38f730c1d1b621d32c9d697e11105871" ] }, "nodes": [ - "enode://6332792c4a00e3e4ee0926ed89e0d27ef985424d97b6a45bf0f23e51f0dcb5e66b875777506458aea7af6f9e4ffb69f43f3778ee73c81ed9d34c51c4b16b0b0f@52.232.243.152:30303", + "enode://d6cb8cba18828397e22e8852324af7e970b57cadbbd94aba6124790d1895728311b1f274e45d44a7a22b4276726903130a11ac2de19af5bc9294998f948eaad4@144.217.72.209:30303", "enode://94c15d1b9e2fe7ce56e458b9a3b672ef11894ddedd0c6f247e0f1d3487f52b66208fb4aeb8179fce6e3a749ea93ed147c37976d67af557508d199d9594c35f09@192.81.208.223:30303", "enode://30b7ab30a01c124a6cceca36863ece12c4f5fa68e3ba9b0b51407ccc002eeed3b3102d20a88f1c1d3c3154e2449317b8ef95090e77b312d5cc39354f86d5d606@52.176.7.10:30303", "enode://865a63255b3bb68023b6bffd5095118fcc13e79dcf014fe4e47e065c350c7cc72af2e53eff895f11ba1bbb6a2b33271c1116ee870f266618eadfc2e78aa7349c@52.176.100.77:30303", @@ -2640,10 +2740,11 @@ "builtin": { "name": "alt_bn128_add", "activate_at": "0x19f0a0", + "eip1108_transition": "0x62f756", "pricing": { - "linear": { - "base": 500, - "word": 0 + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 } } } @@ -2654,10 +2755,11 @@ "builtin": { "name": "alt_bn128_mul", "activate_at": "0x19f0a0", + "eip1108_transition": "0x62f756", "pricing": { - "linear": { - "base": 40000, - "word": 0 + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 } } } @@ -2668,16 +2770,28 @@ "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x19f0a0", + "eip1108_transition": "0x62f756", "pricing": { "alt_bn128_pairing": { "base": 100000, - "pair": 80000 + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 } } } }, "0x0000000000000000000000000000000000000009": { - "balance": "0x1" + "balance": "0x1", + "builtin": { + "name": "blake2_f", + "activate_at": "0x62f756", + "pricing": { + "blake2_f": { + "gas_per_round": 1 + } + } + } }, "0x000000000000000000000000000000000000000a": { "balance": "0x0" diff --git a/ethcore/res/ethereum/social.json b/ethcore/res/ethereum/social.json deleted file mode 100644 index 0768c239f7..0000000000 --- a/ethcore/res/ethereum/social.json +++ /dev/null @@ -1,8854 +0,0 @@ -{ - "name": "Ethereum Social", - "dataDir": "social", - "engine": { - "Ethash": { - "params": { - "minimumDifficulty": "0x020000", - "difficultyBoundDivisor": "0x0800", - "durationLimit": "0x0d", - "blockReward": "0x2B5E3AF16B1880000", - "homesteadTransition": "0x0", - "bombDefuseTransition": "0x0", - "ecip1017EraRounds": 5000000 - } - } - }, - "params": { - "gasLimitBoundDivisor": "0x0400", - "registrar": "0x0000000000000000000000000000000000000000", - "accountStartNonce": "0x00", - "maximumExtraDataSize": "0x20", - "minGasLimit": "0x1388", - "networkID": "0x1C", - "chainID": "0x1C", - "eip150Transition": "0x0", - "eip160Transition": "0x0", - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff", - "eip155Transition": "0x0" - }, - "genesis": { - "seal": { - "ethereum": { - "nonce": "0x0000000000000042", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "difficulty": "0x0400000000", - "author": "0x0000000000000000000000000000000000000000", - "timestamp": "0x00", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "extraData": "0x3230313820457468657265756d20536f6369616c2050726f6a656374", - "gasLimit": "0x1388" - }, - "nodes": [ - "enode://38a3bdd683008f2b404fbd8e59a4ae7377fb1b796be8aca02861a6864304df7f443ae9669d0072d567eb30ab2183556a3cd832b8f2c99246e9a3d9f64ecdc1af@52.78.243.91:30303", - "enode://ee31120190438ca3842afccca9d732d8bfca4bbf9b846fd2bb11178194aa49a74d77ff4801d50a7bd9eb3629f8903661d0fb973e7f43b395263530b390002033@13.209.99.197:30303", - "enode://d538165bf6026602ba9ac296b2b56994e03bb917c73b79cbb11df75a45576fa74df494097bdbcda9bf2c0954a47a65b65674780fa1fbde5bcc89a34870d44983@13.125.206.82:30303", - "enode://67b5de9a4562ba0a01877e3876249c8e551844424773bdbf9713d126b3f144ac7a49d8eb06fc9830871f03b50a7d9b5d98d9d1be5544aef8afcaa10eea2fb9eb@13.125.68.29:30303", - "enode://2d31dd1f8acd956cf36a1c3f27e374f5b94c55df4206749b03a6d0a50366c8090280c91f71aad00886cbde6ebbfcabeaaa91bd910b16e4fb398b337e9ecfdbd9@13.125.232.71:30303" - ], - "accounts": { - "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, - "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, - "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "ceed1c8254abaf069669fc6045e90482543d1f2e": { - "balance": "38000000000000000000000000" - }, - "6f22d7f8c38e0135e36be87e77fc8d4ae4b3d965": { - "balance": "38000000000000000000000000" - }, - "d016e982b7886302428d7c741392c658337513d2": { - "balance": "38000000000000000000000000" - }, - "defa96db5c8a41772bc56f68f95e307ff71a2c60": { - "balance": "38000000000000000000000000" - }, - "951ffd4253ffcf31b2895dd3f7f2a8a9bb2933e5": { - "balance": "38000000000000000000000000" - }, - "b7071dba21cfbe1b70abd7ddfd2f0f83d5d19a61": { - "balance": "38000000000000000000000000" - }, - "6ca420cd8d5407c61a9b14adcb38bee0f26e2848": { - "balance": "38000000000000000000000000" - }, - "b50d185b6cd04499a38afc0fcfcb59eaa74d0956": { - "balance": "38000000000000000000000000" - }, - "7ba8c49a444c117f2d2a50650b3f700d4ee659fe": { - "balance": "38000000000000000000000000" - }, - "83f9959ecc532dce071fcd0c62dc23cd571b689b": { - "balance": "38000000000000000000000000" - }, - "001327afce7ebb623a7d0f17b2ffc358fb863b5a": { - "balance": "9844198127334000000000" - }, - "0015ac7f8bb2a2c7d954fc2dbd4e20c0db5942a5": { - "balance": "1000000000000000000000000" - }, - "0021e69c041be2d28744b69361105ff51295da59": { - "balance": "1379639894000000000" - }, - "002cfd27bbb8164681b8762e71b2891beb127fdd": { - "balance": "25105286685000000000" - }, - "0033cf217bc765ccfc338869451588ce448fde65": { - "balance": "23425485280069000000000" - }, - "0048f1d1735979cd8ac9c0886088336b2d4a43a6": { - "balance": "10000000000000000000" - }, - "006a79cc154917cf204d8097728f290e29716d43": { - "balance": "20000000000000000000000" - }, - "007c8db36e4f649b14516dd78202670b671ba753": { - "balance": "1000000000000000000" - }, - "007d131b58388f251075a3c61020ce301106c5cf": { - "balance": "381079535880476000000000" - }, - "008e8fbffc2fdbefaa7e3be4f4a9160db826d05f": { - "balance": "10000000000000000000000" - }, - "0126d86b9814b0e78c4e01a3916bee6a7778145b": { - "balance": "10000000000000000000000" - }, - "012cb961297c837630251a173b7861e77724856d": { - "balance": "494562376059000000000" - }, - "0145886dfab5ef4f2def50a56b4a074cf5b18acf": { - "balance": "680585022951000000000" - }, - "0167918bab62aa2118cfa4d3eb80da0e71c71d8b": { - "balance": "122395119468000000000" - }, - "0182f7286ae9d4d6bc514d5175d14685d520bde7": { - "balance": "10000000000000000000000" - }, - "0184e9c8fe99d85100fe28a0e8877b14768b372a": { - "balance": "193295614762000000000" - }, - "019eff7dce7f31c2d4f7318da71d212cbf89d36e": { - "balance": "64004138198000000000" - }, - "01f3351ea66c352346244dbb79189066bed62fc5": { - "balance": "937056266523000000000" - }, - "0202ddd7f4f32bc575f7df24612f8aa9f9a7ae42": { - "balance": "106905151080000000000" - }, - "022b8c65e959cab71f56688b7073257b58bbef4a": { - "balance": "9682681149566000000000" - }, - "0245ff6382eb93ab1e8ed2e3c0bce7a1b9a9713d": { - "balance": "289000000000000000000" - }, - "025e117a69ca9244ed430732c11e550e3ee67577": { - "balance": "1861905310567000000000" - }, - "026e7457eeaeaec7898fdee1ad39be89e92733b3": { - "balance": "7529030978000000000" - }, - "028d2def8c54fcc77bf0191b183c0bc4570ec1c5": { - "balance": "9056720934000000000" - }, - "0291a087605b516e465134797b5459436d320e6a": { - "balance": "481100929805000000000" - }, - "02a4b18b3e13ec79307e712fba1867cbf7fb6155": { - "balance": "9000000000000000000" - }, - "02a812d4cebcac1a92ae470ade92fde7bead127d": { - "balance": "66793603497000000000" - }, - "02f718c94b2c8e8d62752f8632443504c1e4b6e2": { - "balance": "1000000000000000000000000" - }, - "030dab52b47b37505b72e5ca0985f65ead590816": { - "balance": "1376851176362000000000" - }, - "031c59846f75de1aefb0e8a95e0fb822fd06555b": { - "balance": "140978338628000000000" - }, - "031ee87c672d83ec73059c86a312a9e972142054": { - "balance": "96406273341000000000" - }, - "033182e860564cf695cb403c8c0f078053368d7d": { - "balance": "1504349255824000000000" - }, - "03788dc6528fa33a90e90e03295ae4b792d56644": { - "balance": "24356250426000000000" - }, - "037aae119047028157c5b3bc9d3d202b02cbce42": { - "balance": "105627739575000000000" - }, - "037d45b323cbc5cbac999c5001169646e690b94c": { - "balance": "2000000000000000000" - }, - "0390ba35c454a24519d845405a7e24df71250748": { - "balance": "1872501898509000000000" - }, - "03ab8c1e7f904db62437b16d28aeb539b2dee55e": { - "balance": "55000000000000000000000000" - }, - "03af4c69728a888fa26b1aefa439005989771fdf": { - "balance": "27704588237757000000000" - }, - "03b33fb19d165e5e33bcfbbfc009f418d71f30fb": { - "balance": "1999139000000000000" - }, - "03b34c79f8167a4e8be0f6133254d2b50cbd878d": { - "balance": "111065050160000000000" - }, - "03d7e8638b74ae44a2770287285489a95fa1ea11": { - "balance": "20000000000000000000000" - }, - "03d870bf719f03250c0dc5156a36751b3aa21f18": { - "balance": "981119649953000000000" - }, - "03de52c12b05fb8bcba3a1cfe02a0ad1bc9761d3": { - "balance": "362007990932000000000" - }, - "03e516db27b1abe008ffc57ced48f72f872d8b08": { - "balance": "3389116345657000000000" - }, - "03ef5ff863ee5f1167f38cdf316e4d52a242b750": { - "balance": "12395856876000000000" - }, - "03f27766760f2bd1cae1cb85ddf43ab59c871e47": { - "balance": "49000000000000000000" - }, - "03f4e1a8fb4eedc776f4835fcc85d0f236612f9c": { - "balance": "27210590272692000000000" - }, - "0404936ee04cc79cbb3aedfa33a53f94940f772c": { - "balance": "29919204637416000000000" - }, - "040501ffde9649be794b7d41643273ed6285ab39": { - "balance": "686000000000000000000" - }, - "040e449de680f69614120f0a2e894cde36e4adf1": { - "balance": "81993180085000000000" - }, - "041531e906dbdc70d89f5e255151d9865a059308": { - "balance": "2163418749315000000000" - }, - "041ad9f6bf970541e4ea8a14dde1e789d0fe4367": { - "balance": "44999979000000000000" - }, - "0446420c07cf73d2b3741b945c1cc8444b4ba6b6": { - "balance": "138749371512564000000000" - }, - "044c1a540b8ab286c218c2fa9d5bfbc2761e7626": { - "balance": "1" - }, - "04526b2c62911e78a939816aa4575fe30baa06c7": { - "balance": "2983093150081000000000" - }, - "04adf59f8a0ad3820a7972c6243202b3b0617fcf": { - "balance": "50000000000000000000" - }, - "04bbb42882a475eed58aae47fe530ed19c1cedaa": { - "balance": "278038763863000000000" - }, - "04cff7a7c2b9b0bf31c5ad4a5de8b0eade70aafc": { - "balance": "515406205244000000000" - }, - "04dcd325dc1fd37ff3c87da3b21c47ddfcc37cc2": { - "balance": "5831887315000000000" - }, - "04ec8d0b5157370f5a2671a2aa68ae486b7a7842": { - "balance": "10000000000000000000000" - }, - "04f50f2a6e89ee497a64c11baa90759a10a1247a": { - "balance": "25443071621949000000000" - }, - "0513a769ebef58ad3a4fd7011ddbe19799ff5600": { - "balance": "64369494797000000000" - }, - "0514c1151f356070ace281435f25c86b58280715": { - "balance": "38967380881301000000000" - }, - "052fda414fe1279c6276a237b07e1b4148a8cc77": { - "balance": "10000000000000000000000" - }, - "05431089cc62a987d0e99847e10a006233146f6d": { - "balance": "268977485219000000000" - }, - "054ed2f55028257212b996f9a3d34758d1d4ffd1": { - "balance": "100000000000000000000000" - }, - "05a68cc758560addde302baf814f2fdbe0ef2c2b": { - "balance": "10000000000000000000" - }, - "05c669d9ded79fe9e4e3718052bc7ca18a3205ab": { - "balance": "7347158140000000000" - }, - "05d77ce5c87477b05e90e829dafd8eb3a8c87823": { - "balance": "21191998933000000000" - }, - "05ef2894a2a1c6eb6c0a768d04ef5b573f357712": { - "balance": "20000000000000000000000" - }, - "0601011f80279190b96f641205c6a524a8ad5a28": { - "balance": "12025716447696000000000" - }, - "061a8acdb1a340ba7c550814831e27262708fc98": { - "balance": "234029764576000000000" - }, - "06219483e217c9ad479f76a95426f689ef4d5951": { - "balance": "1509408723551000000000" - }, - "062d0db8a650f2241f8a4295326a2570a7c771bb": { - "balance": "717459720227000000000" - }, - "0633ba746235d8fc8243751b1aa31646c299f262": { - "balance": "49000000000000000000" - }, - "06b6a5cadfe1fdc88015512e835d840e58ae4123": { - "balance": "1000000000000000000" - }, - "06d08fcbe96791514d900d2cb6c0f029d8d791d0": { - "balance": "19196168602258000000000" - }, - "06e5c0bad43a7011878b12a682abf01ccdfaa151": { - "balance": "30000000000000000000" - }, - "070656bb11ec36074d47c791c0b306394b703401": { - "balance": "1245216075291000000000" - }, - "070d84c938217163b60ed38e4937eea7158c03d9": { - "balance": "27507979787000000000" - }, - "07428c95ef3862026e54d3a963911cdc673dbcd9": { - "balance": "13792309994528000000000" - }, - "0781cb21df142ec5f67b956bf995f02f6f24985f": { - "balance": "224940990659000000000" - }, - "078c38c153b414cc4c12818fce2ea7ba09a34e51": { - "balance": "1410646136000000000" - }, - "07bfd0de7a9a1c927446aaf2d7ede55b471daa87": { - "balance": "77778844734000000000" - }, - "07d1ac83140188b8d7f4c8c607d0da22c5ba523f": { - "balance": "7713686418107000000000" - }, - "07d8ef8fc6dcde319a5af5b6cea18983bdc4c8fe": { - "balance": "3801361173000000000" - }, - "07dfab72dd3e44fcbb1ced625899bf20e0c52ffc": { - "balance": "154177778806000000000" - }, - "0817ce33d943e84c7b3261cc3e37b86b5d6d76ae": { - "balance": "90753785862000000000" - }, - "081be00a2ff62cbcb95a8eb020ac0efa33f93a42": { - "balance": "1027889807304000000000" - }, - "085ffdc6043b04653e51b1a34af20b609d158607": { - "balance": "3314058000000000" - }, - "0882c2228f5df24064bc37e8b7199199de308bb8": { - "balance": "98420617420000000000" - }, - "08918776e9a7136cedad5d0cee52f5d9dd833ece": { - "balance": "1263170315026000000000" - }, - "08bdbcff16919abc5e15fa68ece56eceef33f48d": { - "balance": "2552990000000000" - }, - "08fc8c7bd03fe1249266b233edfcf830693d0e10": { - "balance": "283490111768000000000" - }, - "090f79a4178b5180150444805f62c26cd21be897": { - "balance": "884195010282000000000" - }, - "0914a9dfc9d6ecc063a55e5320050112f305fe17": { - "balance": "15373898854941000000000" - }, - "091791ab5f8ab86f1d8f566ed221b268cbc55347": { - "balance": "2207516004000000000" - }, - "09529f8b1633ce4375451bb44b1025f6e5f9facd": { - "balance": "151697652792000000000" - }, - "09600bbb9d9b23661d269dbe1ed066d8e573b5e1": { - "balance": "802935104935000000000" - }, - "0964d2af1d5883fc0e0a77459f6a141824de7356": { - "balance": "9610980935058000000000" - }, - "097c731d1fc6792ac0f0ff92be4403c3749cc1dd": { - "balance": "165134479709000000000" - }, - "097f152b3f837d38ab1e8c0683d62f5a01d67902": { - "balance": "20000000000000000000000" - }, - "09a6772629ef0bf402ae6d27cd32e6eefb220a12": { - "balance": "20000000000000000000000" - }, - "09addb954d4e4b4e95e0c66d324115d609df5a99": { - "balance": "8435321515000000000" - }, - "09b2eb03e0fa321102196578eb40dcba3a46ec9c": { - "balance": "12723517962933000000000" - }, - "09ba0ed4dce470ba0bcb4d46b507c3b024b83070": { - "balance": "99999979000000000000" - }, - "09efbd6dfea375065be1b3a8f4541f024da21a34": { - "balance": "5870833623000000000" - }, - "0a24d4ae66edc7723bbb314e9b96dc7b9a31e813": { - "balance": "70000000000000000000" - }, - "0a3ee710909382f762648deff8ac7c8b30e2ce10": { - "balance": "407656462445000000000" - }, - "0a42b3145257154e76a97db8147c93be4cffd97b": { - "balance": "10000000000000000000000" - }, - "0a7cb6037f1eba5d19fe781335ecd37b7229c5f7": { - "balance": "74113322448000000000" - }, - "0a85d1bec4d44e309068b115abd517d3733fc56e": { - "balance": "14836218750000000000000" - }, - "0a891ba9ca7b99ecd815b1dcec9243dd4deff866": { - "balance": "178004857988000000000" - }, - "0ab69370b537d4ff5b45704fed293e46e3464f87": { - "balance": "1258876668246000000000" - }, - "0ab77a2e8ab9a3b659d1f1d37956c3607a0f9a60": { - "balance": "6283300817712000000000" - }, - "0abc7e8d52f5b0dcf1d4713e5fa4909102251dfb": { - "balance": "39307290577000000000" - }, - "0af2c0471c802d2e2b20aadf9dd4ec842d313ab0": { - "balance": "1529468143183000000000" - }, - "0b08c717bb3982fc8b92d5b3d30e5b41265a0d0f": { - "balance": "1184600154874000000000" - }, - "0b3f2aa9dc5b57b0469398d62f60a13774ec0e87": { - "balance": "132187640280004000000000" - }, - "0b3ffe85aa89e71a6e51e938c7265d2a7173061b": { - "balance": "2106793086824000000000" - }, - "0b468562e712d22b37e1a65f54b1fa825beebd1b": { - "balance": "15130906006000000000" - }, - "0b5333eb668dee29ebc0e335d74f33ffeaae9ac5": { - "balance": "125953133109000000000" - }, - "0b59a20107495e951b509187307782ca9dfa441f": { - "balance": "25000000000000000000" - }, - "0b8b7fb066601ea7744b81f6e1a21b8e489359cf": { - "balance": "101782000000000000000" - }, - "0bd7791097f79066d71ac0a2c94bce6628a63373": { - "balance": "44389955028000000000" - }, - "0be541af06e167206b5d1cbe08e8fb2b5ebc82cb": { - "balance": "9000000000000000000" - }, - "0bf178bba463f4f6c33e3d81b1a78d220f7b5d4b": { - "balance": "111784804790646000000000" - }, - "0c1f000249b1f1ac9e43c4f10e2da1cc2adf886f": { - "balance": "91251997635000000000" - }, - "0c74e46b115e19726997dd559d2b6ff1bfb79af6": { - "balance": "879229287149000000000" - }, - "0c7c1ec152c920a068c25626c22c4fae7f435536": { - "balance": "39849464104000000000" - }, - "0c85fbd7492d1ae87bf3d286c4750a34f1fd3121": { - "balance": "20000000000000000000000" - }, - "0c9fd6123e313f7d1f0cb25d99839102da08b2c5": { - "balance": "10000000000000000000000" - }, - "0cb051e3bdd9d96e667fbcc00a766d4f149f89e4": { - "balance": "1000000000000000000000" - }, - "0ce32bf6c433cbd26c6f09a1214db0374002784e": { - "balance": "3293279842000000000" - }, - "0ce6374ff04430e34edec8b6323feab2bccab92d": { - "balance": "93983447000000000" - }, - "0ce646412a1524c3f73edfd753c0ba3ee7338275": { - "balance": "10000000000000000000000" - }, - "0ced803e56eac3c99269ff7409d2d200d62d7c25": { - "balance": "49539379000000000" - }, - "0d1dc2be9f78ce2b2591e7f5b8af9dc778499bd5": { - "balance": "2235348003595000000000" - }, - "0d235583458a168e810275f907b5f87bebb2d1cf": { - "balance": "83106439283110000000000" - }, - "0d28fe6e8b7d4b8c90ef7c52b9656511ce5867f1": { - "balance": "1347248794799000000000" - }, - "0d5cbe0da660cbca831787efc45fecb20e06e02b": { - "balance": "297528508941000000000" - }, - "0d7a24f324176f6d793c3a2eb6c54d6ee47eca79": { - "balance": "25637813467000000000" - }, - "0da26a24e3650e84c52fedb36ef76225a8d9d259": { - "balance": "15467820321000000000" - }, - "0db7eaceaf3df21ebb49c56fa2d2e2c8e85dec52": { - "balance": "196000000000000000000" - }, - "0dde52823bd8fb2cb179e6d417c07ff285c31775": { - "balance": "347321514878000000000" - }, - "0df9585f1aa83189e0a813f5eac6e6e0b2bbb8d8": { - "balance": "2891430551000000000" - }, - "0e09af9368f05b476164953b7b9db60ac95248f0": { - "balance": "573644391203000000000" - }, - "0e18315dd2b663ce4859b5bed854403191452c2f": { - "balance": "24174325261000000000" - }, - "0e29bef5f4f66c38a0f05cca1e4938d57ff09c70": { - "balance": "10000000000000000000000" - }, - "0e443353b42e042ff5168e9b3c6de37070368223": { - "balance": "20000000000000000000000" - }, - "0e8cb6e439516b312158f169b546937b715db3f2": { - "balance": "8049136367000000000" - }, - "0e980fab23be601f3abec7b9a24e1335a5e765c8": { - "balance": "8301885845897000000000" - }, - "0ea63fef218ebf570a4ee62ef6ed712dbe623c44": { - "balance": "10000000000000000000000" - }, - "0eb60e3512336e4447ceeb8664ce0ecaa3eb0bdc": { - "balance": "41401696400000000000" - }, - "0edafc1058879a9568e711445b18ec4da31d2480": { - "balance": "10000000000000000000000" - }, - "0efce4565062b23b43dbc1e261463e363e4a5b4c": { - "balance": "10000000000000000000000" - }, - "0f08782c04bf7249ab08f4e251abc60aee792a96": { - "balance": "1380257622493000000000" - }, - "0f19bfe1eb24def828bf1be69791c63ba1de1263": { - "balance": "2223687184885000000000" - }, - "0f2171161eb9674218add261be61d18d86b846a6": { - "balance": "121000000000000000000" - }, - "0f42ef6c5690b6c95f8b8c9dbdc16f717c04852e": { - "balance": "81000000000000000000" - }, - "0f47f5063d321b34a0d800951bcdc3f53c07e32c": { - "balance": "5288516165000000000" - }, - "0f529a9beedb2c2a087a220f0013cea4f8454bfc": { - "balance": "114585457979000000000" - }, - "0f6751d10aaf855454a6e9e4241cfcae3b0ed732": { - "balance": "94160300063000000000" - }, - "0f6ed5a4c3ec100afcd59e9066ba7fcb63cfa6dc": { - "balance": "1000000000000000000" - }, - "0f77025519cc76c38e1cf0bd8721f4a5b9c814d4": { - "balance": "834620571043000000000" - }, - "0f773db2a1a96b775e4481575704f5f087b067e0": { - "balance": "554268361745000000000" - }, - "0fa0f73adbe82f8e09f8adbce15b051971e289c3": { - "balance": "11329911975000000000" - }, - "0fa6397d747d88a25d0c755b3be4eee0e3f68912": { - "balance": "31394936138000000000" - }, - "0fac8635a61bf7652d86725cc75c307949bd4f2a": { - "balance": "49000000000000000000" - }, - "0fb0ce787306ce13dcd614ab3d0e15d9772106ac": { - "balance": "50000000000000000000000" - }, - "0fb1d306d240360056f60f197dc7f68f732ac515": { - "balance": "20000000000000000000000" - }, - "0fe3571f498a6d945e123ac8ff6e3fed348d9432": { - "balance": "20000000000000000000000" - }, - "0ffd6b01ea9a7bd2576fe4a5838fe09e44c1639e": { - "balance": "100000000000000000000" - }, - "100bde3d73fda700369e78229127b58d2ade9177": { - "balance": "10000000000000000000000" - }, - "102028c7626970a28677bbdc7733484c8b14c2d2": { - "balance": "500000000000000000000000" - }, - "10245044be6a46ad41d4559129cb59e843379cf8": { - "balance": "857437279765000000000" - }, - "10417d0ff25c115b25915dd10ca57b16be497bf6": { - "balance": "10000000000000000000000" - }, - "10579870e6685ed7e97dd2c79a6dc3528bae968e": { - "balance": "5187866041491000000000" - }, - "109736465b4bbe31ea65ad01fc98f04498271e6c": { - "balance": "20000000000000000000000" - }, - "109c0535a4a86244c5094e99167d312a77657dd5": { - "balance": "138277702073000000000" - }, - "10aa08064689ee97d5f030a537f3cd4d8bbdaf74": { - "balance": "10000000000000000000000" - }, - "10d8bc8c3d3e2010e83009290586ad85b73321d1": { - "balance": "25000000000000000000" - }, - "10f22b82460252345753875555de2cebebe63a93": { - "balance": "765947730644000000000" - }, - "11111c3a2cfa55e52d6aacf533e1d412f8c8c01c": { - "balance": "4827254128275000000000" - }, - "11386103a0bf199db9504b617ccb3bbd780eb9fe": { - "balance": "10000000000000" - }, - "1156a129183e5bdfdf2bf7a70963285a979363a0": { - "balance": "10000000000000000000000" - }, - "11589cf70a6a4fbaac25224e2ddab222333f78e6": { - "balance": "49000000000000000000" - }, - "1162fabeb3eb1e4124179b00c4a1e01503023f54": { - "balance": "817145350625000000000" - }, - "116a7d140f4b7f9b4689063a8417ac07a32bae00": { - "balance": "106088220142108000000000" - }, - "116dc38ddb4b138b19ce6a51e5922c287da5c86b": { - "balance": "100000000000000000000" - }, - "1175f84f835a5ae40d49b8ca17e3e474c1eceef7": { - "balance": "1698584794716000000000" - }, - "119f822a796fee9c41a488949fcb14b589ffa628": { - "balance": "20000000000000000000000" - }, - "11a99f6019b6a53f5dc8cbd0c34f1ee75ced33b8": { - "balance": "102126982156000000000" - }, - "11b9324406068e8bf598d3a9ea59ef31c52f51fa": { - "balance": "6525925895203000000000" - }, - "11cb7be6869a10f5f9e8a47c6c92f729b083084b": { - "balance": "182959434323344000000000" - }, - "11d96a76166ec579e2b6cfa903f66da4af669351": { - "balance": "1000000000000000000000000" - }, - "11fcee55f78278df60f50096d45da1aafe72722d": { - "balance": "222859488179000000000" - }, - "120a1fc914718acd85bf92d9492330165d78075a": { - "balance": "3736627235906000000000" - }, - "12366136d83c77befdc30e04d4f5d808419f504f": { - "balance": "88008649003000000000" - }, - "12435af3f2f92ec43e8f2894be9c72fa932880fe": { - "balance": "1590548436852000000000" - }, - "124ff67125a00aed24e58b6d64ffa887a59b48a4": { - "balance": "20613022349070000000000" - }, - "1296f04910ebc89556ec7ab1b178fdbf14d0295c": { - "balance": "36000000000000000000" - }, - "1299f180e42bfaa1162d36110d29ab062e43e1c8": { - "balance": "321570118362000000000" - }, - "12abac62150c526866ec958cd0e3721b2c78d550": { - "balance": "51898545633262000000000" - }, - "12b345087cee385b9adccaaaa6741b767c82d7ea": { - "balance": "36000000000000000000" - }, - "12cd5e8c0c93f8e34b589b95954b719f54d1515b": { - "balance": "1000000000000000000" - }, - "12d262cdd25edc39b6fd9ae78184eb548e513927": { - "balance": "500976168000000000" - }, - "12d933448218629702c48547b3446b629ec65883": { - "balance": "2168010577395000000000" - }, - "13054aa42d3e119220ac359641c15f8b54bfffef": { - "balance": "24986834005530000000000" - }, - "130bda09f463a982199849ae617062a1d68f3a85": { - "balance": "154504844790000000000" - }, - "131a5da679863c05dc627d53634f2925ba0ce731": { - "balance": "10000000000000000000000" - }, - "1334f2752b5c21f681ba9e23a9fe95a85f8e05f1": { - "balance": "121000000000000000000" - }, - "13634512e2ae79fe3febb9e55e03b47bc350d7ba": { - "balance": "338331304738000000000" - }, - "136fae842aab625768bef9079ee1711e8c007d8f": { - "balance": "2759741687626000000000" - }, - "139fa969e8b74bee1f6113a362f15060ea998b15": { - "balance": "10000000000000000000000" - }, - "13c7e1d694bde6f8f6a31eb6c99f38dc739d61fe": { - "balance": "10901074773586000000000" - }, - "13c849944ad6ad12a46c46973d562bee8284f46d": { - "balance": "35114615504000000000" - }, - "13ec3aa8f4a427ecdecc7901060ccac9bea7a61e": { - "balance": "10000000000000000000000" - }, - "13f478c74acfd6897d13e602a8d362893f4fd038": { - "balance": "3521111850000000000" - }, - "14403970d0784a6458a7bf2584a53d14234e8860": { - "balance": "25000000000000000000" - }, - "14440bb7410337e34a064a92206075575f5362ee": { - "balance": "14918844868393000000000" - }, - "144a88e7a8af70b8bef5c4b70ee0cff771d0c252": { - "balance": "67961927542000000000" - }, - "146b79f474176a4b0069199b03669ab6467a4787": { - "balance": "122518123211000000000" - }, - "148893e7811c36c6bd1ada367681ab8327b3b2fa": { - "balance": "1313118418375000000000" - }, - "14900a17784e3b4d89d98b6cb31c74c685418b89": { - "balance": "131112181597000000000" - }, - "149a483758a98ffe28f7f25cfa17d7433f852ebe": { - "balance": "10000000000000000000000" - }, - "14a03c8e84f07c5596687a98d1e0b1859e9b34ac": { - "balance": "55000000000000000000000000" - }, - "14c7899cb34b5447d6363d4e8355113ebf4bcc66": { - "balance": "197554844582000000000" - }, - "14efa63ee285277c0f8e0d5cc22193e17984e11b": { - "balance": "106221254735000000000" - }, - "151c6099b3fb5b18e0e36a3335dff186dcd2904d": { - "balance": "4304311254087000000000" - }, - "1525dce233a971eb1387f130fdf0e5bf3455723b": { - "balance": "45004174531000000000" - }, - "15271904676f2bc2511294e500152d05ea9acc85": { - "balance": "9300898622566000000000" - }, - "1556ba42ea69d72c1d0faf802906645268e36aac": { - "balance": "171939212653000000000" - }, - "156558fb71ff986953d899c9916a121fd047675c": { - "balance": "290926338537000000000" - }, - "156fbf32614aac2cf462952ec1a3f141f797316e": { - "balance": "6084388860000000000" - }, - "15b9497d6bde8017baf3c29e12430e05a47efbf4": { - "balance": "206126229839000000000" - }, - "15d532e828bdcaf1246696d679a2eb66a154db5d": { - "balance": "69656571015000000000" - }, - "15e26a60cfaf23dfd9bbb999a30904d11b6ddd05": { - "balance": "9839303178835000000000" - }, - "15f3be2f11ee3b19472cc3d171931f050d8629a2": { - "balance": "13572825921000000000" - }, - "16254bed335420e5f793de2295b0081ac41a08d1": { - "balance": "144000000000000000000" - }, - "163aa91bc2ad588116141d48fcbd943985455cac": { - "balance": "618250979557000000000" - }, - "164cff4b9341d536b8aaf2d1dd0e3ed35ecb1db7": { - "balance": "671554639913000000000" - }, - "164d2a9a63868ac25bfe26ecba446d7ce256c351": { - "balance": "7233638188261000000000" - }, - "164e759b64d3ee0a23ec3030f50a1b454a6ec15b": { - "balance": "12281161499000000000" - }, - "165d4a0f23c016b8064adf0dcf7e31bc06350777": { - "balance": "256757922324741000000000" - }, - "166b862954dacddc3333aba4edbe523d693df858": { - "balance": "123677971414000000000" - }, - "16858eb1a6f0e7ff01b91aa9c92d0a433a5f767c": { - "balance": "500000000000000000000000" - }, - "168909a1c2a43cff1fe4faeac32a609c25fbd1e8": { - "balance": "62258808044224000000000" - }, - "16987ad8e10dda7f9e5d95c0f0ee36f46b10e168": { - "balance": "10000000000000000000000" - }, - "16b5dffce79573300a6514ace5f2e844d26fc64e": { - "balance": "5576805697087000000000" - }, - "16e01370a93befe24f6ae6076cd04c84cd3515b1": { - "balance": "1922179181578000000000" - }, - "16fbafd4fc871c7589e63062133793ab244c2019": { - "balance": "2865030627000000000" - }, - "16fdf76180796c6e4335eaa2842775b2e4a22e0b": { - "balance": "20000000000000000000000" - }, - "17081d4d6ebb9f4b163e181a59c2102c99fce6bd": { - "balance": "490625378000000000000" - }, - "17218ff455aa87b29ad4c4f7ba21e9c6f74fc97a": { - "balance": "1607392037652000000000" - }, - "1725bce47f3700f4646efb343f950e2e8ba66607": { - "balance": "58472967071000000000" - }, - "172c5f71aabf072507664471ebaa435779d74a32": { - "balance": "16000000000000000000" - }, - "173a065f351ee0513cfebfe9b950fd2c641fc8cc": { - "balance": "25000000000000000000" - }, - "174e1793c96cefb584ae0a67fff85c65065dafc5": { - "balance": "50221000010000000000" - }, - "1794bc4d622d514f95da5404358ed404b3f59aa3": { - "balance": "36000000000000000000" - }, - "179839d61e7c7a0382fe08e0573bcfbe42a108ca": { - "balance": "203299791419000000000" - }, - "179eb30b5b28a961eac70a919d26ca96e6472166": { - "balance": "55000000000000000000000000" - }, - "17be72168606fb5d27761157e48fc14789f84634": { - "balance": "311205588354000000000" - }, - "17cefb6611033759b8755197b983de2d7e98315e": { - "balance": "10000000000000000000000" - }, - "17e07cc7d89bcd1708b1f05ab6e1252c629d71cc": { - "balance": "903234908997000000000" - }, - "1811be559b657685c2f163122479101c404325b0": { - "balance": "10060694170000000000" - }, - "181417a4883c429ef26a4baeb48e70d4f00278b4": { - "balance": "4621446218088000000000" - }, - "181d345cd6b5f518bdab8d40f5d4896a725b3f3d": { - "balance": "114349561983000000000" - }, - "184625e544aa31552d2911023a892f739df84be7": { - "balance": "5303698708000000000" - }, - "185e4f6eee203ca3c089baa1e643ff1aab7cc8f4": { - "balance": "33969718257699000000000" - }, - "188e4a1a7b23ff35ec90b7bf7561db9e3c0f53bb": { - "balance": "394325508701000000000" - }, - "18a4dbf513be132f9ecfd69e3eb683d710e28c4b": { - "balance": "5997985132329000000000" - }, - "18c9298f62635ef47d0ef215b8a693af60829c27": { - "balance": "100000000000000000000" - }, - "18e7e2ee0c86bc1ba3595fee3d40257776fe8172": { - "balance": "185584626033000000000" - }, - "196575e74499b741877793f8c8facf2f3b1ddb8f": { - "balance": "30318381929000000000" - }, - "196df33f2d3ed473e6e07650419969f4a39fd03b": { - "balance": "15442864665000000000" - }, - "1975c5293ec9c72a28e6cc74173cdfd8de682fea": { - "balance": "103624886552134000000000" - }, - "19832cd1b2fc4138c8d9291a0f404d3c4326b48f": { - "balance": "4732362673000000000" - }, - "198705f46f31c7ca22f5b88fab210bc5b0c7647c": { - "balance": "548940869737000000000" - }, - "19a5a213e6abfee29f17e871222cbe9ac45322c8": { - "balance": "10000000000000000000000" - }, - "19ab9a7a4e9f9c08c9b4295c406b78389a864ba7": { - "balance": "369299839157000000000" - }, - "19f19f5f01b3f6a1c4f645dc7e3992b1196ccb7a": { - "balance": "97759406000000000000" - }, - "1a11a0b0081522e60e16f154e093ac2e005d24ee": { - "balance": "88024675252000000000" - }, - "1a27309b0c09be2234fd64afdbcfb099f8e2e7cd": { - "balance": "10000000000000000000000" - }, - "1a3d61754974bea23503a61ef0fe584b7b6e6cf3": { - "balance": "326950210355000000000" - }, - "1a49bbde1457a8d4c247606b206ac8d4d389da5a": { - "balance": "402438941516000000000" - }, - "1a7a4b41be64fff3a31eb6166db59741e073d0f7": { - "balance": "250000000000000000000" - }, - "1a8d282e82c606e992f69ce618ba634d98bf2683": { - "balance": "20000000000000000000000" - }, - "1aa0ba27662816e5e3d79e223cc18f5dfef089cf": { - "balance": "187581622694000000000" - }, - "1acab416a1d3e8caa65faca378c79aaf2065b851": { - "balance": "1000000000000000000" - }, - "1acd37af3f87da1dff743dfcb97038d178b1dc4f": { - "balance": "708034481300000000000" - }, - "1ad8f036022c3e5258455d6aa05fb4be5dd121b1": { - "balance": "42957064709000000000" - }, - "1aee811e06c579c21fbcc3b53d2dcf9d5f24808e": { - "balance": "52480060284048000000000" - }, - "1b03b7a4e9908c3531618f49f8d050ba6afb4de6": { - "balance": "28410489187000000000" - }, - "1b073d026e93de51db34d5a8e19047784c277ea1": { - "balance": "20579129628026000000000" - }, - "1b0b87e414bc8fe4920fe104b6de7d17db3a1a19": { - "balance": "10720000000000000000" - }, - "1b411c692c80948e59cd805a0f8574dd67519288": { - "balance": "5416615538000000000" - }, - "1b8d57e995749618c7bb3e60194ac6fc57e9b3eb": { - "balance": "10000000000000000000000" - }, - "1b913efde1255516346b40ae2a48ebf62251682d": { - "balance": "100000000000000000000" - }, - "1ba7276c133f93d43db2f2caddec08e0167eaf15": { - "balance": "82559173174000000000" - }, - "1ba919f7742160cabf2756eb6eae67b92530f3f3": { - "balance": "1102304139883000000000" - }, - "1bb20857de494694fe15bd11f8cac1218435fbc0": { - "balance": "10221322567000000000" - }, - "1bb5c5e81d451f03e899852edc8556a9f7aac5df": { - "balance": "18781017696028000000000" - }, - "1be3507349ed07d3e7902951d490f560a75e96be": { - "balance": "660691718918000000000" - }, - "1bf1c0b2e6f64b612f35f2bf98d894b13dda9bf7": { - "balance": "3050161851140000000000" - }, - "1bfd3c2ba6a537e97cedd542cd554a5050963d54": { - "balance": "20000000000000000000000" - }, - "1c4af5003f9e7223f4141107d21640e4a85a4827": { - "balance": "612390629874000000000" - }, - "1c6a94810bd0afcf79ceea11afe86c34f6813211": { - "balance": "10000000000000000000000" - }, - "1c7e277460191c886cb1647173d27122c2146252": { - "balance": "209062806527000000000" - }, - "1c818ffa9caa61d512fa5d7d6e566f3ae37d5434": { - "balance": "454897845316000000000" - }, - "1c9599d5f8e5eaf8f68d35d52132e15a153f6d3c": { - "balance": "36000000000000000000" - }, - "1c95ab5229fd08c638a1728c022f09291b8dc55d": { - "balance": "20000000000000000000000" - }, - "1c962808c175ee5e5e365483d066c8ea95993700": { - "balance": "1362779746855000000000" - }, - "1cafad295b2188f10192c8a32440931f7e3554e4": { - "balance": "36000000000000000000" - }, - "1cdc2899ec563d79569d1ba776bc03cff331e786": { - "balance": "572163587827000000000" - }, - "1ce0042e7b4f13589f5f8490836dc63e0ca60c3c": { - "balance": "25000000000000000000" - }, - "1ce62051fd7801d294bf31a7b44cd87510e8b545": { - "balance": "2008112411284000000000" - }, - "1cf20f30cd901b2e5fef3f948289dafaaabaa77d": { - "balance": "1444000000000000000000" - }, - "1d449764d38b7a4ac848f49e2dc99df02dfd8a53": { - "balance": "48215693645000000000" - }, - "1d635125c494b1137ca5f15ac95dd6d93c3a9546": { - "balance": "10000000000000000000000" - }, - "1d85a61353c3e0b6d34e105e35c8c7833b6a1e35": { - "balance": "16000000000000000000" - }, - "1d969134ee156c41c98c3721c5dbb092c0b581a6": { - "balance": "64000000000000000000" - }, - "1da12434596a9c318dab854f06d404fe61f0a69d": { - "balance": "16675185416000000000" - }, - "1db0d23fb63681958a66e716e99df3e0b848fd12": { - "balance": "1103581911968000000000" - }, - "1dc628820da657f07ab5eb887d5f512378b5b61f": { - "balance": "6272287019755000000000" - }, - "1e05cba75b0dd379037940352e0073564957b7d9": { - "balance": "12453446342664000000000" - }, - "1e13f037a92ab6f19c4484ae3301b3ac6f48575d": { - "balance": "106244918916000000000" - }, - "1e167bc07f094915c00e7aa4c43b607ed2c998b9": { - "balance": "1000000000000000000" - }, - "1e1f9409bf92c3ef59aa2fd82dce55cd90e23f19": { - "balance": "99139000000000000" - }, - "1e4dfea7871d941e72a161022b62fdb01818c86d": { - "balance": "81000000000000000000" - }, - "1e5d0b525228167334e94314a201388bba08153b": { - "balance": "1138044078759000000000" - }, - "1e6633290c9898abf5fcac54396de770164edc5a": { - "balance": "25052055674000000000" - }, - "1e76296584058670ea80fe9a39d8f457c03747c5": { - "balance": "10000000000000000000000" - }, - "1e88b2c8dcd289929e51a15c636d0b0f3b035569": { - "balance": "87357600832000000000" - }, - "1eb59a1732a159a91a9371650943840e0eb61174": { - "balance": "20542821429000000000" - }, - "1ee077bdef6d45d491602342cee008cd1e2912e3": { - "balance": "10000000000000000000000" - }, - "1f1ebf2f80afced68424cb7b0b966fdf42d508a4": { - "balance": "1460082126494000000000" - }, - "1f3d4a903bd32a537efae19592f5516698c95a20": { - "balance": "10000000000000000000000" - }, - "1f6431696efc6f1ab98dcc2ef0e8553da697e6f1": { - "balance": "20000000000000000000000" - }, - "1f657552b745acbdf731f2ad107d6362480abc88": { - "balance": "162042599568000000000" - }, - "1f699a7682c1266291a3f49e19cac0846470abf5": { - "balance": "712268213248000000000" - }, - "1f7a332dabb00851705274c59187817d859cb9a4": { - "balance": "199999999160000000000000" - }, - "1f7c333047e168f5d3408c42a4919bd44b8f7961": { - "balance": "3918096658000000000" - }, - "1f8226f7a4525b9f3cd4da3acc1bb34529f8d28a": { - "balance": "3530829464000000000" - }, - "1f8b6fcea9e0991ad0b0b25dc65748518a28713f": { - "balance": "142069368416000000000" - }, - "1fa3de6913e4de78cc4828e246554785950c3c8e": { - "balance": "178437291360000000000" - }, - "1faa75d57fd597d2b58d2ac6f65bc2bd5946911f": { - "balance": "13092024644362000000000" - }, - "1faf1721dba3266cde1e04a7e9c789bdabdd930d": { - "balance": "862698523071976000000000" - }, - "1fb861559361701fca1df6ab4ef4d2fb9d2d7e13": { - "balance": "100000000000000000000" - }, - "20154d678cdde9ca1c0acb94726f26617a4da0d8": { - "balance": "2288800561677000000000" - }, - "202484a46ca9d54d0d456bc38e2a74ec5f469349": { - "balance": "50178714107336000000000" - }, - "20324278018b4d8e0c49e0fd1be35d3494079165": { - "balance": "484082383314000000000" - }, - "2033ef68ef6297e9229bb73e6486330543aa3eb7": { - "balance": "51260669473000000000" - }, - "20b1e0ab7b9d62a314946b55a5775f24ae3cfa00": { - "balance": "1540424185584000000000" - }, - "20b61f2eb5e18b1e8568d18235918f9e2f596c32": { - "balance": "10000000000000000000000" - }, - "20ed8ca39dd148edf22e03b8021af32cecadd42a": { - "balance": "20000000000000000000000" - }, - "20fd5feb799fbb021ba262d28332b4dda8f44a2c": { - "balance": "7607475714434000000000" - }, - "215ab8aad1c8960838225294d086f0786c2dd796": { - "balance": "19929201327000000000" - }, - "21681cda53aa1a4cfb3e3ea645c8eeaecfc3ba4f": { - "balance": "10000000000000000000000" - }, - "217b75eaf2c0be12108120ba56ddb709e1885324": { - "balance": "36000000000000000000" - }, - "21be1d75b93e96017f088f1ca64ba7076c8edf07": { - "balance": "150798073752000000000" - }, - "21ccdbe0216b486cb39c94ed13767aa061c75ce9": { - "balance": "11070639373000000000" - }, - "21f2289f2d274bddd7928622fffdf3850d42d383": { - "balance": "268859368544000000000" - }, - "21f54f92a7d9a91915e1751ceb02cb8e3ed3d622": { - "balance": "10000000000000000000000" - }, - "2202c70ec23f4605394d69944edd9f90e488eb61": { - "balance": "9000000000000000000" - }, - "220e2253e1ab9ec348cc28d38bae4cb2d5d9cf8f": { - "balance": "116100821631000000000" - }, - "22328e434957107884854999e666ad0710187e3b": { - "balance": "233364805270000000000" - }, - "22851c0487d119ee3f150010515358d6ff14807a": { - "balance": "104464221701684000000000" - }, - "22a38000f5eca29001e387b52c18fb6030683fac": { - "balance": "55000000000000000000000000" - }, - "22b655a19810307750ed1b6b093da10a863d4fe2": { - "balance": "11840799203605000000000" - }, - "22cc48cf48e8ee207bc08411240f913a4e594529": { - "balance": "10000000000000000000000" - }, - "22d6ea6cb8a9206285ccddd3b6d0d1471ba66f17": { - "balance": "64000000000000000000" - }, - "22e2f41b31a0c69472a1a02d419886539b7b6197": { - "balance": "39885451304000000000" - }, - "22e962f91d01480d027ee0060030f529a7a64c8f": { - "balance": "93285203531000000000" - }, - "22f169328fb1104b386ad7fa69f0c7bf3e9a7d3b": { - "balance": "63366769386000000000" - }, - "22f35f5e0e7a8405714de66a5875c7ef84ec4891": { - "balance": "60944382032000000000" - }, - "23041bdc8d371dc29ffc890f19317dabeef12634": { - "balance": "402327389857000000000" - }, - "230eff5e8595f418686737ae671f1f1d225080a5": { - "balance": "114574598112000000000" - }, - "2331e1756d9800800fc9b54ee6e43e1150b6e58b": { - "balance": "44594796226000000000" - }, - "233a72b132e4ab1d3884274d4402d1a2a6399f0b": { - "balance": "1372148909093000000000" - }, - "2369d9dbbfd0f8aa8a3d84d8f2aea840a0cdf760": { - "balance": "500000000000000000000000" - }, - "23754e5cef31ab60aa97a0c8f9ccb4f2969f2d6c": { - "balance": "24764775861000000000" - }, - "2387973589fb07a8c1ec92492c0b8ba9ab5e52a2": { - "balance": "11642113696681000000000" - }, - "23950cd6f23912758ebe9d412166e27994fe6ec2": { - "balance": "100000000000000000000" - }, - "23b383e11573f3ca9be84e1e11694f58a432324b": { - "balance": "206558238838000000000" - }, - "23c329bb641fa51122ea476e3bc614f5d4f9cf00": { - "balance": "35908627324000000000" - }, - "23cb9f997c39853486adfc1a8b029874d1a6af15": { - "balance": "1400984459856000000000" - }, - "23ee14215c531f6ff1baef2c74b1754306f4532d": { - "balance": "10000000000000000000000" - }, - "23f641f765cf15665b6c28d77229d3b2a58fd857": { - "balance": "266570948120000000000" - }, - "23febb49d9541360b9d099377df16b5630dfbb52": { - "balance": "228513797641000000000" - }, - "24082040652a09cbed6504f3dd6491e0ee9d2bff": { - "balance": "91160839809000000000" - }, - "240d3edf4aaf42e99d366ca36d82c370271b8e8d": { - "balance": "65535355843947000000000" - }, - "242b63ebf47678f17c176d5d4a670e46e66a823c": { - "balance": "469668185647000000000" - }, - "2433612fb939236a87a97261ff7b3bc7b754afb1": { - "balance": "20000000000000000000000" - }, - "246bb03a3fab572b3c64fc23b03dfda42b7ea34c": { - "balance": "936364046000000000" - }, - "246c510dfaf5b49bc0fe01c8256d3879c1b5f89a": { - "balance": "100000000000000000000000" - }, - "24bf4d255bd3db4e33bff1effd73b5aa61ae1ac2": { - "balance": "302436106595000000000" - }, - "24c0378e1a02113c6f0c9f0f2f68167051735111": { - "balance": "36000000000000000000" - }, - "24cf04b7450a0fac4283fa6fcfef6215274b273e": { - "balance": "83714002622000000000" - }, - "24f5f8e7d6a23b55c95fcdc1300de05f9d2abd83": { - "balance": "20000000000000000000000" - }, - "25204bfb27a08dbdee826ad6d9c3398ec6d14fe1": { - "balance": "5929256591480000000000" - }, - "253d95911b4174805d13706b449879413b1672be": { - "balance": "37012901440000000000" - }, - "256065f7e919c508b68957b1d2c9120d29181e12": { - "balance": "25000000000000000000" - }, - "25624542c14c2ecb9a0fe7daec9ac5af16868ee7": { - "balance": "16000000000000000000" - }, - "256d05b6de445179e504a6c94ce1253ae159e19a": { - "balance": "12048598744001000000000" - }, - "256d37fc8980a969063b1f7e7fda8b87d4210da6": { - "balance": "107293553721000000000" - }, - "2588af91a0e8f3ba3ab636781bb84e263acd1f52": { - "balance": "8910000000000000000" - }, - "259774584d4fcae1d84f5997c00beee8a380e46c": { - "balance": "1140713354605000000000" - }, - "25bda1418853a22eb6a5380e8a2862d2a74949bc": { - "balance": "10000000000000000000000" - }, - "25cafdab7f79f7b95d55b4c2dda1f4080aa74d64": { - "balance": "2525573681000000000" - }, - "25cca69b41bb51c51b387c47ece83f30b9a78daa": { - "balance": "163449631440000000000" - }, - "25ce9dabd0a72b02e0056931155ba99c94cbc837": { - "balance": "230073284349000000000" - }, - "25d9d1785c96acddd926b3ed52987ff74f9083f6": { - "balance": "780460361789000000000" - }, - "25e56bd3e1461f27db4eb0cce8bb5ca1574401f8": { - "balance": "1001937531200000000000" - }, - "25fa2162d5c86cda10e4be42c14a24329e455ad8": { - "balance": "50000000000000000000000" - }, - "260a932a23b344056acb8e676714ffac0a13ad2b": { - "balance": "2000000000000000" - }, - "2622efe8836095fcf48d9c8019f48c8320d6e0f2": { - "balance": "5451866545636000000000" - }, - "262447c4d8826ed23ea25e9703a11b4ad3ae9388": { - "balance": "33992454005000000000" - }, - "263eee3badb9b0dd13579c09361806503705a1de": { - "balance": "1134831344000000000" - }, - "266f4c232ebc946c46979cd90d70868380e186d8": { - "balance": "20000000000000000000000" - }, - "267dfe6fa918686942f5e1d19d5fa615f6f2086d": { - "balance": "3569373363935000000000" - }, - "268ad2272c2b71243a7391020a600fd8dfa42d45": { - "balance": "122768017414906000000000" - }, - "269e4f43be9865f05a277933c2fbb466659ada7f": { - "balance": "22064992930948000000000" - }, - "26ae161c20acb26a320fbfbd60c97335cda28bca": { - "balance": "170710653621000000000" - }, - "26b4da905780fb0c5c3e7e5315989fed3aeef135": { - "balance": "20000000000000000000000" - }, - "2704312aa5a4202f14fa3b08e587e4f0ef13accf": { - "balance": "124259630994000000000" - }, - "2704e4b0e8df0c1f298843109ae3bb26c29a22c4": { - "balance": "3155521256785000000000" - }, - "2709347d12251c01aac6455108c6bebe72f0af2d": { - "balance": "220898650215000000000" - }, - "270a32b41dde877463d2106ea4f4529557a5e1d3": { - "balance": "10000000000000000000000" - }, - "2738b3746d6bda9bd72858eaa76f8b5ce7a88c8c": { - "balance": "10000000000000000000000" - }, - "27593d2271aced83e81034e8dd603d098238320c": { - "balance": "20000000000000000000000" - }, - "2771ba4b5944bb12d74b1888255c60e0db215fd2": { - "balance": "412946979808000000000" - }, - "27780086136ea3e97d264584d819dcb2176d7544": { - "balance": "292224348060000000000" - }, - "278936fff8afb553043f038c39fe93906bdb1f4f": { - "balance": "1448466441752000000000" - }, - "27aa0d45d3506f8446816e0e2e9675d46285f6e0": { - "balance": "20000000000000000000000" - }, - "27e655dcc5728b97b3b03fb2796c561090dced1a": { - "balance": "9841344000000000" - }, - "27eb0529279f7a71e50efb70bb1767cbe1ffa4ce": { - "balance": "10000000000000000000000" - }, - "27f564956c837d7949739f419d6ac99deb33d790": { - "balance": "1505247707018000000000" - }, - "280f5618a23c41ac8c60d8bef585aa1cc628a67d": { - "balance": "1316618646306000000000" - }, - "28167a591d66ae52ab22a990954a46e1555c8098": { - "balance": "1000000000000000000000000" - }, - "28257eeb8d20f2fe5f73b0ff2eca3214e30ece4f": { - "balance": "95924728584000000000" - }, - "2827abfc49828db0370b0e3f79de448d46af534e": { - "balance": "769862008499000000000" - }, - "2832b92434e3c922206c2408442bc8274606cbd9": { - "balance": "103421320914027000000000" - }, - "2854f190a38e9b9c04cf499259c6577a68b0b5ed": { - "balance": "144000000000000000000" - }, - "288923bd91be164496e5378ee484f0e4c6c16ed6": { - "balance": "10137243270703000000000" - }, - "2897ff80794153edb721801fb91c6d8373c965f4": { - "balance": "10000000000000000000000" - }, - "28aa06e2290010374097aa2f87a67556d8d68083": { - "balance": "84783245638916000000000" - }, - "28b04ec8eb18b0c6a384f9d92cfb44d1d43ecb51": { - "balance": "14364248730194000000000" - }, - "28db0c000cad3a524bb68dfdd74ffd47b42fb13a": { - "balance": "43586590410000000000" - }, - "28ecd4c5fe98cff66a5b8423f4a27cba9634e2d0": { - "balance": "56106658052000000000" - }, - "2930822031420731f09dce572554a8b8c1eaa09b": { - "balance": "1170839742000000000" - }, - "295154c4522d7bcb2e24b7de9c543dcd1c5f51d9": { - "balance": "179028680906000000000" - }, - "296be4ef7402b00d7af673c1770a50162d7ab602": { - "balance": "8206640005889000000000" - }, - "297b84150756fa89101dd59750a7beb36fb8785c": { - "balance": "1168894124400000000000" - }, - "297cfb72cd1b8b2808fd1b25cdcf7d8de279ad96": { - "balance": "500000000000000000000000" - }, - "29cec0eca9f8508a1ba192a90bb6dee18c40745a": { - "balance": "260217025084000000000" - }, - "29d8f7e72bfa297f17fdce9cf8f4a398f547e200": { - "balance": "307787433251000000000" - }, - "29e14b01c59ba894dd090382fb193ea441164b90": { - "balance": "229028661439000000000" - }, - "29ed634e165084b720e446d28893dbeecd6a7018": { - "balance": "226530464200000000000" - }, - "2a0f8136d43248233f652fe579ef3bd2281dde24": { - "balance": "4007544428000000000" - }, - "2a10204a0c7c9f7701e33c1b71c9427ea16e2e45": { - "balance": "50000000000000000000000" - }, - "2a319ee7a9dbe5b832beae324290f7df6d66f516": { - "balance": "28127560161000000000" - }, - "2a50bfda2b06a9fb28c73f14aaff4f7ef865db65": { - "balance": "10483823413828000000000" - }, - "2a7b7feb145c331cb385b9fcb9555859c16820f6": { - "balance": "1017182951264000000000" - }, - "2ae076c36b18a60f1e3c05d434276a1e16f3f838": { - "balance": "10000000000000000000000" - }, - "2ae2e51ea2ee6a848acde342db2bf6eac927e5af": { - "balance": "494279795271000000000" - }, - "2afd69fac54c167e7ca9d8198a8de386f3acee50": { - "balance": "227162683047000000000" - }, - "2b08018d6e65a7b74ddb5ce1af99976a484b9f50": { - "balance": "16000000000000000000" - }, - "2b0c1d629ad2958ab91e31f351a91219fdbca39e": { - "balance": "113239399820000000000" - }, - "2b2bb67fe9e44165d2108676579a9437c760da30": { - "balance": "20000000000000000000000" - }, - "2b2c99e88e938d1f1416a408a7d0041a605bce16": { - "balance": "6118539729000000000" - }, - "2b5c97b6402ac189e14bbca3e7759319ca8a9222": { - "balance": "10000000000000000000000" - }, - "2b813339c7f818f578b45f17c41c7e931c7828e2": { - "balance": "842834712955000000000" - }, - "2ba6fc21f743968d51f80113aadfc0fdfe8499ed": { - "balance": "309973507270000000000" - }, - "2bb75b272b279cb54498f12b6805261af643c8b1": { - "balance": "1426727673809000000000" - }, - "2bdac062364abd9cf67ba7de214a2cceb0511033": { - "balance": "1090525272063000000000" - }, - "2bea658caa805241aa921f48c8f10cb49e16ffae": { - "balance": "1295499213027000000000" - }, - "2befe7e34299a7c1ad53fc9988ce77e2d9fab20b": { - "balance": "4326342236300000000000" - }, - "2bf466a83cd44aaf0f627606a1c954fd31deb782": { - "balance": "1388986370166000000000" - }, - "2c016a23890e9633fc17b0a8d328ec1ec7ee0113": { - "balance": "92483174342000000000" - }, - "2c45a87a63cc5c8c102d12b83bd9a3501ee41995": { - "balance": "394657687589000000000" - }, - "2c600a596368405e584f3b869f7fabef4ce54aa4": { - "balance": "9879984853585000000000" - }, - "2c7032da8b7816e16095735aee43d1c3f1c43acb": { - "balance": "10000000000000000000" - }, - "2c7275511fe06ee86663b3a618497168b35b0cdf": { - "balance": "10000000000000000000000" - }, - "2ca4074843e9519265447c0dd9ac84ddc2033c1a": { - "balance": "179612279567000000000" - }, - "2cac03ba2c45a6c8186bdceb095b7c5feced3114": { - "balance": "2022060470376000000000" - }, - "2cb8c2cd506b2d7b4cac88ce63230022d412c62d": { - "balance": "211378154058000000000" - }, - "2cd27561cf37ec229982dd592c71d1aab9c2d7d8": { - "balance": "42189968284000000000" - }, - "2cd2e85310a4fbb7f296c3d0d1cee07b191239eb": { - "balance": "1940327317417000000000" - }, - "2ceca4501c5f2194518b411def28985e84d42913": { - "balance": "25000000000000000000" - }, - "2cf7abd42394634689aa2a36d263a6345116b7df": { - "balance": "3553167226295000000000" - }, - "2cf88f29356c166df8383d3312cea10397e25150": { - "balance": "76961677759000000000" - }, - "2d0b62fe49592752cfebaa19003a60b8b39b1cb9": { - "balance": "10277397502735000000000" - }, - "2d2051887107bbd8ed45b405b9be6974a13172d9": { - "balance": "1928781992000000000" - }, - "2d2c9525e2811f4d1016c042f476faf23274aa31": { - "balance": "1000000000000000000000000" - }, - "2d2ef9e1c7a6b66d9a2994adb3ac4a9921408e69": { - "balance": "10000000000000000000" - }, - "2d3bcd18e5c97ddbf1cd28ab37eabe070e9a04d1": { - "balance": "323879852538000000000" - }, - "2d3e60496d0092a4efc665389a916be1a9f8b378": { - "balance": "161958437779000000000" - }, - "2d3fb0ae9b17d3a57d23549ae5500fbb163de25d": { - "balance": "25000000000000000000" - }, - "2d8106dbee6f728c0ff11887690a6370a7d9f5a5": { - "balance": "3102418708000000000" - }, - "2da48eeb788686811ac8270ef3baf0159fc47446": { - "balance": "252187695395000000000" - }, - "2da9d2a6f0b92651a36b05c5e9d2a717c6e166de": { - "balance": "500000000000000000000000" - }, - "2dad81b23d8447190259119019c04a4ef61ab91f": { - "balance": "53428719965000000000" - }, - "2db1faf35901e272aee74a2469a278fdaa6e6e18": { - "balance": "100000000000000000000000" - }, - "2dbae8e1ad37384ca5ff0b4470d3dbc73559841c": { - "balance": "10000000000000000000000" - }, - "2ddf9e23945c181b8592d7965e782068b4c38b37": { - "balance": "100000000000000000" - }, - "2def05d1f2abbaa193a219b87e5319c7ecd48dea": { - "balance": "51359946957000000000" - }, - "2dfd221f96a21e41ffe4dca67b15cd352fe9637e": { - "balance": "36000000000000000000" - }, - "2e1371fcfea9d8dc8e692897a91753400caa9c3a": { - "balance": "5199902650733000000000" - }, - "2e2e04945adbfaeec698ea0f5275f1ad5ffd3d5b": { - "balance": "42034514567000000000" - }, - "2e41f865cfbcf8b89f848405e04de9114087f4ff": { - "balance": "44875730962000000000" - }, - "2e530254768ce94db0ef1204ede0e12b3558e7eb": { - "balance": "14319506377747000000000" - }, - "2e5c43868f45de268967fb22f3f4107da401510d": { - "balance": "20000000000000000000000" - }, - "2e5d2e117d2ba9af9697ec023a4d10b5a2436902": { - "balance": "16000000000000000000" - }, - "2e6000778fb225ddb3e1a2f297d56774e85d9c9d": { - "balance": "10000000000000000000000" - }, - "2eb64b8ab13f0d7823158217d15ba310ed3d0e58": { - "balance": "58724606000000000" - }, - "2ec3973ff33a06d355ad4e8f73b657af8a5ed8e9": { - "balance": "1165606294808000000000" - }, - "2ed4362ea5edf510e210af733089b294f87e8f67": { - "balance": "427561040806000000000" - }, - "2ed8788f1c31b508e37079098a7337bff77b49cc": { - "balance": "10000000000000000000000" - }, - "2edbbe1e2ea482920c76a4ff4c14602b4d37c955": { - "balance": "294409476945451000000000" - }, - "2edcba2bd76128750c8aa00f832c62db30aa7868": { - "balance": "25000000000000000000" - }, - "2ee5abcc0d0d51d4b18947b5aaaa95d037be4e2c": { - "balance": "20000000000000000000000" - }, - "2f058187ef141c06c7c87da86cc1953d2fcf70fa": { - "balance": "9000000000000000000" - }, - "2f16b101da9986a18f4b0d30a26557860338c4e0": { - "balance": "254907899725000000000" - }, - "2f4363df2c61273d230071286bb0157dfefee2cc": { - "balance": "64000000000000000000" - }, - "2f6099a8cb7bc3713b87dab20994d8dc09342003": { - "balance": "1902400000000000000000" - }, - "2f7b3902ce56f74adb0f83cc7d3a99df440cca1c": { - "balance": "825246221388000000000" - }, - "2f7d0298ff6a363375b7eecfe754fca0963c8a1b": { - "balance": "101000000000000000000" - }, - "2fb7c16232b3b1f2e3a676d6d5c93ae6fe5cb14e": { - "balance": "1000000000000000000" - }, - "2fbd5ccc716d2f510d10ec84def3fa69e49f46ca": { - "balance": "1000000000000000000" - }, - "2fd84376be11772e5d072cd74c96b0d9a49c27fb": { - "balance": "1000000000000000000" - }, - "2fdab070e20e2c8923a24c196bec72c33ff0f220": { - "balance": "64000000000000000000" - }, - "3003e6007f69902a0f5e4b4e6d0468277897fc70": { - "balance": "1501210602075000000000" - }, - "30095e6a4ccd1ac2014c3d1d98dce003d775708e": { - "balance": "500000000000000000000000" - }, - "300e47e0fa556371f6c882eb98423be44de7c239": { - "balance": "9108837665958000000000" - }, - "3011231224920b62bcfcbf0aed4fde35dd0a4bdb": { - "balance": "374689586073000000000" - }, - "304be24debce62e70943efddd20457d34e85ab40": { - "balance": "81000000000000000000" - }, - "30912555bb14023e9b7c90aa2314721918cdf1f9": { - "balance": "10000000000000000000000" - }, - "309a94ca7b44bc84a7909ee2b93ed1c94eaf75a1": { - "balance": "39000000000000" - }, - "30bcc93965fa36bbaabcd781326e42227c4e1a51": { - "balance": "10000000000000000000000" - }, - "30c71fed91d24bff69f286ff8f0c6c02a21736a8": { - "balance": "409782329653000000000" - }, - "30cbaf4103757013fd8fb71c44a985939e212b86": { - "balance": "7424807960947000000000" - }, - "30dd59e66093d0bfd87b09c5f6588b9857e9a6f7": { - "balance": "26123006239871345154" - }, - "30f692235f254b02f583d5b515f4701a35c7f692": { - "balance": "148184457997000000000" - }, - "310763019a24a927ce42b00604ee664ca53ff6d0": { - "balance": "393757908273000000000" - }, - "3118a5d4d06ca8b7c8835f4860e6973228000ee2": { - "balance": "56188713212579000000000" - }, - "311adec5bfcaed44680691cc644ee120a484aa05": { - "balance": "169000000000000000000" - }, - "3124e387aa7023995643344c782dac84b9d8c7d4": { - "balance": "1393596696367000000000" - }, - "31379702391cb5a737db3f3ffc336bd03aaa181f": { - "balance": "10000000000000000000000" - }, - "3145606c3ccbaf337610185ffac14ac4f0583c0b": { - "balance": "196454968572000000000" - }, - "315e11501d2c57a62af1631fc2662d4d8745401e": { - "balance": "225000000000000000000" - }, - "31a785ad3eea177c59fb575cad0b44f9a48a12e9": { - "balance": "38039017162416000000000" - }, - "31ae64035e95c1205bf957afb5e1636df00dea3d": { - "balance": "1718600907000000000" - }, - "31c0bb22fd2e9d22984f248a16ec3ed9ad834517": { - "balance": "5982762676000000000" - }, - "31e73a3b5451ebe1163571e9e0567c425bbbfb83": { - "balance": "10000000000000000000000" - }, - "322543c74039ef61fd051021b5e6f16b54bc7c1c": { - "balance": "101346282441000000000" - }, - "3233c7ed11c25bfc41d506c3ae0daf5a3c7c1278": { - "balance": "20000000000000000000" - }, - "325dae17b5225f6734a02c677d43fd126bea89b7": { - "balance": "365067246683000000000" - }, - "326ce8166a4094b93c15557f50f2b1d47811e72c": { - "balance": "16641460224765000000000" - }, - "32cf76046ae48b609524b1a6203eb6296d04853d": { - "balance": "1094839482061000000000" - }, - "33456a28f36aa240262cf95b78b4ac2cd8aa77f6": { - "balance": "3077123488326000000000" - }, - "3348bce2ef90ffd6a59ef5079e1af84b2dd604a7": { - "balance": "9000000000000000000" - }, - "334e5f0ae77dcd3d32dfc2c4ec6ab5e2826dc4b1": { - "balance": "3176777762079000000000" - }, - "335775e19200cd0305e529bc4cdf7295a47cb2d3": { - "balance": "2945631571804000000000" - }, - "336ba81ea6ec4f0da38c1a1761ed3d97fd3ca28c": { - "balance": "3587379203826000000000" - }, - "339191e03e9d5a08ae7b58f4c860235a0721b5a1": { - "balance": "2732237722000000000" - }, - "3399bf9f94c5488c89450257b39fdf3ec8c7f413": { - "balance": "477423805836000000000" - }, - "33cb8556a6c6c867e1be7de591cb22c1b7e9824e": { - "balance": "62293494164000000000" - }, - "33ed633804f39367078e830328dd223254be3366": { - "balance": "22842013797896000000000" - }, - "3409025dce86ad441a5a80f30ce03768d37e40bc": { - "balance": "1381667933000000000" - }, - "34153174cd4d3f1eaed7438638d302f6414d5965": { - "balance": "50000000000000000000000" - }, - "343c6b82b13f0dc82d4269e2c806d2d58e6dde35": { - "balance": "9546969736042000000000" - }, - "346089ea81f7dcb79caf2444df34bd6ee78be4bb": { - "balance": "4344080889000000000" - }, - "34984a8f96dbbfd1f977826a4c2187482559a2e4": { - "balance": "25000000000000000000" - }, - "34a5cce96d2211feb04472260c4cd368bda8432e": { - "balance": "1240050112677000000000" - }, - "34c026a39e44955d1051e8669f9cc58a027455c1": { - "balance": "20000000000000000000000" - }, - "34d730652f4aa002a9f39a47212ca3bc47506b8b": { - "balance": "418050617956000000000" - }, - "34e1d8c8a32ce0f6378abb9bd05ea1f9bfdc5782": { - "balance": "20000000000000000000000" - }, - "350b228870445141f4417ea5dba4f009d693b96c": { - "balance": "76995849736776000000000" - }, - "350eaec708d5d862831aa31be2c37b2fdcef97c6": { - "balance": "258753545822704000000000" - }, - "351fc1f25e88b4ccf090266ebb408593418d8fde": { - "balance": "10000000000000000000000" - }, - "3523ac7a6e79162bb8400bf161cb59389432aa51": { - "balance": "436606776923000000000" - }, - "354d490095e79a29bda2fa11823328450f14333b": { - "balance": "50000000000000000000" - }, - "355a555a36e319e76042e62875a15e1db3012b86": { - "balance": "20000000000000000000000" - }, - "3568840d0a26f39248ab088653ede831f150ce29": { - "balance": "16000000000000000000" - }, - "357096b9c1c7c8d51b682ed3c43d150f55629ff2": { - "balance": "900090781248000000000" - }, - "3588c47ba9204b672c456ee9b5c1ae70f3c738ac": { - "balance": "10000000000000000000000" - }, - "3591edeb9c036e871b4fc6fb3ae6d42e0c0d7203": { - "balance": "1000000000000000000" - }, - "359d92e3e8757a4a97187a96d408c0c11f5c7eb9": { - "balance": "22330509101591000000000" - }, - "35aac2a948f316ba93ed111ac127e29ee9a3adb0": { - "balance": "364387817746000000000" - }, - "35b20459a7daa5f44ae423fd4a1b451ea5090b09": { - "balance": "20000000000000000000000" - }, - "35cdaa84c1f3bc2673bc0c60222c133bae0d3db1": { - "balance": "15234182435000000000" - }, - "35d554233ca690130aaa43501e121a208c657226": { - "balance": "10000000000000000000000" - }, - "35ed399940ece44d01ac873b9c0d3212e659a97e": { - "balance": "55000000000000000000000000" - }, - "35f164612afc2d678bb770f317085ae68cce19bc": { - "balance": "693763596328000000000" - }, - "3601b36cb475101d0d0976a8de9d38e5f3483a08": { - "balance": "1000021000000000000" - }, - "361368bc42c8daf365bce9f9ff3b611373d7b690": { - "balance": "21658400518000000000" - }, - "361bc43be077a269e3e37c11e91479017c47f847": { - "balance": "268900383140000000000" - }, - "363c7a2203f6f93287de091bde3c87eb6800e7a7": { - "balance": "20874859005000000000" - }, - "365dc06856dc6ef35b75b1d4eabb00a7220f4fb5": { - "balance": "30000000000000000000" - }, - "3660e246bce68e2b6e4a802681f188587d2c1c99": { - "balance": "55000000000000000000000000" - }, - "366868ef8e193d7e649ee970d476e6774d5ff1ac": { - "balance": "2544456626840000000000" - }, - "366f7f762887cfb2d09cefa4a5108cf390bdeb41": { - "balance": "26837527714000000000" - }, - "36759f9c92a016b940424404de6548632c8721b1": { - "balance": "1033159825798000000000" - }, - "36a939be88508646709d36841110015bf7cedd90": { - "balance": "144000000000000000000" - }, - "36adca6635db6b00d28a250228532fe560127efb": { - "balance": "3370820618318000000000" - }, - "36bfaed8099ee9f216193ade26d21656c98ce4b5": { - "balance": "1353728563832000000000" - }, - "36df854d0123e271529a8767d1cded4e7b5f31d6": { - "balance": "10000000000000000000000" - }, - "36f59989a902cd10725ff7fe2cab1689aa4e9326": { - "balance": "20000000000000000000000" - }, - "370d6999ae70e781c81d12dc259ea304183b01eb": { - "balance": "45563989086590000000000" - }, - "370e8af59a64a3171b422913921a1e2f982dd512": { - "balance": "170263356254000000000" - }, - "372e01083072214134018f50bde3c8ac4f6e071d": { - "balance": "1400474252324000000000" - }, - "37410fda52f94185d824258ad5f3c9ad9a331257": { - "balance": "11830521097085000000000" - }, - "3752b7e1628275522cd693307787b9564501d959": { - "balance": "67839627078000000000" - }, - "3776f82701c384ce6cbf6a8fea40772cb882b66d": { - "balance": "50000000000000000000000" - }, - "379f63e538168925ba6313f9a6a3b6e7f0e8ed52": { - "balance": "292876625446000000000" - }, - "37a24c1a8080ab429a136c5582782b276eaa931f": { - "balance": "6099055841000000000" - }, - "37abbeaf24b5e6264c87633734852e243d377010": { - "balance": "1051360014489000000000" - }, - "37c50cecab8fe9dcd81aaede95050d27c53f4d45": { - "balance": "106051638566000000000" - }, - "37f82962c3097f0cd9ff605db66e792025a540cb": { - "balance": "10000000000000000000000" - }, - "382ba1e6c53cd7b9c360ef894962d281d557561f": { - "balance": "216789631461000000000" - }, - "38309b458993916efc1ac8b0b5d41302fec21095": { - "balance": "999139000000000000" - }, - "3847f25956a97a32caac059fd9e4cdc105756e25": { - "balance": "876497264905000000000" - }, - "384fe5f399638d277d4fb93f26d527497939287a": { - "balance": "280035151914000000000" - }, - "388335d8b92b445b1b19a3107547bb6ca7c0763c": { - "balance": "167140942784000000000" - }, - "3894a1e65973a542101caa4dc01e9553a5521d63": { - "balance": "34262479791000000000" - }, - "38a0e019c6120a19acaf0e651dd8338982cdaab1": { - "balance": "153843170492000000000" - }, - "38d4bdb10819a7d4ae9a32f4abb82402dff319b5": { - "balance": "1471131830647000000000" - }, - "38e56a55e2ac8320a480562f4a7cea9220306ee3": { - "balance": "907464312139000000000" - }, - "38f18123f3643e03d24ad759afbefc90ed923a2a": { - "balance": "943729130798000000000" - }, - "38f764c861def6d5d65e5ec099536f4cfcc3af55": { - "balance": "20000000000000000000000" - }, - "391e12b51fc85fb879a72fa746ca06c7a5659e6c": { - "balance": "9000000000000000000" - }, - "392342dc7b475c3975877a41622be0fed8e386be": { - "balance": "218719857770000000000" - }, - "3944cc960b8f1993ad841629a79e53d0535a88c8": { - "balance": "210571656485000000000" - }, - "396219864b8cfb0ffb3c675690ccd7026424ad4b": { - "balance": "138984508746000000000" - }, - "396403f26b388150b4876485b124a49845101464": { - "balance": "10000000000000000000000" - }, - "396f1e0f9e7ee86d1b2159ab8f9353677d12d340": { - "balance": "121000000000000000000" - }, - "397cc9f6254d56c721c767e41628a9078bea878c": { - "balance": "225000000000000000000" - }, - "39878b0c7049fb179aba0015279eff6cc3136816": { - "balance": "33962071375000000000" - }, - "3a06b58d0cceee5b091fe6aeb0fc0db5774e9395": { - "balance": "272033811720000000000" - }, - "3a3330e0152d86c5aa1d9bdfe9e1697645d3377e": { - "balance": "2165107207206000000000" - }, - "3a3bb8ed3130e09fbdfc21db3571d4711fc92d60": { - "balance": "885484658836000000000" - }, - "3a4ac96c489c864765cb1997a0084ba745b67a87": { - "balance": "1257436384863000000000" - }, - "3a69e1c351978ced418cea6cee019f220bcb065f": { - "balance": "579242822216000000000" - }, - "3a76a23d81929bed05ef7e1982d32b456e62aa7c": { - "balance": "1027078338792000000000" - }, - "3a7beadd1e11d0e3326c0dcd0f670530612931a5": { - "balance": "20633069818937000000000" - }, - "3a867c44d0dd06517a82ad467d0aefd7f11ce729": { - "balance": "12323708574000000000" - }, - "3a969ae486215e24c7ab89e38929562e2f85d923": { - "balance": "18955477335000000000" - }, - "3ab81366d898a8b798afb08a4b722ab0eb883652": { - "balance": "1220090012596000000000" - }, - "3ac1e14ed5929d382f6488c5444e717373ed29ba": { - "balance": "2030543873000000000" - }, - "3accf4b8ef20e4fea983f13f99ab257a5f9e988d": { - "balance": "156030342415000000000" - }, - "3ad38fa6e3c078025794e213d9dcc5aa397050c2": { - "balance": "36561766773000000000" - }, - "3adef81b2c861ae39c418d55be99aee2306e29fc": { - "balance": "15752410974000000000" - }, - "3b21ff4d5801d3976643899f195fbfd1b72a50b3": { - "balance": "8971221745646000000000" - }, - "3b2f2635dd428ac0b5873088a9a81800f09d6e02": { - "balance": "56922872447000000000" - }, - "3b39919c7bc8d0afec792288c56ab7f4934dc7d2": { - "balance": "1678237240464000000000" - }, - "3b468d9d5546810aa837c29ccb8349548b0e8170": { - "balance": "1100000000000000000" - }, - "3b83d1b651f117f1559a19b04ef408619c2dc4a7": { - "balance": "53628552066000000000" - }, - "3b9a72201bb1e8e678e36129cb1570e3ac99270e": { - "balance": "25000000000000000000" - }, - "3bcab1535b04a0a3fbb673bc41fedaa80bf7901c": { - "balance": "1526488015042000000000" - }, - "3bed42c3d0c49ffac87b9d482f6338fdc9e3880e": { - "balance": "26189771073000000000" - }, - "3bf736b57f0ae47f3714a6bb852090a543b9d367": { - "balance": "652395174320000000000" - }, - "3bfd481651956105ed909eeb98be404ec5ae77e9": { - "balance": "177520143473000000000" - }, - "3c0a12a327545b5f8b7b5c1f7a1ec6a341ec9578": { - "balance": "4184342789398000000000" - }, - "3c132698d59927fe08cba433a41d08acc96c0edd": { - "balance": "151913899135971000000000" - }, - "3c27bd92c4be1a19974ec773bd20b13afe582c9f": { - "balance": "10000000000000000000000" - }, - "3c2ad171573a608286f1fa3f5ef9e6099823983e": { - "balance": "3240802189194000000000" - }, - "3c4b5e808b9fb8baab1144b981b6cd53e216fcdd": { - "balance": "61214114118619000000000" - }, - "3c4cfc6ead044819ceb41c1c64ceda1a228af801": { - "balance": "9000000000000000000" - }, - "3c553afd45535f7c2a70c701d00890e607b96ffe": { - "balance": "2678827200938000000000" - }, - "3c620d55268c55b6deea3b7dc7f59dbe93b6e141": { - "balance": "55494311990000000000" - }, - "3c9b204db23b902d4295e6aba3405917efd59449": { - "balance": "55543672571000000000" - }, - "3cf233b7730a175d05a861318b7bb917bb5bee06": { - "balance": "1867187351033000000000" - }, - "3d292272992397ed5f27d5202da693128d023d35": { - "balance": "79770828413000000000" - }, - "3d353cfe84e9a93aef90547fbeb6e4b4bef83069": { - "balance": "36000000000000000000" - }, - "3d54da4ddd0621822a114581ecd15572e6488be9": { - "balance": "1623867132383000000000" - }, - "3d62ddc67d366fb055eaf92c936a6e7df5085454": { - "balance": "124933526793000000000" - }, - "3d754df1151b9b62a6ed48b477225121c29af063": { - "balance": "50000000000000000000000" - }, - "3d79d1ebd5224ffdc13e27924ab7f9f8e3452ec9": { - "balance": "520163228474000000000" - }, - "3d84fd9785a6bd3148847038c6f1e135042a892e": { - "balance": "10000000000000000000000" - }, - "3d9574c3860f30bcb42523a0cbb08aa7dd83e733": { - "balance": "15259904884000000000" - }, - "3da809a5911ccc77f892034049a97a9022c35e7d": { - "balance": "1415009021101000000000" - }, - "3db9a6c6ab3d0cf6d3bd7e04bdad39b4d419ab13": { - "balance": "9999781764000000000" - }, - "3dc7367c3218f88de8867c425f89102d2f2056f4": { - "balance": "10000000000000000000000" - }, - "3dd273dedb28824d1309c7d60a0744a6b6353e79": { - "balance": "9000000000000000000" - }, - "3dd6b25eb91dd2f3468e0786e8beb465abe7f515": { - "balance": "275172962210000000000" - }, - "3e0d14f83b304136311a33bbac2720c0cd66f117": { - "balance": "3390479675000000000" - }, - "3e15e947ee76f52f0f2a7d84da7c4ab060eb5cbf": { - "balance": "6751398714759000000000" - }, - "3e1b5469e1da4ec27537513f4df3f1a338a7dc2d": { - "balance": "161899580000000000000" - }, - "3e3329bcc90e47e4dabb5c93572b18b5e0efa024": { - "balance": "10000000000000000000000" - }, - "3e5a585ad0f34d78899433edaed574af052616f0": { - "balance": "910225655353000000000" - }, - "3e6be9615713bb06198bf354ef434a9db649699b": { - "balance": "783525278181000000000" - }, - "3e7c7c082f2f99b1ad579400a2e93586a24ed992": { - "balance": "159035553843000000000" - }, - "3e86ea5713f90022c0914fcc25e97c39487eb957": { - "balance": "101867287023438000000000" - }, - "3e9dabab6e50a696edfba6bcd44230d087c8d04c": { - "balance": "3315882414579000000000" - }, - "3ed956f86fe78223c86e164e4f372c9a0bf4a279": { - "balance": "119959915220000000000" - }, - "3ee87e776fb12e9c894e36fd5a61daa984e8a5cb": { - "balance": "50000000000000000000" - }, - "3ef1c8f294443f776a794563ce7569a8fe4d5d20": { - "balance": "25000000000000000000" - }, - "3ef6a396d6611df6c79ec1e6ad6bbd253917fbe9": { - "balance": "10000000000000000000000" - }, - "3ef727346fc631ae6473e9a36e2e5e54df696195": { - "balance": "121000000000000000000" - }, - "3efdcf2c0998637cb82d2b5fc24f27162578d207": { - "balance": "1054861112990000000000" - }, - "3f2cb2335e2bc07744175c497e2f437e87c2a146": { - "balance": "48999979000000000000" - }, - "3f4d16663a4f76ade93eb8bd6ca8fe2158e24322": { - "balance": "237117597268000000000" - }, - "3f7c5e6aea7f3f74d764df50f0fc1aa758fc99a7": { - "balance": "63372222562060000000000" - }, - "3f92239fdb41c6ec228252248c2db3f23675e275": { - "balance": "28538064487000000000" - }, - "3f9610454b621c04f00f01f4d54046502edb21fb": { - "balance": "16000000000000000000" - }, - "3fcfb30cbfe53c0c43f58c28386d9a6e5b49f7cd": { - "balance": "79080579219000000000" - }, - "3fda0c9a3d3f0000635376f064481d05d1b930bb": { - "balance": "10599947385000000000" - }, - "3ffce0475430de0bd9b09a412e404bc63aa28eea": { - "balance": "10000000000000000000000" - }, - "3ffe7583b568448ded5183e1544bca0d283680d2": { - "balance": "1076944549283000000000" - }, - "4003a137e577351a4ad7e42d1fc2d2cf1f906b6f": { - "balance": "25000000000000000000" - }, - "40215fc4c6300d8d8179383d9028fd2d909c6cc4": { - "balance": "3941346079000000000" - }, - "4027d7bbfa5d12c1ab9d08933a1659ae8dd023ee": { - "balance": "1156537386462000000000" - }, - "4039439c960070394dbda457726d97121c7b3669": { - "balance": "4444061364102000000000" - }, - "405978c24a12d930ada6163a44fc4a70c16569e1": { - "balance": "707298643296000000000" - }, - "405d2c1b55ba3f67c8634456b99c19092b407a10": { - "balance": "1462185951849000000000" - }, - "405ddfcf45005cf5a0ee1bfa605a7346a0167945": { - "balance": "88775535985000000000" - }, - "405f72a6940acf5d36a29498075f2d0d7a75bc22": { - "balance": "402796678569000000000" - }, - "407253b005ae97857f812fc60d441e5367b4bac8": { - "balance": "1484147810895000000000" - }, - "4091e1fb1c7af51a64c201d6a0c8f0183dfb7ca5": { - "balance": "10000000000000000000000" - }, - "40950bad9580d4b111955da7d3f9ada26dd9f05a": { - "balance": "500000000000000000000000" - }, - "409a28106192cae7a76c6aa8add0f73dcd63d2c0": { - "balance": "214832616721000000000" - }, - "409d5b872b059aea9a773e854f9a17ed2d5c2ef3": { - "balance": "64000000000000000000" - }, - "40a6e3c753b04c42fcf89cc30df8f50418caecb8": { - "balance": "754228409494000000000" - }, - "40e5ce1e18c78d6c792f46ed6246bfb31bcdb6af": { - "balance": "500000000000000000000000" - }, - "4121692a14554ddca1ca662fb577d7152d4fa7d0": { - "balance": "49000000000000000000" - }, - "412acb10c8ca937ddd64cf0d413b1dd34760f72b": { - "balance": "6073360870000000000" - }, - "4166a5c94d5ae48ced410f950d40656182bf8990": { - "balance": "55000000000000000000000000" - }, - "41752b7d0d3ee58a6b69d8ba721c0894ff701237": { - "balance": "585556720807000000000" - }, - "417c86d6bf734e99892a15294230771bbfd7e1e1": { - "balance": "38233258264000000000" - }, - "418414498f7361b29428c54732e1f49fb394f813": { - "balance": "2063786326155000000000" - }, - "41a424dcbff6bf31686f5c936e00d21e8a4e0f78": { - "balance": "33554754580438000000000" - }, - "41a893429d5f8487c1866b87779155d4bfe33198": { - "balance": "20000000000000000000000" - }, - "41bbedd607fa576d130305486824cd2871bf6b05": { - "balance": "649728993301000000000" - }, - "41ee42c1fb1bcdc9c7a97a199fdcf9b63623521a": { - "balance": "7906012418597000000000" - }, - "41feffaf56d1712af6965fa6eee1b06bd624e7b8": { - "balance": "49000000000000000000" - }, - "42107e765e77ea76b3d6069d3775bc3aef7d692c": { - "balance": "25320783684183000000000" - }, - "421f4dab3240e15a1c78e3ce8642de9b578b8e4a": { - "balance": "832511242936000000000" - }, - "4246c52c3601541a873d4bbaafedf28b9bad5b73": { - "balance": "10000000000000000000" - }, - "424efe1ba28bb1aeedc38a3a5135547d0fe80751": { - "balance": "25622294162729000000000" - }, - "424fb0a3ec325bf42e7edbef7e450f2ffd1cf318": { - "balance": "20000000000000000000000" - }, - "42714c04d17f6c29029daf7f50d1cbad6590cfad": { - "balance": "271755674161000000000" - }, - "42b66e9123d304b70fef3dbcfe8587fd6189b5c4": { - "balance": "1030481609000000000" - }, - "42dacbc412b829cb304ffbc316b3f81b379bfc80": { - "balance": "304208485736000000000" - }, - "42e3d9832c8b6cdea39c97525570391803dee276": { - "balance": "2581020833000000000" - }, - "42f757898f95c1b46f64a4a6b7f86ab03022d672": { - "balance": "100000000000000000000" - }, - "42f7956fd659e00d3be2f3d1d4f3ed187aef04d6": { - "balance": "50000000000000000000000" - }, - "43160b2bc00f7f8f7fc806e2f6e2ffdc62b3a651": { - "balance": "1000000000000000000000000" - }, - "431b77cdd067003eeed26c1aee32f67fb94f7092": { - "balance": "902514849986000000000" - }, - "434e44583786e354731bca250d94ef0d8860a538": { - "balance": "1187789683866000000000" - }, - "434f1b9b193c88bf58685124aac0167fe69f9014": { - "balance": "500000000000000000000000" - }, - "43535982688844fa703cb9bd5723790cab364049": { - "balance": "100000000000000000000000" - }, - "43559f405590592c254e427fa25f03e774d8defd": { - "balance": "6913200000000000000" - }, - "435c08c481d59308a64afec0d6f936321bb120bf": { - "balance": "9005920819593000000000" - }, - "43629748a92b846f21f637aac5103412fbabb9a6": { - "balance": "1177513692845000000000" - }, - "43650b37552882d225ccc977aa2b7a86a4ca9bb1": { - "balance": "16000000000000000000" - }, - "4385de394371d26a45f18e8b3842effd015027bf": { - "balance": "187331693412000000000" - }, - "4386ff9648fe420503c9a36fe7b97c079de3b770": { - "balance": "2714401478778000000000" - }, - "43b370c4457cf39a3be86cc00c2b27614ca6e638": { - "balance": "8316429850934000000000" - }, - "43c464ea740172fe6f4f09974106fd24029837b9": { - "balance": "129643160399000000000" - }, - "43ddd2d33dcb7e578f4e59ad6b9c61a24c793aa8": { - "balance": "500000000000000000000000" - }, - "43e0f8065eb7faf3bbd13bc7c5d5d8f5ff1bdac3": { - "balance": "4454324716300000000000" - }, - "43e96cd065d7934b246d0fec8cd2dc6b36d56d7a": { - "balance": "81721481452000000000" - }, - "43e99acabfbdc6cafee3afb12fa7ed1345370b2d": { - "balance": "4595292398872000000000" - }, - "43fae764c7555b859b93d2126edfa59cfbf298b5": { - "balance": "105746805109558000000000" - }, - "44052eb938c02776b5240f38ec99f5ef51ef0d87": { - "balance": "38446396949881000000000" - }, - "440fc7621cc17f121f0bdf2a68c5be2c3af4fd3b": { - "balance": "1026958147051000000000" - }, - "4440ccbc77249a4d891d9ab5a5f2026b17aff7c7": { - "balance": "10000000000000000000000" - }, - "447f3f702c13a3fbdc8675c6285702b5aa2b66bc": { - "balance": "1089533398014000000000" - }, - "448f152be153fdb0497403f70e37d876946a5021": { - "balance": "614429461682000000000" - }, - "44a1e3a044f5d1fb00f4beb3772a3ee08d8b7093": { - "balance": "1000000000000000000" - }, - "4515edc7154bedd7143b69a04c4e738f8aa4ab18": { - "balance": "10000000000000000000000" - }, - "4572148fe5ea9d4795e1f1ed93097aac1d70991c": { - "balance": "2873782218000000000" - }, - "457581f223b8eacd757abb292613e317d6f59305": { - "balance": "3582446780073000000000" - }, - "45b450961882850f7038d5cdcd2a8fa2dc4b5469": { - "balance": "20000000000000000000000" - }, - "45bdfdf3840d4341503cd7fc87e4b66f6179e5fe": { - "balance": "10000000000000000000000" - }, - "45dd9baa87b3c94df66308d8ed4f3a5bb65c3dcb": { - "balance": "25000000000000000000" - }, - "45de332b8ee95d886cf11b99291b46f46c1ddd45": { - "balance": "36000000000000000000" - }, - "45e06afdbc70288a2cc55bccc4fb2d8195aea028": { - "balance": "790360485306000000000" - }, - "45fce5fd1acb2bc5507723c897cb340437e39735": { - "balance": "100000000000000000000" - }, - "46045cddd940d80596826ce5354489b3047663bb": { - "balance": "100000000000000000000000" - }, - "4610286f8a2649dcfbc6d91735745f418a6abc75": { - "balance": "10000000000000000000000" - }, - "4615905ecc6f7df0ccb7b86a3e1d3770adb2f874": { - "balance": "1000000000000000" - }, - "46256e00ff927d54b0ca139ddccac2148784273b": { - "balance": "10000000000000000000000" - }, - "465e40e7d129ad310fc60ff0f17c0f968611118f": { - "balance": "677971225649000000000" - }, - "4664a920f7fe9b0d78a665e1a4aeb95f287d6059": { - "balance": "20000000000000000000000" - }, - "46679de1c6143138fd9c44ff05853a52371915ff": { - "balance": "363627463229000000000" - }, - "467cdc210ae48ba99740d37ee79fa57c4216bc81": { - "balance": "10000000000000000000000" - }, - "468053d193debb88735571acb24b764f2676272e": { - "balance": "49000000000000000000" - }, - "46826d1f1418abbe4e7b9236d643e5b57a0f0208": { - "balance": "37752144164916000000000" - }, - "468df2ea57972ddeb88d470a5f3c2c0e2284ac17": { - "balance": "757320434551000000000" - }, - "4695ad5b686520ee8426d24b50ff7a5f0d703443": { - "balance": "2851082366000000000" - }, - "46a149bc8ec2b85fdf938f753a6c53777dcca2b1": { - "balance": "10123698633000000000" - }, - "46c081440f760a21b74c2499bdda13aef8245930": { - "balance": "180752319265000000000" - }, - "46e615324f6e4fb242f9bfecffc0c802ba7733c9": { - "balance": "10000000000000000000000" - }, - "46eb54f09dbdaaf3b97a1f79a3d82ee2e902b3b8": { - "balance": "3430510380318000000000" - }, - "46ebb24b04919ec0164f0bafcebca2309f2d3035": { - "balance": "129155832233000000000" - }, - "4701f9fe78111011f820fe28c47522e601655678": { - "balance": "9000000000000000000" - }, - "473f44e2c1d5d7aa53cf7041d7ad19a0d9eaf1d8": { - "balance": "162679637505000000000" - }, - "474f8bf4d03a7efa4d190905ce062eea7c75118c": { - "balance": "1259904506149000000000" - }, - "47598330e862a4f7cbda8be74ac10cd5d370a55e": { - "balance": "291763101699000000000" - }, - "476455d48fc858a06bd7854fcf1bd60bcfde9ed3": { - "balance": "10000000000000000000000" - }, - "476826d58192ad822f4686311d6c6d4d4f66ee5f": { - "balance": "453184657722000000000" - }, - "47a231eb3fdbc24f2d008f06228624b2a45ae5fa": { - "balance": "1000000000000000000" - }, - "4805f4c0eb1c83c436118ec9148019e5fc1962e3": { - "balance": "1311161626928000000000" - }, - "4809f373cdd56c8481ba3bce5a401d55a7e50a50": { - "balance": "2284845194349000000000" - }, - "4839bf9ad56873abd5695057bf71972806cde827": { - "balance": "42264923611000000000" - }, - "486dba2a47decabc9a85d1d64d74687983ab273b": { - "balance": "49000000000000000000" - }, - "4877993f5ecf02451f8d4591594cb2f30dcf9f26": { - "balance": "100000000000000000000" - }, - "489723e325f609e27be14528c4111fb3eec13f7c": { - "balance": "2489030141000000000" - }, - "48b710d16e9da736b773453089d69cc6ede116b5": { - "balance": "26651593216000000000" - }, - "491088e1e4b5c3d65870f2deef9be6ec3dc6c7c7": { - "balance": "1446809481953000000000" - }, - "49174451320ad2e14cb2b05ecdd251b75ace3038": { - "balance": "15533380764616000000000" - }, - "4956ead915594b621131b2fc2dbbb49ba43c5559": { - "balance": "1175638488000000000" - }, - "4973a0d32147ba89f525a18f989518dcfce93b0e": { - "balance": "522848489444000000000" - }, - "498c6f9063705054fae07260d4176c3d55a97650": { - "balance": "732941433000000000" - }, - "49991f68f2a76bd1cffa3e9721be36f3fd8351b8": { - "balance": "17742568700019000000000" - }, - "499a8af194e0040f349e893937fe3858f8267fca": { - "balance": "80704784160862000000000" - }, - "49bcbb7b263febf54f8ff498525bac8e7241f966": { - "balance": "603044032468000000000" - }, - "49bd72773656c4e1a4d16284aea2fb05546d2b31": { - "balance": "1896607093054000000000" - }, - "49bf80fcdefebe8cd4830ba09e46ccd7231c8e6f": { - "balance": "10000000000000000000" - }, - "49c9d82dea78f14b1c52efc0196b67f508f7859b": { - "balance": "2313040051399000000000" - }, - "4a2daeacf0468d137e3bc464d6d5fa3893a9136b": { - "balance": "10000000000000000000000" - }, - "4a6c428f245e8d9115b34764bab17eb86ac472be": { - "balance": "10000000000000000000000" - }, - "4a6e8d037acf1960dbbf14e7a02fec0ac656f9c1": { - "balance": "6516295825438000000000" - }, - "4a7e7fc3c72f2f9b92bf0dcd5297cfb19f077d7c": { - "balance": "99426213999999999" - }, - "4aaa6817a5000bb7596e000135b3051c5931e7c5": { - "balance": "102884105546478000000000" - }, - "4abcdc3d7d3d314a163da92aee53a56b87313a2e": { - "balance": "44402243657000000000" - }, - "4ac9385ade2377b061f4211b392ed6a6e7fb83cc": { - "balance": "1000000000000000000" - }, - "4ac96e1e26cb66ff788ed8c62db811d7b4fdbc74": { - "balance": "68476115774000000000" - }, - "4b10c247caf33fb872d9bf86572424410aa86752": { - "balance": "337915294240000000000" - }, - "4b23ffff1894df49005c7afc0828880924571299": { - "balance": "169848767272000000000" - }, - "4b486895caf3a0b5afa198df744de7082eec8666": { - "balance": "1672587376054000000000" - }, - "4b98fc960610573be456c0e1e319f4f863bf9095": { - "balance": "259382246718303000000000" - }, - "4bc0cc483be20223f40ed6deef63dd9645c216c4": { - "balance": "4322684620000000000" - }, - "4bf4a046afdd4ec9d0e50730ff6ded5ef2327442": { - "balance": "70601389160000000000" - }, - "4c0149058e2e74f7c900e6d6e5fa12eea882c5e0": { - "balance": "2017399852886000000000" - }, - "4c17a3997fb70599794d01a33a27a6d5b52b6f01": { - "balance": "469002093209000000000" - }, - "4c4559e7b32340dce112cf7a021ced1b113f6dd9": { - "balance": "25000000000000000000" - }, - "4c4f02b3f232b8ce8485d425639271510cd0486f": { - "balance": "68828038140000000000" - }, - "4c52ec56142bb6e8c8830e5c17b01b5165915f3c": { - "balance": "321766233041000000000" - }, - "4c58defa57875e709ca039a54a2be5aed6672f6d": { - "balance": "121000000000000000000" - }, - "4c5a886ab90b6bac68677a7eb92a06bf33ff2930": { - "balance": "236899852150000000000" - }, - "4c60539363edbd812334a54543c40ecab8af2ac8": { - "balance": "3281904094699000000000" - }, - "4c76897d0d5d39195354194710c5e7f99bef63d1": { - "balance": "10232271258305000000000" - }, - "4ca3c03780c20a64f3b5ebb75669982a71ee8a71": { - "balance": "377172198976000000000" - }, - "4caf77eefe062a6f053a464171bc75254b47f52b": { - "balance": "20000000000000000000000" - }, - "4cb7d7ce805e56f6e47e94cd755b6d97f8f996a0": { - "balance": "120998866000000000000" - }, - "4cd34f8f3299d3b7aaee180baa0b432369e1b3d6": { - "balance": "197088135242000000000" - }, - "4cd7aaa5415d809f405f520e4c0319a6029b981b": { - "balance": "686627368232000000000" - }, - "4d01067555f1ef63883f25c562b07168f79fa80d": { - "balance": "17547055698000000000" - }, - "4d2cb4c1da53e227b08c0a269402e9243a13f08d": { - "balance": "324000000000000000000" - }, - "4d38bb5f48ec37b751d16de32a4896fbda479ce1": { - "balance": "802530078718000000000" - }, - "4db3e76e2f68896cecc9826e10a5e09df0352c28": { - "balance": "555180306924000000000" - }, - "4dc8730d9f032d33dc493bcd3c6375b38f41afff": { - "balance": "5726933881000000000" - }, - "4ddde96556f5185a13617f01ebd9102800bc9e9c": { - "balance": "1181822708402000000000" - }, - "4df9359cb204bf649668ff8086a7f5e24709083c": { - "balance": "262998978400000000000" - }, - "4e0a1a3dff0d33c418758263664b490140da9e01": { - "balance": "100000000000000000000" - }, - "4e0dd6d8de5caa3a3bf9fdd6f2d7b30618623cc0": { - "balance": "10000000000000000000" - }, - "4e11af85d184b7f5e56d6b54a99198e4a5594b38": { - "balance": "76658631121000000000" - }, - "4e314349abc52c686d47dc771ebc8040966be386": { - "balance": "632341985941000000000" - }, - "4e3fb09c35375106bece137dbe0e5491e872871b": { - "balance": "153648535396000000000" - }, - "4e4f0d606f7065bfb1545e60b5e684ae1934e055": { - "balance": "48998635468000000000" - }, - "4e50957aa6c91c548075add8ec625b74c0973abd": { - "balance": "1000000000000000000" - }, - "4e5c6efa76493f0e9422582016aac50539ae60d9": { - "balance": "2078967343000000000" - }, - "4e70bbcb50c4e875fd573dcb694908abf3b30b37": { - "balance": "20000000000000000000000" - }, - "4e7f5670a7dd168a0803e53b8bf72f4db280e3ae": { - "balance": "1658463113665000000000" - }, - "4edaf859990a10977bf378df45b32f93422c84b4": { - "balance": "121000000000000000000" - }, - "4ef41923a1a426772832d3c267adbd84e5994edd": { - "balance": "5432615017384000000000" - }, - "4f11a70d80f36f46ed0c2a5fff1a39b711f3bae5": { - "balance": "8415785077000000000" - }, - "4f159095afcc75b8f5cfc90c9d07a0d77ac8ed69": { - "balance": "25000000000000000000" - }, - "4f2652322736cc18b24af582d4022fe329a9dfb7": { - "balance": "9000000000000000000" - }, - "4f328173f352f3dfdca0ff5e3185f26de77c6f75": { - "balance": "10722917874680000000000" - }, - "4f47a62aba6ea049fc0e92d8afbe1682472d98bf": { - "balance": "10000000000000000000000" - }, - "4f4c3e89f1474fe0f20125fae97db0054e9e14e0": { - "balance": "50203638983000000000" - }, - "4f5ac8dfe79c366010eb340c6135fbee56f781d8": { - "balance": "50000000000000000000000" - }, - "4f672cbd373183d77d8bd791096c6ebb82fa9a2a": { - "balance": "978111227765000000000" - }, - "4fb179c9c88decaa9b21d8fc165889b8b5c56706": { - "balance": "24750205150000000000" - }, - "4fbcf391c765b244b321875d6ab4381c44d0747a": { - "balance": "99999580000000000000" - }, - "4fc979b38b981fca67dfa96c6a38a17816d00013": { - "balance": "1088876196468000000000" - }, - "4fdfdd1832b114b4404aae23305c346beee14e1d": { - "balance": "278724179057000000000" - }, - "4feffb1836029cd0e9b8f4aa94b35ae3982fa770": { - "balance": "1674590934924000000000" - }, - "50045745a859f8fce8a2becf2c2b883b3723b2c8": { - "balance": "169000000000000000000" - }, - "5028bde29fe88e03e3de069b3907fa9df551c379": { - "balance": "196000000000000000000" - }, - "507096ed771fa8a1d004ee5377c01506df461b32": { - "balance": "2669205000000000" - }, - "50788574a0967580fdaddc4758f834d8978455f6": { - "balance": "1648581593000000000" - }, - "508d8e8f338ca98d3c09f0f15fd9e7baa80701e8": { - "balance": "16000000000000000000" - }, - "50a4dc916845172b83764a6c8b4b00d6d02d41d3": { - "balance": "3020744393592000000000" - }, - "50da06418780c220ced4898af0b1fca533f73cca": { - "balance": "36486700700823000000000" - }, - "50fb6fd8432a66219e754234e9eea1dabcc07676": { - "balance": "489500000000000000" - }, - "5104bb1b831902333732dd25209afee810dfb4fe": { - "balance": "1333614132000000000" - }, - "513963743ec6ec9dc91abf356b807ebad64df221": { - "balance": "1508002412172000000000" - }, - "51397ca69d36e515a58882a04266179843727304": { - "balance": "941648956414000000000" - }, - "514a58f2b36c2cf1b6293c36360cf658d8af30ed": { - "balance": "1233397704089000000000" - }, - "514fe0cdb3de692cab9f2ef2fd774244df71be66": { - "balance": "9670444445882000000000" - }, - "51583128081fd800d9550144afebdf3fe88149cb": { - "balance": "231190355520000000000" - }, - "517384fe92391187d0e65747a17bfaadf967c331": { - "balance": "1943121865489000000000" - }, - "51aebfaa26a54071cfe6c2d8f81157ec313984ad": { - "balance": "1422225031261000000000" - }, - "51d4f1205b272e491e94fe21f0341465f14141fc": { - "balance": "552384783614000000000" - }, - "51de598faa85276bb26a68b135028755304b6700": { - "balance": "2068484560002000000000" - }, - "51e08e0304f08ef768c80ca149da4721fcf482b0": { - "balance": "194629207228000000000" - }, - "51fa3da695e24f602952a71966f37ac3596a94a4": { - "balance": "17008166261720000000000" - }, - "520b22776b1befd3064636da0dd251afe569ef13": { - "balance": "18538137781909000000000" - }, - "52219a1e1aa82b78b971088c30583a3bbe675c8e": { - "balance": "411959222637000000000" - }, - "5252b8a0688096523498cb5c1f42bcd1f61923d7": { - "balance": "1863936864000000000" - }, - "5259154e1a5a809b2e3dab80372124cebbfd56e2": { - "balance": "110000000000000" - }, - "5264f2de516835e549710bfe34ef03b08b8557dd": { - "balance": "1216000000000000000000" - }, - "52b17fae7e9cac447f026db71dba4034a1d53174": { - "balance": "99001631977000000000" - }, - "52b3363ae882a99354faeb76733d0fa2cbb89787": { - "balance": "102517584327000000000" - }, - "52bee7fb24a7fc1f34cf0874ec2f06c5fe847cb1": { - "balance": "54443400591000000000" - }, - "52d1f12d391c7a2f3b52939a61a20da5f85eecc3": { - "balance": "2707175772061000000000" - }, - "52f27099483589e883e7eb789896de39c61e46da": { - "balance": "358944977251000000000" - }, - "52f3b715b678de95d1befb292de14c70f89f5e03": { - "balance": "2989868434000000000" - }, - "53259780569f6dd6753c1da1d53d0b155c5b30d2": { - "balance": "200489122590000000000" - }, - "532e4908e8297c90d75d2280b432b469aaafa2ac": { - "balance": "20000000000000000" - }, - "5334d1e399feacabc9648cebcd93172db95d43be": { - "balance": "25000000000000000000" - }, - "5341665addfb5e367f7a7d35de95b87a0cceb3a9": { - "balance": "60544291695000000000" - }, - "535a39a854ed1c2f0afbc5944f1ee0e2e68cf65a": { - "balance": "2141913781000000000" - }, - "536515c0c08988ee69da1d75f18c706f6b9bf7a3": { - "balance": "169000000000000000000" - }, - "5387a1ce4cd2ef4f90075c15dc3c0744948ec356": { - "balance": "50000000000000000000000" - }, - "539a30ee5724978010990718bb8b0dd25f89fd15": { - "balance": "1306896514000000000" - }, - "53a5f87dfb17149b8c2934a2a9d519ace4ac9724": { - "balance": "4569449510000000000" - }, - "53b24fb36e72c22eb830dc93857a8188b03397a9": { - "balance": "64000000000000000000" - }, - "53cc35b3daf4b8e1982e0e63d0bc68d7252e7fcc": { - "balance": "68213426853658000000000" - }, - "53e1f85147e000ae1ff6a5910407395e388c683c": { - "balance": "20000000000000000000000" - }, - "541f43ff66ed5eb1a1ea0ae3f86355ecff665274": { - "balance": "49562725831000000000" - }, - "5428a31f736c0d2b3c4e80baefb75a76ed44d3f7": { - "balance": "10000000000000000000000" - }, - "542f732aec0873bf531f6941828b6f0ed0611106": { - "balance": "8407722276000000000" - }, - "54300b6a77b95545373b2bba73e60f37c31eb1c6": { - "balance": "1581215621996000000000" - }, - "5434bd65a492a4d14d3b97eb49f6e491350ef73c": { - "balance": "484000000000000000000" - }, - "5444a1735913eeac177d947ef38de7cd6bdfc0a6": { - "balance": "1000000000000000000000000" - }, - "544ffeab53bdc59ef8edaff0042b03c2ea123615": { - "balance": "10000000000000000000000" - }, - "54613713df6c5b89c3012a7835651f25cdac8331": { - "balance": "98684037547000000000" - }, - "5471fb39b4e48c118f855492830ad9e2eaa68179": { - "balance": "91791250228000000000" - }, - "5472591efd048dd60a4d6afdb549e95a65578b0a": { - "balance": "50000000000000000000000" - }, - "547b4c1ae70567fd77a896dc05eb536f502ac8a4": { - "balance": "14037444012000000000" - }, - "547fa9f6f86a2939f9144aacb74e0af60d434535": { - "balance": "428416957729000000000" - }, - "54841d6a478cb9b6e717a9de35577a1a4a504b0d": { - "balance": "144000000000000000000" - }, - "549157e5b1c92a88a0eef335b1bcf4d162482017": { - "balance": "21019502942000000000" - }, - "5492757c55c72ac5946b21514ee16c5065ecde7b": { - "balance": "10446737491000000000" - }, - "54984a41eeaa8e710e4e5b8a7f68c96057b7df3a": { - "balance": "10000000000000000000000" - }, - "549a3717a1bca3f38d24655197c3ccef1e8c273e": { - "balance": "4416133255000000000" - }, - "54b047fbe004191cd02f31163d29bd61ccfaadf7": { - "balance": "52649445905000000000" - }, - "54b125d8b260386633b756056b7d7e78e7071715": { - "balance": "10000000000000000000000" - }, - "54ffad1ae76ab45c4218ced27e49bf2745b2a2e7": { - "balance": "1426474871178000000000" - }, - "550b28968bae36f4e99780c6d7deb54c158be6d8": { - "balance": "10000000000000000000" - }, - "55117923e8393dbf233c0f10819e7de75569962c": { - "balance": "470094520022000000000" - }, - "554a2471e6ecf2320da545d559c40b8b622465ab": { - "balance": "4052895973949000000000" - }, - "55607b39da9480ed8f54d74d0818ab8798136589": { - "balance": "13704276648975000000000" - }, - "5561cbe99fd775f5d0f05903fd62ba4877b3319d": { - "balance": "1007596371374000000000" - }, - "559ba7ab58670d4a0b118bbf6aed7f6fdb276594": { - "balance": "3127762973000000000" - }, - "55b0bc444f2a5952a98f216f61cf07382da1e156": { - "balance": "18683409750727000000000" - }, - "55c0a02dc68123aca7ee0c9cd073ead50b16406e": { - "balance": "99999999580000000000000" - }, - "55c47d593952afd637050c5758a921a204f23fc6": { - "balance": "1615608723958000000000" - }, - "55c6855b3970e5a550f0c75d5727329476406d91": { - "balance": "600705012673000000000" - }, - "55eadbe33899f53138d0fb204f42e272f447cfd6": { - "balance": "1671128311341000000000" - }, - "55fa59fa0fbba06b7184ea78868d438176eb96eb": { - "balance": "1553000000000000000000" - }, - "560a11493b5a0ec28589e80276fe975ee26c6a3e": { - "balance": "10000000000000000000000" - }, - "560fbb31d83bf6dc49e5fb15bd582d70c49fd273": { - "balance": "46015432815000000000" - }, - "5620e17ccf094b1be1a93f6f3388fb96e3a90165": { - "balance": "484000000000000000000" - }, - "5633512298cf74f4d2b8663e6f291e9e25436e7f": { - "balance": "10026444446000000000" - }, - "564423f92b8841b3b1f8bdba443067b580916e65": { - "balance": "465451550122000000000" - }, - "56730e1d11a84970355c43ac7659f2f4786dadcd": { - "balance": "20000000000000000000000" - }, - "5678851984add045f3d054623c198dfd4665d54e": { - "balance": "227651903234000000000" - }, - "569cf18b4bcb99e3f3d27235f2c4c0d8d160af03": { - "balance": "4124979731000000000" - }, - "56ac5f2c3486a9ce744a71599ab89a606e7464a7": { - "balance": "9000000000000000000" - }, - "56bc5936a6ea37c1d0839bf64bcec0d366840ace": { - "balance": "14741201469670000000000" - }, - "56bf62e0135e903525cc46b0a3cce33f4a16880a": { - "balance": "534970476270000000000" - }, - "56da0781a80a0abf5dcda4da35861e9de601bfbb": { - "balance": "166898390441000000000" - }, - "56db15729e52d615a744a04f8a59d63e3b9f735b": { - "balance": "10000000000000000000000" - }, - "56e32ed78e7f5be6b00c28847efe7b3589cdae1a": { - "balance": "1046236086484000000000" - }, - "570f7a08150e0088178276f8116bc4103f885903": { - "balance": "1124393518440000000000" - }, - "57147fdd9b52ef53b4ebd4b5712d29da83f99374": { - "balance": "39000000000000" - }, - "57395fb355fe51f1b32c1baa4e9ee0fc2b8fe05c": { - "balance": "7701013675397000000000" - }, - "5752f0f11ed12bb1d5041b0cee4ddd500cd8806f": { - "balance": "151337200533000000000" - }, - "575907d73ad5ad4980a2037efbd20860afc67ad9": { - "balance": "3568754158000000000000" - }, - "576acb4c0bccc89903ad285ac08c70fde514aaf2": { - "balance": "25000000000000000000" - }, - "5784cb8a17cfb5392c4aeec2edbd173849ca6ee3": { - "balance": "15804767597000000000" - }, - "579234645eb857a3ca51230b3a02b964f8efa2f6": { - "balance": "20576922380000000000" - }, - "57989f9fa52b4c0502e7d0c3caac0c37a0b20516": { - "balance": "462711082812000000000" - }, - "57a55c376ea03c22e21c797d83e2fb039508ad3c": { - "balance": "10000000000000000000" - }, - "57d1612ea1fddacf088b62f625ad8cd49d7517cd": { - "balance": "18001023230648000000000" - }, - "5811590907050746b897efe65fea7b65710e1a2c": { - "balance": "310984892882000000000" - }, - "582ffd8c43966aa8ad3c6cecdfc18eddc56fe5c0": { - "balance": "69136214255000000000" - }, - "583b90b3c4d00b9ddf101efbce75bb811d969fe2": { - "balance": "7839200298177000000000" - }, - "5841fee8b1965141e51b8c146b6af00f6a879a8c": { - "balance": "1210322907244000000000" - }, - "5847a576f7799ba1a35e36906b2c2a5aadeb99b1": { - "balance": "183765768447000000000" - }, - "586dea7ada0a54150f5afcf54198db473ed046a2": { - "balance": "7123598380000000000" - }, - "586f545062ec7dc0ffc213eacd59af80660df570": { - "balance": "10000000000000000000000" - }, - "587187488758f67912bd5bb8a5be787a73d97ee3": { - "balance": "702757402654000000000" - }, - "58be0a3482dc3411571f047f4128387049cb9798": { - "balance": "1000000000000000000" - }, - "58d546e2ae82efc4d8efc887ac6fd30f7eb5dac6": { - "balance": "1486717153455000000000" - }, - "58e7010e6b8d97a556c0e7f0d90151224ebf674e": { - "balance": "20000000000000000000000" - }, - "58f991b3b12d29f09ff4cc2c6e83d576e95b1f59": { - "balance": "25000000000000000000" - }, - "5923a65a796934e69081715657e8dfec8874e40d": { - "balance": "10000000000000000000000" - }, - "593b7c43073b8954355ed76020ff3780dd6ae783": { - "balance": "1403468567787000000000" - }, - "5947f1dbd79a622bcc3fa64b19f9b6eda164dcce": { - "balance": "50000000000000000000" - }, - "596311e2fc09ae1eaee57900f2ca188afd5e68a6": { - "balance": "448723397560091000000000" - }, - "597a3adac4607d457c90817220f67eb4abcf129f": { - "balance": "18000240000000000000" - }, - "598201a9bcff0a773e9323338a8a094e9d9b3999": { - "balance": "74904485722481000000000" - }, - "599e93031704c2ce36308f44d4ff8166e71ae516": { - "balance": "100000000000000000000" - }, - "59af0178699f9f3d8f0ea645dda75356119a6e2e": { - "balance": "152462578058000000000" - }, - "59b0c06e40475cd75728797add9c69c3fdb17b4e": { - "balance": "23147237210000000000" - }, - "59b79577f183b9d39c2b458646a26b2fd6ed806e": { - "balance": "4244859516807000000000" - }, - "5a03b51d67a9c660258ebc030120d5d1d4f687c5": { - "balance": "4451691855300000000000" - }, - "5a0d03dff6754963c757eb15a3339ac6c4ba6196": { - "balance": "215126489934000000000" - }, - "5a34ab3937854e407a8739fa14574d3d20e30d6f": { - "balance": "1375979293937000000000" - }, - "5a352fbeb2fd78bbe0268b0efd34f68d401e2769": { - "balance": "27929247671418000000000" - }, - "5a47c2ca4c0fad7e2fc7bbdf5f2356d68843c564": { - "balance": "3218227936000000000" - }, - "5a538adb2c7f6a80634b0ec20ec5152ff6bb4d5f": { - "balance": "10000000000000000000000" - }, - "5a8fe770c221072a7cba79ae7759cae0185adde7": { - "balance": "11913943233694000000000" - }, - "5aafe1efac688583d7facb09d3e569d58fb5a357": { - "balance": "4713219466825000000000" - }, - "5ab68d762750d5185138187db7751c9f71db5836": { - "balance": "500000000000000000000000" - }, - "5acab69851959dd5a6f0673ef757009ed36dfa3b": { - "balance": "974443209942000000000" - }, - "5ad9f2ab11b5e59b756404395f350aad6019d7a7": { - "balance": "54151179981663000000000" - }, - "5b1dc013ba1a28235cc70e785a00eff8808faef6": { - "balance": "516289257133000000000" - }, - "5b1eeb44ef61c7f35482503b7041162bec9b1e32": { - "balance": "125493885394000000000" - }, - "5b3db31996bca4625d22330686128ec234270206": { - "balance": "362316593128000000000" - }, - "5b401fc9ff3be7cdf5f0df870843bbef94f43285": { - "balance": "1373804724122000000000" - }, - "5b47ba296069041f25768e61be14437b8a469e81": { - "balance": "3152706392234000000000" - }, - "5b5030b5057c0457c190489c5d709d7dbdddee8f": { - "balance": "1154404278000000000" - }, - "5b5a4a782d37154a307868cd79bec9cb2a8f0161": { - "balance": "100277816425153000000000" - }, - "5b5e0b6b7cc27b06456ba4c7816ac4e89e1e26a3": { - "balance": "1023749119000000000" - }, - "5b638e4b6dfdb6928b07586e63d5879dce69a1f8": { - "balance": "1000000000000000000000000" - }, - "5b7be81d6ff5228a2b8c2913deea3f86823f1dee": { - "balance": "36000000000000000000" - }, - "5b7c4804bc2b8c72f3112b73d44b59c0711f83cf": { - "balance": "6803857604000000000" - }, - "5ba26d941544d07100744d8ffd6595a8eb7770bc": { - "balance": "583051897662000000000" - }, - "5bd58fc88733632b63d4f26893bc5c08fb60e2ad": { - "balance": "3480620567502000000000" - }, - "5bd85b5f0ecad08133fceb486c43998e537b3451": { - "balance": "484263880245000000000" - }, - "5c12639a5ab107f9e580cbd2278568dde10758d6": { - "balance": "101293252434000000000" - }, - "5c5522df05d6c6d960394c4762599e74247ab102": { - "balance": "149088856773000000000" - }, - "5c722f3ac94421f95389756af9cd97d0eaa6b696": { - "balance": "1435349483553000000000" - }, - "5c7b14ce51abf629bb0953ee4e2d9d87fc86eb4d": { - "balance": "10000000000000000000000" - }, - "5c8b215403da4e7912c1a1704a949087e091b111": { - "balance": "1440961256910000000000" - }, - "5cab313964f6730888e4158234bbd4806db0286e": { - "balance": "32284637230203000000000" - }, - "5cd736bf65c99469490d0523b10a658178cab10b": { - "balance": "99740204082000000000" - }, - "5ce91ef7ae254b2bd6d910cbf0d380814200811b": { - "balance": "50000000000000000000000" - }, - "5d15fc3a0ba8b3d87b80f9bbf972320112c644f9": { - "balance": "64000000000000000000" - }, - "5d2ccc795b19df400f21f24c0dca4d0e9e898093": { - "balance": "10000000000000000000000" - }, - "5d879b8b31af1e400cf53eb7170f82583190b96f": { - "balance": "93765337844000000000" - }, - "5d8dd54178b68bb36e1963d47d29c123864fd0ef": { - "balance": "20000000000000000000000" - }, - "5da1653bbe8353134edfff6158211ad7ee21dbef": { - "balance": "1491149937915000000000" - }, - "5da733ef41a7bdc0cf7975f83ed24604fbb4d40b": { - "balance": "10343699901151000000000" - }, - "5ddf5d7306f7c603b8d3ff993f03906dca14cd8b": { - "balance": "862558469755000000000" - }, - "5de87ec54e2160c7c2a8eff2d859414737501ae2": { - "balance": "21579321171000000000" - }, - "5df1b805b1361c1f39ca844aebe5ecee8a8d06b2": { - "balance": "411820472746000000000" - }, - "5df86b0a183b5e7f702e4da582ce9a8116a05f61": { - "balance": "256000000000000000000" - }, - "5e22359e20dc14be6930c6c1ce5a0c81c039cac7": { - "balance": "10000000000000000000" - }, - "5e2d38a06f33c784303abf2012f9af12622d9e5a": { - "balance": "10000000000000000000000" - }, - "5e479e616585e7fa84bd6f7465d394a1c0302be7": { - "balance": "10000000000000000000000" - }, - "5e4a55027a0d372f6da042b7f73720b143347d9c": { - "balance": "16175516772000000000" - }, - "5e52e86eda3e05f96e353d7e3f0ee90f08864f84": { - "balance": "21255916842000000000" - }, - "5e91c4d3a21c9dfac2c0994ed8890c78d58626d5": { - "balance": "325349462011000000000" - }, - "5ea797b18caba45d5504e57b80b12f5f5ae630aa": { - "balance": "7805696321000000000" - }, - "5eaec8815e859c34dba88cfe7b7fe28572c964ba": { - "balance": "145852682588000000000" - }, - "5eb974b5716fc4712d431bec7fbb2c49057a7b84": { - "balance": "4890681156035000000000" - }, - "5ee5f8407dedbac839f509419051106219458006": { - "balance": "3042761975468000000000" - }, - "5ef782abb28d1ca889ceb3039eef98713effbf32": { - "balance": "40915083108000000000" - }, - "5f23b88f06430c42570ac3fa33b1c7503b388a3c": { - "balance": "2376070180325000000000" - }, - "5f2b1641c0f2605b090039851aacf297e35632ef": { - "balance": "141615261000000000" - }, - "5f44cc8083340e644d19d3debc84dc14a0cbc53f": { - "balance": "291829106275000000000" - }, - "5f633f89adcc70e9da0b66611a5da108b4b221cd": { - "balance": "50835573000000000" - }, - "5f94ef8e9612b03a5c6ffcf423ada9a19a40818f": { - "balance": "102566595099430000000000" - }, - "5fae1977b76a5e899b384f572e4d94855f9cb52f": { - "balance": "773616125740000000000" - }, - "5fbd22cb3de462c794e523fd1ce36f230cc84b83": { - "balance": "1009995132839000000000" - }, - "5fd91676bc95bd6b5e69db8b9216dc83ed9dddaa": { - "balance": "1000000000000000000" - }, - "5fdda8f5271a08cf1b830faa497019d75fa9d231": { - "balance": "4149626365000000000" - }, - "5fdea351c5eccedf2394fb54437b149ae423ecf3": { - "balance": "100000000000000000000000" - }, - "5fe70ee123cb2e03c768138b2f71c1e1ea75ad17": { - "balance": "1074496282650000000000" - }, - "5fec9df797214459f85a040a559b186ee9161c88": { - "balance": "205282872821268000000000" - }, - "60037df7e4092466656a6b9571437fc4600c66e3": { - "balance": "1000000000000000000000000" - }, - "6009a0bcf531640a5a7f1664a69fe0f64b564ede": { - "balance": "50170000000000000000" - }, - "601668d8b678c95ec5ef98d9d2624decbdd52e9b": { - "balance": "23592727870000000000" - }, - "6027bafcd0ade24fda8c345dcbc812d59df74bf7": { - "balance": "10000000000000000000000" - }, - "6029514f24825c1fadc68cf8614951de5d53268f": { - "balance": "1389262963614000000000" - }, - "606de6db14272a314d778cf0e67913b7fabea45c": { - "balance": "144000000000000000000" - }, - "6074f20675f975ae2c081930cae8f299710f0bba": { - "balance": "10000000000000000000000" - }, - "60850fa9e09d414af3690e4b5daefb1b906b0d20": { - "balance": "10000000000000000000000" - }, - "60ad0b6239dda5df7ac0f0ca941684cf20ae0fd8": { - "balance": "81000000000000000000" - }, - "60d6136e6db631be45fefb9667c3dfa69e9d6054": { - "balance": "651902184266000000000" - }, - "60d733dedec6886908520ba57cab8c9d5c2d7f7a": { - "balance": "555461746642000000000" - }, - "61202238aea4010d115c5c64322ad790576cee43": { - "balance": "10465801848035000000000" - }, - "6142d92b61111657de4b2d65698a3621411e3adc": { - "balance": "100000000000000000000" - }, - "61879bc1a022d9cac8b7d57c8f528065beb10bb2": { - "balance": "72766025231000000000" - }, - "618b15c9a60ad89e7fc28afc79bbf7f28d4998cf": { - "balance": "444855210015000000000" - }, - "61c1169e8ba43ee6b919e5be2eac19542eb913b4": { - "balance": "500000000000000000000000" - }, - "61f1cd6efce17f5458325f022f363fd9772d8f20": { - "balance": "19704989598372000000000" - }, - "61f7d39211a0af2e226d8cbc95fb673168653b0a": { - "balance": "484884476279000000000" - }, - "621aa67f09e6506efb2fd141f080fb1d96693a57": { - "balance": "1694451603196000000000" - }, - "62332fa5127b98bd2a627a0ac22d3a1bdb418efd": { - "balance": "926882233406000000000" - }, - "624a465696ad409586a2e67d84750ba50a971fee": { - "balance": "25000000000000000000" - }, - "624d866f0d61bdefc3ec2210bfe36b6d51018f9c": { - "balance": "199592183194000000000" - }, - "6255d6d3b49443891661b209056d530ecd63bcca": { - "balance": "10000000000000000000000" - }, - "626c484055e6739d46e2ff25190c8b3a4af3fe0f": { - "balance": "1485276462321000000000" - }, - "62865e637d723393ab9654d6439db7fb5abf8803": { - "balance": "10000000000000000000000" - }, - "628a47761d5ce755de88444aaf6d7736b911672f": { - "balance": "18625552918216000000000" - }, - "62df6a38e8b15a1c4f4a7aa7c1736c612f54a0e4": { - "balance": "16468111299582000000000" - }, - "631d7916ddbb5f7c469f8ba07cd48e377560319d": { - "balance": "2493487426430000000000" - }, - "632754f5afcae7dc36d9286cfcd91c14abf0f7bd": { - "balance": "1424933496931000000000" - }, - "635788343997ea9f145c508b0cd2ed36e180f46d": { - "balance": "143040938538000000000" - }, - "636973e7dbda9e3042a8c03e25696d0faf27f025": { - "balance": "5491869128148000000000" - }, - "63707efa26d34d7ceadf4e6439324e7bde0ebc3f": { - "balance": "1000000000000000000" - }, - "637d92494f7872d397340c9b5183dce354c8c43b": { - "balance": "724687404033000000000" - }, - "63b9c2e6762a431752f7669b8bbedae9f37120b3": { - "balance": "1360967549741000000000" - }, - "63bd281d8c4d1279519237a2b68f2a73c228f7e1": { - "balance": "217457311664000000000" - }, - "63c0eb8c9a0019e36ec9a731b4bd947271a5bed0": { - "balance": "36693488147419103230" - }, - "63c6362eff56de328a29b7e9d32ced28f3602b6b": { - "balance": "148335309448000000000" - }, - "63c979c787a7b037693cadfeda738ae33178c009": { - "balance": "81000000000000000000" - }, - "63d4621d91906215d32f6fbcee1ac48bd773f630": { - "balance": "1006939236069000000000" - }, - "63ff99fec1cbd2f6e83c0e6de3c0ea4b7c7e1398": { - "balance": "1201300688980000000000" - }, - "640ffd856e48528b05d5ef1e60348048ce291960": { - "balance": "20000000000000000000000" - }, - "641c25f7c380e2745c81a268384a029b2e2be0cf": { - "balance": "635133477665000000000" - }, - "6427792a164bbeab45f6c3acf17c76f721b90e81": { - "balance": "10000000000000000000000" - }, - "6437986b4c545af9c4a5ee96371a5807275e9221": { - "balance": "2951152516627000000000" - }, - "64460d09d1bc5c425d62bef5969eb0c5916963c3": { - "balance": "1680000000000000000" - }, - "646381f92216b97abbd86ca100a773eebdf7545b": { - "balance": "211234535515000000000" - }, - "649f73d1cafeb3ab0631432f04c9d08b9f438c22": { - "balance": "248900746448000000000" - }, - "64a239be45a92df83bb85b25f8ed7de5d82313b9": { - "balance": "100000000000000000000000" - }, - "64a3d97f82e3d42eea78bbcee31a95d33767b055": { - "balance": "2511466286000000000" - }, - "64ad579975888f455217e0f801e371900d9814c9": { - "balance": "7118859416319000000000" - }, - "64af5edbfec8adea679951662c08a781175688bb": { - "balance": "822966999709000000000" - }, - "64b7f2c22c20a59c07cb0dd7f8f692153c68f3f8": { - "balance": "20000000000000000000000" - }, - "64bc17e28d468b7b8368ee8a8375710d21c3ac5d": { - "balance": "875002262415000000000" - }, - "64d17aa662e56061cebb3c2e2421e637163e8dd3": { - "balance": "363241251465000000000" - }, - "64d714ec3145308e8f939bab7591b0773038b886": { - "balance": "338231954012000000000" - }, - "65199fc9ba95434382c108b44ac553534a9a3670": { - "balance": "2537340957145000000000" - }, - "6527c67c29e47833dc2440570596023318a7bd99": { - "balance": "555434226832000000000" - }, - "654b9d299077c90768c5ca6635e5802e8099f51a": { - "balance": "119004827465000000000" - }, - "655908513607cc38de35351ff3738b201bbf39d4": { - "balance": "652902936029000000000" - }, - "656ad16063b2d397788c231e537384ece94eb0d2": { - "balance": "63116382606000000000" - }, - "656e622970b8829a7cfe24f5b82696c7777683ba": { - "balance": "20390269890405000000000" - }, - "6583a6ff4dfcf447e3b163a61b0d5cb84ceee375": { - "balance": "3858529344000000000" - }, - "658d2b7e8a6517256efafd74321757d5c384a2b9": { - "balance": "221114751567000000000" - }, - "65920758857ee5b27b0f31487ccc3c5d6986df3a": { - "balance": "16272975796000000000" - }, - "659d60d67a07774ecc5cfea9e56809bec024d639": { - "balance": "20000000000000000000000" - }, - "65a1a3f968bab5fc1f097b8e297099a3d34ef45a": { - "balance": "16000000000000000000" - }, - "65b5e3163d20b2a6fc75c0219b7f97d83479a26d": { - "balance": "1716459529041000000000" - }, - "65c9bc3b8b0ce7c4d16b35abe1a5c285a59f672e": { - "balance": "20000000000000000000000" - }, - "65d5b458d9b1a9659c1125d20d970d5e6c29dc3e": { - "balance": "20000000000000000000000" - }, - "65e75bb8ade25eb7975ea12b9afdb17ac21063b3": { - "balance": "2270407774714000000000" - }, - "65ed78d0c4ef1150e8765b24b210f056e079cd59": { - "balance": "500000000000000000000000" - }, - "664ee5e334b8378928becfbf5d5e51daaf001125": { - "balance": "860160259186000000000" - }, - "6679bdb26adc179d046607d49f4b10c65d8a40d1": { - "balance": "436794739763000000000" - }, - "6680fe9d6eda3ab9fc4ac1ac933339b533eb682b": { - "balance": "551296206326000000000" - }, - "66a1249501cc5076b040bbb165ce032ace216ea2": { - "balance": "36000000000000000000" - }, - "66a475d014c2f976704bfb93ce78dbabbfc5e072": { - "balance": "1140135640169000000000" - }, - "66ae43d92e8fb2231fee8c72d720ff90cdd267ff": { - "balance": "796696150339000000000" - }, - "66b7e0c810d6959afa8210f6ca67e3e40bd24eb9": { - "balance": "16000000000000000000" - }, - "66bf8be16f33b111b2a425743bb7ebcdfbb35034": { - "balance": "538590591000000000" - }, - "66d2eaf7fe10900d93eab17823ebfde5486aa2b7": { - "balance": "121000000000000000000" - }, - "66e525bb01b3ede1a4a105bb6087ec8a76200616": { - "balance": "1506610219207000000000" - }, - "67291e0df83d6e9f1386e87a1792d7d147341df9": { - "balance": "272330177662000000000" - }, - "6730b27b62e064b9d63df3bcbb8c4bbb0e500afe": { - "balance": "331282968154000000000" - }, - "67318617bfe19b739fac9a126fd129223db52498": { - "balance": "12699924981000000000" - }, - "674dd0b036c91f3a83288af44897b4ceb2e15a12": { - "balance": "4352791270187000000000" - }, - "6751bffd04be55c86692994fed06694cb78b62ff": { - "balance": "26049487516000000000" - }, - "6768d99a0cdcd7bb7c7d0aeee466d6bdc7208bbc": { - "balance": "309909685000000000000" - }, - "677ba2de3e5c68a4c354c9e3129ed1c41025312b": { - "balance": "127426274611000000000" - }, - "67b83745856551f1878027843be20e1473191944": { - "balance": "185757248875000000000" - }, - "68170edcfaf2c6df4e6542b2856ad33e9e2d6623": { - "balance": "4003453949471000000000" - }, - "684ae403d9a08e4f4f971cfedf81094074daa77f": { - "balance": "25139713925794000000000" - }, - "684f3b8a749c002aa434bad6af7a3e2579c69315": { - "balance": "16000000000000000000" - }, - "68538a9e8246be5a5c5ea315cb325344062cf8c4": { - "balance": "14009193210480000000000" - }, - "68935ff3a3a3b6ef16ae7df58cee50b157658dd2": { - "balance": "20000000000000000000000" - }, - "689f508256ea64f5dbd6bb77f1ce1bdaf36d7152": { - "balance": "10000000000000000000000" - }, - "68a3e6e7c191a8c1add988bfbbb9b51d4f36f521": { - "balance": "10000000000000000000000" - }, - "68a74ff2a5577321f854b56d3834a55d3c41bd94": { - "balance": "88873831171000000000" - }, - "68e6da521bde13cf4e4f423a78fda2f69b3d1c2a": { - "balance": "538392460838000000000" - }, - "68ecd5cf8cf8d9704fafc36d8da53930afeb0553": { - "balance": "1090923641219767000000000" - }, - "68fd0b8e000bd2788be6cb10fc0496fe2cbe155d": { - "balance": "32853847745000000000" - }, - "6904045feb5ef94e096894b863d314ff8a0f206b": { - "balance": "9892165615000000000" - }, - "690fbae5153849bb20797af7b8dea66a728a06c3": { - "balance": "6082107223716000000000" - }, - "693d909842877d017e0f102e37a55024517dd0ae": { - "balance": "20000000000000000000000" - }, - "694cd00fac9cded484ef2cfcd44faf161354f288": { - "balance": "3049716150137000000000" - }, - "6964c3c2c7bc719ec94a51bc4bf412e137d2b4e9": { - "balance": "1000000000000000000000000" - }, - "69a5c692516940bebad8efaa2243a8fbdf2ade62": { - "balance": "2803346939929000000000" - }, - "69f566c44802b0140f5e1c9234f46006773c03d4": { - "balance": "20000000000000000000000" - }, - "6a17eef3a6bd407260f52067592226448182cdc3": { - "balance": "1116509364305000000000" - }, - "6a200e99a0f50aab32fa7373c7880817c81f472a": { - "balance": "1836680122795000000000" - }, - "6a2a29f5f441876816dd17856051040787f48a64": { - "balance": "1131603204000000000" - }, - "6a3f855c7dceb75d0de7fa18fbc2f40c81b76756": { - "balance": "32267494586000000000" - }, - "6a46af653b938643e781cc4a0edcf5357852fd21": { - "balance": "1140718780752000000000" - }, - "6a4b2e5b45da0d70621ce71f165a11078a1745e2": { - "balance": "3768326643000000000" - }, - "6a530c813595a5b7776cced05a865dedcb110d94": { - "balance": "270559347097000000000" - }, - "6a6e3e82f98ce891f47721770301dbe2652a9e25": { - "balance": "10000000000000000000000" - }, - "6a828d6f2f7f68bde4a12608024020e593540010": { - "balance": "7531817000000000" - }, - "6aaddd1f4ff6b4d414c87271619b826ead27f09f": { - "balance": "64000000000000000000" - }, - "6ae6bce1e2865ade0d02eff9899ea3767b5511cd": { - "balance": "6893781798524000000000" - }, - "6b04e7c6a837d218fd3322b87a267fdd979358ef": { - "balance": "302679180175000000000" - }, - "6b2210b8536803b134e69c5046904acafef48cdd": { - "balance": "47823456459000000000" - }, - "6b2da6f36c2e7f61cabd7580480065360c995c93": { - "balance": "55000000000000000000000000" - }, - "6b3401986f2be7ae5a4ec160b8f96b2a651fce73": { - "balance": "16000000000000000000" - }, - "6b3847774e99dec307dcf5bf5adba49df4a9f145": { - "balance": "43276069579000000000" - }, - "6b57f2d9d95cac67fd2f70c0911d48c7f09de072": { - "balance": "1000000000000000000" - }, - "6b65d736a8ca89ec8508b52e4aca5166f9703732": { - "balance": "766421968820000000000" - }, - "6bcc55d897829e98fc3f3ac8beb331e59c33b942": { - "balance": "318115956882000000000" - }, - "6bd76e7af1775b88743d5f53ede0ce846d3d7ced": { - "balance": "139548017482371000000000" - }, - "6bd7cca99acf6eed5842417c2327c642df5473fd": { - "balance": "3321731000000000" - }, - "6bf72c4d39d6700181954a8d386c3df216634412": { - "balance": "12742769034078000000000" - }, - "6bfd3aedeac7c6ec086c0a4ec29d2d0f5bd69bc5": { - "balance": "50000000000000000000000" - }, - "6c025962810a6fb8374af5e07d7fcd631d10b1ce": { - "balance": "674126722005000000000" - }, - "6c1b72df836f410038af9e020fa2ff2ead398ef4": { - "balance": "1851293017364000000000" - }, - "6c1fddb4254ff46b3750de322ebb7d6238c0a606": { - "balance": "9977629348276000000000" - }, - "6c37069a361c5c72355bb5a56879dd0a9735a237": { - "balance": "1062230154063000000000" - }, - "6cb166eeca248a234c971b2a864a7b3fdbe5a737": { - "balance": "390222992865000000000" - }, - "6cb797289059cadcfa77eab0365e6bf1ae12df46": { - "balance": "100000000000000000000" - }, - "6cc787e6bb4f484828b080330667b93953e7a3c9": { - "balance": "16106440380234000000000" - }, - "6cdf7b334fb2ef8115198d475d431eeb7d88df77": { - "balance": "1940904395351000000000" - }, - "6ced85b035b787e9e427d0904aaf96e011417310": { - "balance": "103417697874000000000" - }, - "6d6e09acc07f388cbab99e53959f75e9ad8f07bc": { - "balance": "1305917678000000000" - }, - "6da91b02f512f412d374392247a9aaa853e9dd59": { - "balance": "2300525907893000000000" - }, - "6de5d70481cd40db468f64227228cdd362ad9980": { - "balance": "10447389944082000000000" - }, - "6dea87255c9ebfa63f017209046e894ecbbc03b7": { - "balance": "1527216854064000000000" - }, - "6df6f6b9953c2f2a8ce5985e19dd6835ae2c566c": { - "balance": "6539856530000000000" - }, - "6e013c83cac111a38fbbf8d47778fda0d3af25d5": { - "balance": "12139181929380000000000" - }, - "6e18a484f402fd433a5ac4dee5a4b8bf6f22db47": { - "balance": "23215906572368000000000" - }, - "6e4fd058e4dcd502c2015f83f3677f680ec58110": { - "balance": "480059342014000000000" - }, - "6e501ac7357fc758caf5dff6c29a995c806a1a7f": { - "balance": "1573491311733000000000" - }, - "6e6912f9fc21dfba736055e6ccef074dd62dcc59": { - "balance": "256000000000000000000" - }, - "6e869c68511c1458f4fbed9a4c5296fe961eb47e": { - "balance": "68488423994541000000000" - }, - "6ea6827b377b3d3ecf7c7628ed8daad7fd8eab1e": { - "balance": "188825714738000000000" - }, - "6eb9237738339fcaad3763466509f23efd0c5054": { - "balance": "48417242786000000000" - }, - "6eb92a61390f9d9ecdac80a8833aa801c3926b13": { - "balance": "1412936326723000000000" - }, - "6ecb93f18153ef2d2a552286ea3b7436f1f8168c": { - "balance": "20272577229669000000000" - }, - "6ee087c04cf16f4768c783a548686448fd125914": { - "balance": "1397039628538000000000" - }, - "6efbae7a34c71233329d0bb4cbec45274824ebf4": { - "balance": "8910000000000000000" - }, - "6efcd6776f287c25a6eb3cf71018adc282eeab6d": { - "balance": "1310659853178000000000" - }, - "6f9ca805ddaaea5205e85778dedb2eff4a5aaa75": { - "balance": "2585733757016000000000" - }, - "6fbbea927469f4d18942ce0aade164828fe23a2a": { - "balance": "4671857880000000000" - }, - "6fbe9df6c42151c453502960d99170445dd3ac0a": { - "balance": "20060296562115000000000" - }, - "6fed121fb310431f1659e637f35f4c878a7256c7": { - "balance": "55170085399000000000" - }, - "6ff2dd5373bd72966ef48d3183c60d74a6549cb9": { - "balance": "24103445361000000000" - }, - "703a490c4783776da244384c964897491aed3711": { - "balance": "2001677632732000000000" - }, - "704dcd2d9f75f0bbfb73f2fe58bcbf4508374381": { - "balance": "439603954369000000000" - }, - "70859a14f33b8ab873fa5781a4af1ce40dff65c0": { - "balance": "10000000000000000000000" - }, - "70b9cdfa5f6d41c60e1c0d3f544f569c9b340ea2": { - "balance": "198355566698000000000" - }, - "70d0ee793e28e320b34267ef2df69050fca0a9e0": { - "balance": "8010660534227000000000" - }, - "70dc7e5951752c22a0e3c50e8e7b1f7af4971d51": { - "balance": "3991137321749000000000" - }, - "71057f5afbed7d82c92d50790e3797fd7395d036": { - "balance": "49000000000000000000" - }, - "7109a3b3d5d6af49693549728691099d696ce016": { - "balance": "4119694297000000000" - }, - "712231a5161745fa1b33c7b0f6e8c767e1de4f81": { - "balance": "1353809351914000000000" - }, - "712aa38999c0be211654e5c84f59e3b2e018f597": { - "balance": "160199774000000000000" - }, - "713229fc94a86b71a5bd1ea6498b9373e3f3c549": { - "balance": "98289185940000000000" - }, - "715de29a0b6f467b94d4a90dc767ad52d0fb3b9e": { - "balance": "948824982990000000000" - }, - "71776853ac97ce04b008c9a7b64156a3cafc52a4": { - "balance": "608309596513759000000000" - }, - "7189f6dcfe64e1ddbfb5e51fd5f3174bc636dd0e": { - "balance": "5674608906899000000000" - }, - "718a4da87464caf6e83ca374d5ef9255b8f7cc3e": { - "balance": "761891873568000000000" - }, - "71bc447761cdb68915cc2288b4929fdc0adce02d": { - "balance": "10000000000000000000" - }, - "71d78531896642069b725bf82fc385789c63217c": { - "balance": "33103960195000000000" - }, - "71e328deeafbb1724051d1062609c43eef56ecdf": { - "balance": "493550967964000000000" - }, - "71ed0310fb51b86a61794aea17a3c792dd301e3c": { - "balance": "3234918634449000000000" - }, - "71fa264f58041e41cfe36e8f8d4e0cb22ab71925": { - "balance": "5558941960000000000" - }, - "72059c57d0fc05bc02ba54ebea6cefd1efbeadf1": { - "balance": "4458278271443000000000" - }, - "720847a28916a532bcab33e1fcbde5d1c4d820bc": { - "balance": "1392418942284000000000" - }, - "723cd2b5b836b0ee8481d37b9c51b5f3f1beddd2": { - "balance": "1856420455522000000000" - }, - "72430c6664d23c7051b0e99912fa54dfadcfdeff": { - "balance": "102078926010505000000000" - }, - "72652c4320dda25348f15c0ecfeb4b3b3ceeb7c8": { - "balance": "307639955659000000000" - }, - "7288bd1b9f4c068dd5df9bcd6fec1ccecd240195": { - "balance": "80161087899000000000" - }, - "7299cb8a288abe8e1a22c11b53a903acb7db5827": { - "balance": "752198565719000000000" - }, - "72f6bc0c3ae437756c099e02e9c084febedc5569": { - "balance": "696294297587000000000" - }, - "730e5907b344c80e0a6115723a90a23e3635192f": { - "balance": "6056082041729000000000" - }, - "732e97b992e4f8a53034cf29cf11aacba7452261": { - "balance": "100000000000000000000000" - }, - "7339df65ce293b3d501647a04c83819099f0bd38": { - "balance": "706500983417000000000" - }, - "73482f8135ca2231db5e0e034a235a9d244a8656": { - "balance": "1143989148865000000000" - }, - "73769e43058d30a530048e5a2bea7e9333534e93": { - "balance": "113542901996000000000" - }, - "73bb9e6f1709fbb7964df7b3cc0f9170c3152f38": { - "balance": "1639793026701000000000" - }, - "73e261da7978764044ee916f88bf66680952607f": { - "balance": "100000000000000000000" - }, - "740154120c4f41c50b0aaa0636a2000ff1e870ad": { - "balance": "10000000000000000000000" - }, - "741fe2a1537284b70e97e3ff659eedfd7fc5b1b6": { - "balance": "75911502037000000000" - }, - "7420bb277d834763e4429db9bf37f053f71ab769": { - "balance": "3100160195046000000000" - }, - "74281371c3b569c774da6bab686e7d7a45d4dc4c": { - "balance": "25666397941223000000000" - }, - "7428d261b5418652c5ab248d6abc3d2af25d904a": { - "balance": "56252809397000000000" - }, - "742c876433297f5a8fd4a25f75ee9a607726bd3c": { - "balance": "4132793019677000000000" - }, - "74302036cf52e11aa3f32a371bb4992e2bdc3f39": { - "balance": "19557661364000000000" - }, - "7445c657c24d014f3a9dddc3e446868bc2dbd13e": { - "balance": "10000000000000000000000" - }, - "744b8fa69d2542be3557267edaeaf2cfa8a9e991": { - "balance": "16000000000000000000" - }, - "74728999963524e7cc1736abcb4deac630142c44": { - "balance": "37000250991000000000" - }, - "74926cbdacd0e871cad0d926c8e17cb2c00475b9": { - "balance": "20000000000000000000000" - }, - "749e115a9e675bb15af5e1c04f81fede07c40120": { - "balance": "440913547154000000000" - }, - "74b7e01acf825898544d6c1b61e53356be759c56": { - "balance": "25000000000000000000" - }, - "74c5fcf875e2e9b726a7cf6e176dc2f7eb84c200": { - "balance": "59208835472000000000" - }, - "74f44579859e4a7944dda7bd810088e116ae9910": { - "balance": "1038454108527000000000" - }, - "750b1e2955ba05c1fc8a1f9dbb1624ed11587edd": { - "balance": "9545712605000000000" - }, - "75375129cff2a051f656b91f868325c3b35ee1ae": { - "balance": "25000000000000000000" - }, - "753ca28fbd89081382a996fe938da7e6c3ae6cfd": { - "balance": "156582454263000000000" - }, - "753d91c04e554680cc32a97c1abc96280e8263ee": { - "balance": "725101425969000000000" - }, - "754e5b5d64c267e83fd4804d112725531cf5abe9": { - "balance": "83276113115000000000" - }, - "7588a96a2bc65569a6c124c4a4acc55863a8ab78": { - "balance": "24062602342000000000" - }, - "759075dc3a6b9d2499a74bc57e346c9ed7ff834e": { - "balance": "225000000000000000000" - }, - "7591d6fa043801fe12462e11d9e33a53f438c073": { - "balance": "1863874274000000000" - }, - "75bda5bdf6aa749bbd62b6107941a7dd9ce3880a": { - "balance": "36000000000000000000" - }, - "75c2d3a99f144c4b9962b49be9d0a81b203906e8": { - "balance": "9000000000000000000" - }, - "75f587a69a97eb4d1c4c4078418d5fa85dff6f94": { - "balance": "10000000000000000000000" - }, - "75f67649605f49d98d866102ea2d6881ead9bea0": { - "balance": "814929108418000000000" - }, - "7602abce0f510b6ca471fd8d734e21a2591886f6": { - "balance": "50000000001006000000000" - }, - "7629b788160531b0be28bf445bf305fbe2c514d2": { - "balance": "23022256366212000000000" - }, - "762aed2e3aa2293e69dc2110b1fc6c806ae799a5": { - "balance": "10000000000000000000000" - }, - "7637b89130bc3f87e90c618fd02d6dd27179101d": { - "balance": "77765738300000000000" - }, - "765136022facade53e7a95c0c7aa510787e674d5": { - "balance": "1478178932688000000000" - }, - "765274015a308a9e6b1f264e5bac592d267f2f7b": { - "balance": "3058788819393000000000" - }, - "765cbc0a89fd727a2c1a6b055139faee53f11330": { - "balance": "500000000000000000000000" - }, - "768bb6d4b190c18a0946d92073ee446d68d98a6f": { - "balance": "144000000000000000000" - }, - "76ae8079894c760f2850c02cf5a0d7bb41e5864d": { - "balance": "156059816821000000000" - }, - "76af4103a231b1302d314c486a0ba524d0427899": { - "balance": "10000000000000000000000" - }, - "76b6394cd02ddf761e981b6a6ce1654c0e575443": { - "balance": "1078304803757000000000" - }, - "76db33eafeaf965dcf15d5460b64a48b37285259": { - "balance": "1000000000000000000" - }, - "76e5721c0a39d41274f84cb572039967a07e9beb": { - "balance": "156298167226000000000" - }, - "76e6ca6ef145d2711ab27f82376a065cc6f62a29": { - "balance": "100000000000000000" - }, - "7705d637cf9f6ceaa452deaca7ccc581beb5fa34": { - "balance": "36254762908065000000000" - }, - "7706c80af4eb372e168501eedfe7bda6dc942243": { - "balance": "50000000000000000000000" - }, - "771493da92c9fc6c6b39a4071ae70d99f6a588d3": { - "balance": "2000677471360000000000" - }, - "7719206286f26144c0f20b5e1c35cf4495271152": { - "balance": "1380480863056000000000" - }, - "771adcba1409fa2df6db19d9f784abc81a7bbf36": { - "balance": "15416381820915000000000" - }, - "772f7baa80a852e05b2fb3903a36061da132b2d8": { - "balance": "121000000000000000000" - }, - "7731a4175eee5077e2ede48878e6e2a18fce0f9e": { - "balance": "10000000000000000000000" - }, - "77385deeba01e3cd7a63e13d6048011020f56724": { - "balance": "57204247488000000000" - }, - "776808e7688432755b9e91a838410d29e532c624": { - "balance": "120318608715941000000000" - }, - "776d1b406f63082b80e250c4a0073fa0d83b9090": { - "balance": "243779839900000000000" - }, - "779848a59036ee3cd23b93ff6d53620d874f0bee": { - "balance": "82228810849000000000" - }, - "77d02a031274bd4ed2a16f3cc29d94e755142036": { - "balance": "408567696646000000000" - }, - "77d609a407aa0d126d58090b8d635f5ab7a02d6d": { - "balance": "776754055755000000000" - }, - "77dec41e116301dbd6e542f139816bfd9bf6d154": { - "balance": "16335989583000000000" - }, - "780398b42f81167731a8ef6a8bd1d14942b83267": { - "balance": "25000000000000000000" - }, - "780a645d59027e7b0670d9565898dc00704cbe5f": { - "balance": "20000000000000000000000" - }, - "78182a7711c773f306ec42ce6da3e983cd49b00b": { - "balance": "580861257254000000000" - }, - "7822622f07fec12995c4bb8eb32d62aa7f00be05": { - "balance": "5018461926846000000000" - }, - "786410c679101c0ebf06fb4f36102368121f3c8b": { - "balance": "16098386724761000000000" - }, - "787d5476038ab0a09b846645285ada23ffd7318c": { - "balance": "492047430907000000000" - }, - "788e9e27ed979d1e7aefadda798f69df1de1d1bd": { - "balance": "30965301214000000000" - }, - "78ab2d2dfaf5d2580ed89c970e771572bc91d3be": { - "balance": "36000000000000000000" - }, - "78ab7ac6f379ff084a7acf4a1a31fe2e5a6834c0": { - "balance": "107332516726000000000" - }, - "78aba95da37385c736ef93d0ca8318baf6c5ff3e": { - "balance": "9000000000000000000" - }, - "78cecbd82229dc91a530bd555c9e45125e2a6bc7": { - "balance": "28474069251604000000000" - }, - "78d4df90990248f3ac67e492a0a1e3f4ee455507": { - "balance": "10000000000000000000" - }, - "78f6de3768abc604c49b10d798e0656948cd334e": { - "balance": "9000000000000000000" - }, - "7909aca95ed899743de222e56c231f9bed1b518a": { - "balance": "5355599376491000000000" - }, - "79193e660b4431e8aca9c821b7daa88064e33750": { - "balance": "100000000000000000000000" - }, - "792487caa23b0d9b9998002810cf29439f7190bb": { - "balance": "4828579961131000000000" - }, - "793f56adea51063243a9633ecc1d1e620a91f327": { - "balance": "926742377449000000000" - }, - "796d187077c1d7591583436ae64d10a641490ca5": { - "balance": "242664407084091000000000" - }, - "79a6b7fad3b5a655679450ca82818ec2d6f58688": { - "balance": "1400472715109000000000" - }, - "79acf627e67cedf48297c26fd135973bff6c57da": { - "balance": "444598475759000000000" - }, - "79ae0dda1964ff0191b98d28c9b52a79dc9ab078": { - "balance": "325908985422000000000" - }, - "79e71dcc52fa1b28226c519f715faa3cf63cfb09": { - "balance": "497898493594000000000" - }, - "79e98193ff8770f26af824734bbb1c2ce8197b6f": { - "balance": "10000000000000000000000" - }, - "79ff3d790d52c58b7317a415278e9058915d5241": { - "balance": "48502649691864000000000" - }, - "7a0b02d16d26e8f31e57106bbdad308f513d436c": { - "balance": "841000000000000000000" - }, - "7a1d422352ec7e6ca46131728e4b71f20ed84e2f": { - "balance": "50496873413000000000" - }, - "7a2a3fbe27e33df867ba8800788995d7662c046b": { - "balance": "100000000000000000000000" - }, - "7a629c4783079cd55633661d2b02e6706b45cf8e": { - "balance": "50000000000000000000000" - }, - "7a62d8875f53e54b775ee2f67f7e2ec137bf724f": { - "balance": "25000000000000000000" - }, - "7a67285fd883d36ea3107aa3fe7727c68a99eb2d": { - "balance": "254787158217000000000" - }, - "7a90fbec48492473d54b0fad128ceda94ea66100": { - "balance": "313715004199000000000" - }, - "7a9e11463d84a08140d698972e32e66bacf7a7c9": { - "balance": "3602603216258000000000" - }, - "7ac4f33e1b93ef0f9c15014e06da24904ef4419e": { - "balance": "101000000000000000" - }, - "7ae082ad247275fd5a9e77b127cee5693784e9e1": { - "balance": "1921957343533000000000" - }, - "7b27e070ca4158d13f8333b34842d4c28b678c92": { - "balance": "10000000000000000000000" - }, - "7b2e34374921e4dc10fd9cfc670a40f5d092da1b": { - "balance": "2098457950503000000000" - }, - "7b54c6c8041c8b09240de1ff06e0d3d2d8d877e0": { - "balance": "944752036841000000000" - }, - "7b5aecb798d8f4f5a04bdaef909e09a35bde8d47": { - "balance": "21975115049000000000" - }, - "7b88a7ef9201966bd1ca634779c3b7f40c22f0d7": { - "balance": "64344833519732000000000" - }, - "7b8c22ddc5c7e59e571587d7c776fa50e65f4845": { - "balance": "225108110445000000000" - }, - "7bb4d8a169f72432494ac362eeab005ce1e02d81": { - "balance": "2098993419448000000000" - }, - "7bbaaa6690698e749d095447bdd27207c0caee43": { - "balance": "490069993631000000000" - }, - "7bbf27f92f9f726381d4f68b21ed86af8f792d04": { - "balance": "806346082666000000000" - }, - "7bc6f172fd78953c3456c571ac8394756715d5fd": { - "balance": "81000000000000000000" - }, - "7bcca29b477730ee8f219a5d1bca24415c7a4625": { - "balance": "36273885000000000000" - }, - "7bd296e1cb29ad87ed28b0ed18440ee686b157e0": { - "balance": "35964679698000000000" - }, - "7bde6d49a1af34a5a9dac0b9007e9a5583c65ebd": { - "balance": "1041474566346000000000" - }, - "7bea6240f245e649563253fa4c1da39b12625da7": { - "balance": "100000000000000000000" - }, - "7bf096396c56f27f9c39c4056ee6cfcb0db44bc6": { - "balance": "407261849111000000000" - }, - "7c3b58d3ba283bd9b1580832e9d014eff48bff7f": { - "balance": "7074518779349000000000" - }, - "7c5a56c45f23c353ff9f6f71ec86c9a6a1a0ca67": { - "balance": "11277879639596900000000" - }, - "7c783ac9b07bc6576835635f37e7e3c137055c8c": { - "balance": "16253676225000000000" - }, - "7ca2fbc0a0d1370e95048a21a300eac4d6056df3": { - "balance": "2772084065617000000000" - }, - "7cbe95802a20eb765f9fcff0a068859cc35d2660": { - "balance": "255153842674000000000" - }, - "7d004fb3a6a81c00fd2872e8079ad2912841b0e0": { - "balance": "642630220843000000000" - }, - "7d30c788d4ea18849ebae1173373c8915ffd7a35": { - "balance": "61062263242000000000" - }, - "7d39324f5ff62e849b0f0f46ab8ee396fbd85581": { - "balance": "100000000000000000000000" - }, - "7db0ce6c04537417dca1dd3415a5bf213edc2028": { - "balance": "30393443462000000000" - }, - "7dcfaa795586c92f1ce7d5c7b10608fe6a773fe4": { - "balance": "183173395920000000000" - }, - "7ddd111cfdc3133f59b82568e3deefc3cf10b0d0": { - "balance": "5622149283840000000000" - }, - "7de81daaa7ed5cbf4d379cdd26ae353cbd5a2489": { - "balance": "10000000000000000000000" - }, - "7e0a11af993a41626c5564f719442c0dfd608ec5": { - "balance": "1532083534600000000000" - }, - "7e34971b187047e7f7980650630b936eedc11023": { - "balance": "10000000000000000000000" - }, - "7e5214e16851b33c4a4d29e5a06929461d3d9555": { - "balance": "371790231197000000000" - }, - "7e52ae9c7e4b888015a3a5af7a91444510aa18e2": { - "balance": "109879329128000000000" - }, - "7e69b383671f96b7abc2d1fed8b61477b87a58dd": { - "balance": "10000000000000000000000" - }, - "7e733b1fcadc9a20dc038fba74e236af0b5a39b3": { - "balance": "43583614302000000000" - }, - "7eadcf955c90040668fb0f75a61f687e4e41f314": { - "balance": "332201682206000000000" - }, - "7eb51f3ead1dd0f5384c199ad5518ec55f77d35c": { - "balance": "38487884822000000000" - }, - "7ee73c0d64caf46f47f439969060092ecafdecd9": { - "balance": "15063618320000000000" - }, - "7ee8e4c6742a4c6d8efbfacc4d56119bc6c74ea4": { - "balance": "31882319329000000000" - }, - "7f16d981521c06347db8324da38b25eab3cee23c": { - "balance": "400000000000000" - }, - "7f6ff7db81a26fe78dd80636f0b178c669344393": { - "balance": "10000000000000000" - }, - "7f792b094c0b96d6819823cf21bc0c402fc27bf9": { - "balance": "50000000000000000000000" - }, - "7f84ae97c21cc45a7e56603ddf97449d803fb246": { - "balance": "81000000000000000000" - }, - "7f89c2b9daba034841f19ae843cfb6cd6f75b1d7": { - "balance": "20000000000000000000000" - }, - "7fb18f8b0e1fd1ed8c863a66226082bdc0429ee6": { - "balance": "11465417544634000000000" - }, - "7fb4e30579c64efe981d0057204e5bd8770a1f87": { - "balance": "249801873762000000000" - }, - "7fcc4de10e837d98691acc52732e1568c890304a": { - "balance": "1000000000000000000" - }, - "7fcc77798cd50345b2784a78b81a25dd4c1e64ab": { - "balance": "2676882485895000000000" - }, - "7fe33e773a02b995278ff595d55a0741813b19d4": { - "balance": "5788279057355000000000" - }, - "7ff32b13d531ceef500ca6c6806ffc0773639264": { - "balance": "1000000000000000" - }, - "801380158ef8f24316bdceaa00eb89c3d886707e": { - "balance": "35627521347898000000000" - }, - "804fdccdc8603858d15dec88666437505b2a106a": { - "balance": "14607090269617000000000" - }, - "807915567eed99bb9146354a32409812b9490d70": { - "balance": "1083142734057000000000" - }, - "8092ceeb2be5b271f4c156d85fe14977e919c7e0": { - "balance": "761607160308000000000" - }, - "80962bf961d0d713395dbe00379a6e207b425a76": { - "balance": "524215754483000000000" - }, - "80a9787124075c8cd44b9c8674967a54445e2354": { - "balance": "7600078997429000000000" - }, - "80aacd59dd76bf443c47ca02976178af8453f23a": { - "balance": "411856023767000000000" - }, - "80db788f7fbd7613f0fff66c21389eedbbd4bd35": { - "balance": "956888725645000000000" - }, - "80e449a70e3c7707d6441ae8863a44aee2d7f3f2": { - "balance": "16260784762856000000000" - }, - "811a2c3d0ba4e1c36a848495585da824ec3a7620": { - "balance": "36000000000000000000" - }, - "812a3c55234d5849a854ad76891c34ee90c8a0e3": { - "balance": "703378980438000000000" - }, - "814b4b5eb67afb8d1a60e3d240fe804bb752f632": { - "balance": "17578964576000000000" - }, - "817025619f37838470b90d0a25af2c02de80dae6": { - "balance": "96000000000000000000" - }, - "817233a104d87cac34d9c90243aebd7f68e0a9ea": { - "balance": "510051038684000000000" - }, - "818be95c0c13c3018b4084ea177556705e84c1f5": { - "balance": "332239667000000000" - }, - "819618c19a4a490b821f8156c5633749ea782ca2": { - "balance": "10000000000000000000000" - }, - "81a80d26b70626e07e8747bc1569dd2855834f7c": { - "balance": "521696417321000000000" - }, - "81b2fb0db882bf2538cf8788bae1ad850cef3bab": { - "balance": "102457067052000000000" - }, - "81d4c3bf72837b21203b2a4f90bf42fda10acf48": { - "balance": "10000000000000000000000" - }, - "81df59e5d7b9a2db5463b53be83b4d7c7673d163": { - "balance": "887372337013000000000" - }, - "81ef38d074e0aa9ad618deaab01bcd135301fb67": { - "balance": "24072930558567000000000" - }, - "81f3a4c5291f13f8f97a067a6ed744a686331eaf": { - "balance": "56612148225000000000" - }, - "820610d0ddd3e9f3893f7cc13f32b1ad0d169f81": { - "balance": "50000000000000000000" - }, - "822d6388145e96cdeb2900420a0e0436e940b670": { - "balance": "20000000000000000000000" - }, - "82323b748fdee9f18e34aefc4ddebd4993ac6293": { - "balance": "112752706047881000000000" - }, - "82324995b36f4ff15be3559ccee14742d5b4c75a": { - "balance": "1184047304377000000000" - }, - "8235bfba0bf0fb664271ebe534616456a78852ce": { - "balance": "6804584686000000000" - }, - "824df7b17a61392f88f7e3067f8c261abb48806b": { - "balance": "144857897574000000000" - }, - "82555a7aebfc95a01a3773aa5370394cadef0302": { - "balance": "40069354268401000000000" - }, - "82831d451b8f92fbf6a763adb708010a3e66bb60": { - "balance": "8750983992240000000000" - }, - "8294176178418f46bb18440cc87a07cf40c1669d": { - "balance": "4439783816461000000000" - }, - "82a1c733c3c937ba0a1a49481e4d1f6226157d2a": { - "balance": "50000000000000000000000" - }, - "82ad0b5dc23bc763da0352f5983efceeaee6ea08": { - "balance": "171723633433000000000" - }, - "82b4a3d16655fd71f4020e6a562592a621ff6e1c": { - "balance": "190211621484000000000" - }, - "8357d5a016a00aa5e3ef05d3ce210826adf4c501": { - "balance": "10000000000000000" - }, - "836c41d7f9e72131eff839b7d510fd0ed412f939": { - "balance": "15575572364757000000000" - }, - "8377fff2b0eb03393543ddf5ffae90b3311af5d3": { - "balance": "2058810049054000000000" - }, - "838859e6fd751539a88d00581b0e19bc98c37e47": { - "balance": "338264241636000000000" - }, - "838da0414211392b644e73541e51e9f0fba26615": { - "balance": "20000000000000000000000" - }, - "83958896a43d23ef4ba01bdf6757c36105985096": { - "balance": "9000000000000000000" - }, - "83b88314b606df40d5e716df488980bc64125b46": { - "balance": "10985538717083000000000" - }, - "83bf53fa162e1d85751be0bc6f46e8ec881392e2": { - "balance": "1497107276676000000000" - }, - "83d7c52608b445e18fb1e28dc6198908d66bb6d8": { - "balance": "265446362740000000000" - }, - "83ee8ebaed62092d2116de6b4e90778454e8dfc4": { - "balance": "1000000000000000000000000" - }, - "8402fe573658250f50fbe111596ce35ea9ec01ca": { - "balance": "3479737676000000000" - }, - "8412b877e708a7d5db2a38d9b0f4f23d12231f63": { - "balance": "9225027744855000000000" - }, - "8418dcc09fe052febf2946ee22bcc8c53d548eb6": { - "balance": "3000000000000000" - }, - "84199f54ef96bda5e14f60aa1723e811f755d3bb": { - "balance": "129197612052433000000000" - }, - "841b1400f97ecd2ca008e7b4f5a95274bc3e99dc": { - "balance": "2095180906854000000000" - }, - "844177191a120d2dc4be9169ddbc3b5430e9e238": { - "balance": "3620793599287000000000" - }, - "84578fcffc73be7d65bfa81b0cdafd26885bafbc": { - "balance": "37592478429000000000" - }, - "8460acb05c6c476ca26495aec7224c2bf90996fc": { - "balance": "8999580000000000000" - }, - "84696cdb9f018d3e7bf453efdc174e1a586e9c25": { - "balance": "118007806297016000000000" - }, - "846a8a91d2890000d1e995fc1663cf5b7c22211c": { - "balance": "27266838638307000000000" - }, - "846b5ef52d5f7ccc17d9c7e5f49db807908c63f3": { - "balance": "375423381758000000000" - }, - "847409e5d6ed2c4e54ff97f2ed58217ac5fc3d68": { - "balance": "23972870617025000000000" - }, - "84bf432c967540caafb8bf49cdc9983e8953a18a": { - "balance": "453476687224000000000" - }, - "84eba1bb76f7a3f6d2b9052d068cc6c48d449d76": { - "balance": "17655334922000000000" - }, - "851245ef1637a07578241b3c35acf215908e1898": { - "balance": "1269389304110000000000" - }, - "853708e974fd4810655d9cd19fc8dbfd3d5e1e36": { - "balance": "18000534000000000000" - }, - "8547989af8c99a3432038a03d3fb30a054d90413": { - "balance": "10000000000000000000000" - }, - "854ba39bac4c7bf619804b6773fe43bc71f3255d": { - "balance": "15999580000000000000" - }, - "85636f3e113cbe1d1bbd1b3a23e9e98edbcb94f2": { - "balance": "1199038399611000000000" - }, - "857167896b859394babf897c4c6fa57b3a057117": { - "balance": "921057404898000000000" - }, - "85799226a1474371ca76f05597a1e3835c17e7d7": { - "balance": "562141544946000000000" - }, - "85a2221cbbb47e8b74fc2617d6087a98f47e2738": { - "balance": "10000000000000000000000" - }, - "85be0bd55fb9143ff17387914a82d0a2650224c4": { - "balance": "4038654147145000000000" - }, - "85c5ff0e4956ef0fb662a2cbf6a86325a53dac8a": { - "balance": "28690160424000000000" - }, - "85caff4ec0e1719ad963e97c1c02828683070370": { - "balance": "2022427900763000000000" - }, - "8630cc2780fee566f172ed0437264c45421ce675": { - "balance": "669721278148000000000" - }, - "8633d245c5f1b63403e3d7828dc197ce1cfafc0f": { - "balance": "10000000000000000000000" - }, - "867ccceae3192a27751d870ae13b1d3d2c3584dc": { - "balance": "1491436265909000000000" - }, - "868bed241f77983ff4a7a8d0bf121299b6b2248b": { - "balance": "5600000000000000000" - }, - "868ddd283a76a26c8bbb9761df3ca647bea267e2": { - "balance": "9000000000000000000" - }, - "8696e546f96f6e51f405905e095902db8bb90118": { - "balance": "533558981421000000000" - }, - "86ac0eae4e4c20cb7019325f4dbebad053f92213": { - "balance": "697960117764000000000" - }, - "86bef47f9d2cd7526495454eb4d1737510696a5f": { - "balance": "2938307902381000000000" - }, - "86ddd4e3f444b395be8b2b2b75c35c78877fefb7": { - "balance": "15615434748526000000000" - }, - "86f115ed19a32aba4f98270b8ad45820abbc4653": { - "balance": "151868798605000000000" - }, - "870f19e7ee358de61ad0fd3c7710441156d68f66": { - "balance": "674715936435000000000" - }, - "87141a2d3857fb8a328ef8e7b503ed965294c85d": { - "balance": "1609607183158000000000" - }, - "87257783d866af25a7a71b46ea6c2bd1e9ab9596": { - "balance": "64000000000000000000" - }, - "87298979a9a0dbc272b0e15b7e5f2e42639c9912": { - "balance": "722087160930000000000" - }, - "8757b784015f88d072229176cabefa358a0e95a4": { - "balance": "204003337866000000000" - }, - "8760e60a56c5b8b61276634a571400023f08e3ac": { - "balance": "1000000000000000000" - }, - "877e54ea7e8ab03bb8e2b842dadab16bf4ae0a4c": { - "balance": "341020957932000000000" - }, - "87919285fc5d98169bbd073cebb1b3a564264dd8": { - "balance": "579080463078000000000" - }, - "87c39cfaa9c82d84119f306e6a233a3abfbb0ad1": { - "balance": "121753433796000000000" - }, - "87d479659a472af7c8ea78a3c658605f8c40bec6": { - "balance": "20000000000000000000000" - }, - "87d933ad6fba603950da9d245b9387880e6d9def": { - "balance": "1087642723520000000000" - }, - "87ec448309024bb1b756116b81652ea518cf353d": { - "balance": "344562808694000000000" - }, - "87fbbe010837f8907cc01a5bbd967f402a216488": { - "balance": "185411503628000000000" - }, - "8805a3c529bef4d19a6491f3b7d7b1b7232bb93d": { - "balance": "264150205918000000000" - }, - "880ec9548864fcd51f711ab731d847260ed0e3d5": { - "balance": "723225945994000000000" - }, - "8818d160b56b18e196871a6c7ccf02112dc13342": { - "balance": "2857439182291000000000" - }, - "8836e25baa08c19a9b0155c57072582b49f7dbef": { - "balance": "5468425690148000000000" - }, - "885b6303d06142accf2ddddbbdd4a9379d1cd124": { - "balance": "11853214736000000000" - }, - "88656958d9cd758d71546ba52c4ea646b658c84c": { - "balance": "10000000000000000000000" - }, - "88740acdf9ab5711d015391fe8cf4a7c70a0bc86": { - "balance": "510027156671000000000" - }, - "8874966976d776c3154261afa802692afedf3d3d": { - "balance": "305634301700000000000" - }, - "88aea53c727d7a5dd8a416e49faba1c4f741f01a": { - "balance": "15358334295959000000000" - }, - "88b67d05997ae3852259ca638a00ce9b9e7e4a61": { - "balance": "278125551806452000000000" - }, - "88d730e074a102048008de81d3adcba831335736": { - "balance": "5984576042159000000000" - }, - "88da27b1f0a604a87fdedd9ea51087a331179cb4": { - "balance": "10000000000000000000000" - }, - "88efaa91dab9671f5c903e69aa6ca4d9a04b5ddb": { - "balance": "1996126782729000000000" - }, - "89a9d702f64f14fae4d1a69717744dd700208d9a": { - "balance": "251686323241000000000" - }, - "89ac81571265bebbf9d3c09e9459fd1ba7fb1297": { - "balance": "162368080974000000000" - }, - "89c75c4f0ce41d283587beba1a3e3efab05ca6ad": { - "balance": "16000000000000000000" - }, - "89d44cb81cc5a1bdf4d573c4954ee641f3cb91d1": { - "balance": "97965629614355000000000" - }, - "89e2fef4f7b7c255b36afa81cf4033b22de3db25": { - "balance": "7278615226888000000000" - }, - "89fe5d3cb5283c7b87daf6103bb568f92a230631": { - "balance": "64000000000000000000" - }, - "8a07242231f4a654aeea65b857d1519385a18065": { - "balance": "20000000000000000000000" - }, - "8a5a415f0fe2a8329e14628493d11ca20d4e482a": { - "balance": "157274758238000000000" - }, - "8a6ce9f270fe3ec33a013be9e5b1ef823c0dab53": { - "balance": "20672772672000000000" - }, - "8a6fe4fa2f86f879ec9b2bf643beeb0876da46d4": { - "balance": "1041983771868000000000" - }, - "8a765ff2b429dcdf59b65a34c4bb41798dfb5886": { - "balance": "355487172996000000000" - }, - "8a9b9b65a3d443a6e4dcf696a64983f3b625774f": { - "balance": "3185351572575000000000" - }, - "8ab1f5443cf9149773b9ddb69de3e6ea047ae38f": { - "balance": "161619949415000000000" - }, - "8abeacee0078e07fb417277e8bf15dcc2cdb9fa7": { - "balance": "144000000000000000000" - }, - "8ac0d9e0e77aa4ada4080604f2118b3a5a0f8102": { - "balance": "100000000000000000" - }, - "8adae0dc99300f60d31bfa619ec83d45b48ea22b": { - "balance": "697262590215000000000" - }, - "8aef59e59a27a8662043f1a4abcaf945a5e3fafc": { - "balance": "26780431538000000000" - }, - "8b3386f32e2d77526c223ee8bb95b7dd111ced92": { - "balance": "2179932854210000000000" - }, - "8b34d5e457ef6451bb7f5ecc93c80678a30e3194": { - "balance": "31492358338840000000000" - }, - "8b47e07f192c33bd7d298bae717dfcd68a8097ae": { - "balance": "1000000000000000000000000" - }, - "8b55bff4b281f6a24ab428d66b91f9bab06f7b96": { - "balance": "1596248680941000000000" - }, - "8b576b1e2391f22193bb4f91bec5f2a8aec02af7": { - "balance": "29660301836269000000000" - }, - "8b9097b762c7bc38a487974f3551fea697087553": { - "balance": "260887123991000000000" - }, - "8b92c50e1c39466f900a578edb20a49356c4fe24": { - "balance": "35654824979000000000" - }, - "8ba3933337108841a997accf0b5735e005373f53": { - "balance": "574965182000000000" - }, - "8ba3eeb2d1b27e021ed6bf5827280807f32c7897": { - "balance": "64000000000000000000" - }, - "8bb23a5b8c48ec5bde84f39b463559b7c048c853": { - "balance": "16186405874000000000" - }, - "8be0b6ab14e15b46905335d07df03726fb1df0e8": { - "balance": "500000000000000000000000" - }, - "8bfc53af1ae6931f47ad7f7ed2f807f70fddb24e": { - "balance": "20000000000000000000" - }, - "8c0599df87df142d3aea37d50c975c1813ecb642": { - "balance": "871085782287000000000" - }, - "8c2deeeaf095be075a2646ed7b8764d3665acf14": { - "balance": "10000000000000000000000" - }, - "8c3e7381b0598356ff81e860faf25390ae7de9d9": { - "balance": "36000000000000000000" - }, - "8c5671a6f4610ddbd05a5139659c7190f54117b5": { - "balance": "50000000000000000000000" - }, - "8c60582c4e4e60da665b4a5a2d18f514ded6c49d": { - "balance": "16806447782991000000000" - }, - "8c8464ea6b17687eec36ef04966d59c7c91fa092": { - "balance": "1872124465602000000000" - }, - "8c85c5a318cc0227576adba3e91dce6adc73f6a2": { - "balance": "52479305517000000000" - }, - "8c8f3796a2942a2298d14ff1a9e3264e9f63f2bd": { - "balance": "10000000000000000000000" - }, - "8cec1886f2cc71b09ca32a1cf77a280ae3a6a9fe": { - "balance": "500000000000000000000000" - }, - "8d0b26d57eb52a62814d7876d64c8274f4371464": { - "balance": "20794037603000000000" - }, - "8d40b92e41f3cfec06e767d64b4dafc5612133b6": { - "balance": "25000000000000000000" - }, - "8d41ea1cfb70d0ef1f6572fd72a6b417739ac7dc": { - "balance": "738777348304000000000" - }, - "8d4eb54646f9d14882fc8ebb0ef15f6056d1afbb": { - "balance": "1003867239086000000000" - }, - "8d51ab29ccd190bfe12bcd94a651e9f49a003253": { - "balance": "442251355663000000000" - }, - "8d6c0c8e4ca47626115433b39feb939014b8738f": { - "balance": "119828137027000000000" - }, - "8d7acd92d664a485625bb9884e7cac9cc6077f41": { - "balance": "1381910232084000000000" - }, - "8d7ee7a9c1c263ba8061f54dcf62d9f8420e2008": { - "balance": "20000000000000000000000" - }, - "8d941c5d0c6e2b8e2934c9f80f8a63e2fb5868ef": { - "balance": "116443644149000000000" - }, - "8da0dc43ed3ccefb18f21aa13f3fa42c13e540a6": { - "balance": "516000000000000000000" - }, - "8dab4500316475e8fc3bb6494be09f549dedf026": { - "balance": "2736245677000000000" - }, - "8db39a95f4e63bde0bd8c02e386122ce2c57a30f": { - "balance": "12577347153000000000" - }, - "8dc718b49fb68584d9472490743f9be1b0ad683b": { - "balance": "50000000000000000000000" - }, - "8dd05e26224aa8a6deb0904b6d3bbb34d268e901": { - "balance": "613146658282863000000000" - }, - "8dda0e7ddde515480ef08cf90a1eb4e78f50a2c4": { - "balance": "19265526663314000000000" - }, - "8dedad1511c11798c338334dde7be967de96e9b2": { - "balance": "50000000000000000000000" - }, - "8df63c04f18a854d7bb397bca3e2ba19202e9da1": { - "balance": "1479940547081000000000" - }, - "8dfd7edb7d28e8b3df1faab70a8ef9e3b923d998": { - "balance": "10000000000000000000000" - }, - "8e2c3af057e931b5f82e83873b336a7f68e7eb03": { - "balance": "27138009123000000000" - }, - "8e2f4eaddd60468bdc09d47f65839b96f50596ef": { - "balance": "970529157231000000000" - }, - "8e750010c88ba99d75b0b5943c716d6fc0d01802": { - "balance": "42271114987000000000" - }, - "8e889d47f3307a18490e53f2108dc31b14d6300e": { - "balance": "115722965933000000000" - }, - "8e9e1953c82217ba56365e7a9c54b1ded73914bd": { - "balance": "6248835752208000000000" - }, - "8ec980d3066cb6afa793577cf88ccb46ce8d13f2": { - "balance": "100000000000000000000000" - }, - "8ef324c861de7e042c445776bcc8ac026533bc15": { - "balance": "1869634994148000000000" - }, - "8efd14464465e50af087a80a5fbe652445de373d": { - "balance": "1157403424927000000000" - }, - "8f1b57304406fd8b2eb5dabcbd322e326dd873f5": { - "balance": "194188733254000000000" - }, - "8f36ffd921e12083e374335d3cc43fcfeeadfa46": { - "balance": "100000000000000000000000" - }, - "8f813b88e6e125eab71a63455f326322ef505501": { - "balance": "19087691927734000000000" - }, - "8f83892d4d2892cd57828fde2318610a54b14498": { - "balance": "22833507983000000000" - }, - "8f89c1bcba85757cf1718d5b9eb007e27e5195ab": { - "balance": "2241600478705000000000" - }, - "8f927ab63df4c2ce46f1ea35bc875a0c006d2d4f": { - "balance": "327487123409000000000" - }, - "8fc3c231df0f93a84bbe348aff12ab576284d70f": { - "balance": "25000000000000000000" - }, - "8ffa089b07ed1388a5d1a428daf54d9591e734e6": { - "balance": "1347580402248000000000" - }, - "90040e00f585f8be44c82597037fde452472e741": { - "balance": "2746884591879000000000" - }, - "9034eb46aad2a76bdb812c981565d4701dc10718": { - "balance": "10000000000000000000" - }, - "904ca1ac2381702bd18472b175262a8928cde5f1": { - "balance": "304421909590000000000" - }, - "90502c1123692c3b86e99b328d07fae473d4a283": { - "balance": "227491252462000000000" - }, - "9052ca7e9623c1bbe3568668673d6d252b56a764": { - "balance": "35268091378000000000" - }, - "9093d12d8410193293e1fda0cca98a43b85b91a8": { - "balance": "6829489147119000000000" - }, - "909ba8cdc707c12ba577dcd8ed1df1c02a7ce2ef": { - "balance": "60524108169000000000" - }, - "90a2cc3aa73495531691e027a8c02783cea7941d": { - "balance": "65263780625000000000" - }, - "90d7c82615f151953a8d71a68096cee4d428619c": { - "balance": "298774379499000000000" - }, - "90e02deb31d98b9c85fcaa7876eb5ec51d721dd4": { - "balance": "2000000000000000000" - }, - "90e538746bbfc6181514338a608181a3c4286d1d": { - "balance": "6069511690189000000000" - }, - "9106dddc1b693e7dcb85f1dc13563d6c7c9d8a6e": { - "balance": "1977000091291000000000" - }, - "910d1e0d3f71054835ee0d4cd87054dd7add3e38": { - "balance": "40104690362000000000" - }, - "912e2349b791fe702692a6c1ccbf6f0f06b826db": { - "balance": "6305336897000000000" - }, - "9144cc61c01eb819e654b46730620c230da9e936": { - "balance": "144000000000000000000" - }, - "91478d4c15d9ba02816456030915be08fa3aa208": { - "balance": "200078339107000000000" - }, - "9160c466b5f9020b0ab1c0ff497bf0345598ec90": { - "balance": "17705350930000000000" - }, - "919025625787101c572d8340ead1444a96593424": { - "balance": "2418027749789000000000" - }, - "91926323868c65f91b6d74c85c07279610651ede": { - "balance": "538073886450000000000" - }, - "91950cd6e2dd99e024854b65c09c5a7476777a21": { - "balance": "11629505934425000000000" - }, - "91ae8d74c26d3dcc291db208fc0783347fcc197f": { - "balance": "7604593786920000000000" - }, - "91b9ac26869abc9eb3090f1d8140eabe97f41001": { - "balance": "25000000000000000000" - }, - "91c349651afb604f9b00a08e097e02c0964e148a": { - "balance": "117290771022000000000" - }, - "91ddc95cadeb6dcf6ebbdb3300a29699ac8ded39": { - "balance": "20000000000000000000000" - }, - "91ebbd36714cc069f8ce46f3e0eda5504fdd3aa2": { - "balance": "203944728497000000000" - }, - "91f2765125b84923bd506a719d72b0c1de030e32": { - "balance": "452269960816000000000" - }, - "91f2e54a9d61ef52a33d150da50d5a8f2ebcd6bf": { - "balance": "242321058694000000000" - }, - "920dc90d11e087a0d8912c1d43db102e9ba4f43e": { - "balance": "20000000000000000000000" - }, - "922ff522cf7f3ce0bab9312132df51704caa755b": { - "balance": "1414824682473000000000" - }, - "9251449b0f757ef62f63c2774eb63ba15bf3712b": { - "balance": "102688517037000000000" - }, - "926255c17386720fdc1701747a2f024475063d4a": { - "balance": "25000000000000000000" - }, - "92808a38ffc5a339b1ab6b0b472f9975718d4a07": { - "balance": "500000000000000000000000" - }, - "9286c4497e820845341e3b9127813c1b7c884830": { - "balance": "101241387488275000000000" - }, - "9298e1df6730e91e9892d19f7ce18a3db9b5d2a1": { - "balance": "169000000000000000000" - }, - "92d98aed335c29402a43ba96c610251bed97308b": { - "balance": "3032350763000000000" - }, - "9319153f24814a81d920c60cbee9b5f2f275fac0": { - "balance": "56619610984000000000" - }, - "9347532d6396bc0b86bcd34eb80facd4c3690684": { - "balance": "258912194626000000000" - }, - "93487691d71e6248d88f06b1fbaee58b6fe34615": { - "balance": "1593901704394000000000" - }, - "9375154a7f19783b26ae1c9e48f114e1cfd1307a": { - "balance": "9000000000000000000" - }, - "9377947e0db688bb09c9ca3838ca2197fb262a1e": { - "balance": "323993393587000000000" - }, - "939ca9030b28d356dc1b071169f98b0728a9aef3": { - "balance": "218900305967000000000" - }, - "93b71636b8332515c2af031aac7a8805de716a62": { - "balance": "1640174743698000000000" - }, - "93bca153afd427b0c3c1de4a5584610e4a6595b7": { - "balance": "654782426410000000000" - }, - "93cb3b73fee80cedacf5197f8b4ac8f18f0d0184": { - "balance": "100000000000000000000" - }, - "940fcd215bab373d1b736e354f2def501244885a": { - "balance": "13133641534585000000000" - }, - "943f4bc76f20580b6546b6aff2800448f82cfdc0": { - "balance": "1927982550280000000000" - }, - "946ddb5c46fb13010b9c7ec56e4055b4f3e24b4a": { - "balance": "1410000000000000000" - }, - "947961dc367226f78d722361d5821cced52db01b": { - "balance": "115598797369000000000" - }, - "948eab3ffe44d5f1f381de2c8cadcb311c25df2a": { - "balance": "870664355820000000000" - }, - "94bf674593378243fb6b811f331f77561efb4106": { - "balance": "226539311455000000000" - }, - "94ce082887dd6324d7dcfa6cae17b653be021b25": { - "balance": "420000000000000000000" - }, - "94e2aaa4b5e2b36a12f866c96e3382a1150a97b4": { - "balance": "7344059136611000000000" - }, - "94ea5b1cdceb3f1a9d5ecacb6ac8dd2db9a461d7": { - "balance": "1951787237292000000000" - }, - "95218633176c0fe2f32fb55ad3df9f387e63aed1": { - "balance": "99999999580000000000000" - }, - "9543cb22853a46cce3aadc60e46cbddbd3fcf593": { - "balance": "2806074281914000000000" - }, - "958842c5389656d156aab05ac1731a20656716ff": { - "balance": "391064461038000000000" - }, - "958fd9bbc96531a00adc5c484d06dc61ccd717b6": { - "balance": "8021794447667000000000" - }, - "9593ce72919cb0648ddacc58af233d942963e2e6": { - "balance": "32322940730755000000000" - }, - "95a8e371af9128c97c9d4d7c4d58f5f75f2d07d4": { - "balance": "49000000000000000000" - }, - "95b9a9ad563a4c1ff7b6ebcf5fabcf5dbdb4a6a3": { - "balance": "10000000000000000000000" - }, - "95ef5fac6aa3ab1b4a87246fa800cfceff43dec7": { - "balance": "119666779022000000000" - }, - "961a3aa8015cd520de43bd47d81f5194ee4dfdc2": { - "balance": "248589901007000000000" - }, - "962bad39df25d64ee1c6b4ae9c14a18d316bfc06": { - "balance": "2404608291000000000" - }, - "96392119198c4b644c64284c9a75f61210a6292d": { - "balance": "1000000000000000000" - }, - "963c82319380587eeba0bd7b07eb63ea7042984b": { - "balance": "1480123630618000000000" - }, - "963e05fb6245ec11d67ed80e9feba6e2c0a8b4ae": { - "balance": "276053287417000000000" - }, - "964452b86b0d1d4b34aa881509a99e7b631d4a85": { - "balance": "64000000000000000000" - }, - "9644a2af2ff70eb43584a4351bfbe027c42ba3f9": { - "balance": "500000000000000000000000" - }, - "96572a017489450f2dfc0e31928576acd3bc6808": { - "balance": "1140183097730000000000" - }, - "9686bfcc0dc3de20604eb77787d0dba818cc5016": { - "balance": "10593448987804000000000" - }, - "96879780764b4433589d26573fc221f5218f1877": { - "balance": "154136576560000000000" - }, - "96ac1e62c95e33dbbd4f6ed389007e16c00b205e": { - "balance": "4130528000000000" - }, - "96ba703df3a8a6dc3c5d6be02cbf6a4afa2d1650": { - "balance": "2885298549532000000000" - }, - "96d516ded110f1d7e0290716689fd1b7964d9d42": { - "balance": "40665675241000000000" - }, - "96d75950c9354cec6084ba11058dd52d00fdb1f2": { - "balance": "903158106646000000000" - }, - "96f362c59c72fa1d39ae3ec37a7b715d2dd23679": { - "balance": "110000000000000000" - }, - "97115f7544cb05009b3fad2f0c2817f3ee77dd4d": { - "balance": "10000000000000000000000" - }, - "971cbaeafd4b0fdbad24fab946051b8949efaebf": { - "balance": "8462381628000000000" - }, - "971e195e980b4fd4db8d279c80968ca1bd390edd": { - "balance": "10000000000000000000" - }, - "9722648970c455929d621546fddbff27c49acd3c": { - "balance": "70337427969000000000" - }, - "9772027a4ea991eb9eb5ae6b8f34d750a917538b": { - "balance": "148918416138000000000" - }, - "97797e3919aa35567b9eb1224be87f96c6c2e1b4": { - "balance": "973342196399000000000" - }, - "9780a9c86160e27f627179535c3d3f23b6b29917": { - "balance": "10000000000000000000000" - }, - "97a85f4e3f53aa066825de15f1d0e25d4189b037": { - "balance": "2435764858719000000000" - }, - "97f46465e99910539bd3593c16a572e159bac87d": { - "balance": "25000000000000000000" - }, - "9882505fcb54ca2d2f4f79b03f0a5ead61936979": { - "balance": "249999580000000000000" - }, - "9898e969629502a891b758efecc9fdc5ada7d32c": { - "balance": "20000000000000000000000" - }, - "98a52d325e28ca9b4474846c7e4c07a223440fab": { - "balance": "418260286015000000000" - }, - "98a9b2f7d1ba7838e3242b5e4cbf1f2897aa4bc5": { - "balance": "500000000000000000000000" - }, - "98b8308c37a2f6cc1bb382dba2ba95a3c5ca2834": { - "balance": "10000000000000000000000" - }, - "98bf0170a61f98ab0710a68810bf152b7f6c56fd": { - "balance": "2279761566089000000000" - }, - "98c8a323a0022bd147a466fa1ac867977e12eb92": { - "balance": "10000000000000000000000" - }, - "98cd102caf0866ba0a74604b01f54049503905d6": { - "balance": "34739921273310000000000" - }, - "98d7e89c2765aaac224d4015aa277fef208953c3": { - "balance": "1291811952000000000" - }, - "98fe96bfd1e10fb60b343e512b15e955aefc0778": { - "balance": "464922897623000000000" - }, - "99064a57d693e45559a1a910c9ef7d46cce0e703": { - "balance": "8969733492948000000000" - }, - "991ea5429b91a8bfc4352a1d93304dc463be5b90": { - "balance": "149367286734000000000" - }, - "9921d405fada890fee6bf76acc39141fd34e5d2b": { - "balance": "5021308706457000000000" - }, - "9938d357d3d5dcc6f6fc7fb47a98405c0ab6830e": { - "balance": "516293591974000000000" - }, - "994f4e6521a3a5752359308b9f6b2722922c60b1": { - "balance": "23993133615000000000" - }, - "995a6a1c38f037b3a9f0a2e915b8fc0efdea082a": { - "balance": "1403498530728000000000" - }, - "99709e57748a7da6556b1670ba4f15c45aef4689": { - "balance": "36000000000000000000" - }, - "99789f65655c6f917d575169f4ba8192440e659a": { - "balance": "393071814319000000000" - }, - "998f66cbde2693603fa109ad7aaa8bc42a8765a9": { - "balance": "49000000000000000000" - }, - "99afd42a58af31daa54ad9ba35b06954330107ba": { - "balance": "25000000000000000000" - }, - "99b6a9ff2b2ac9ac0361af007aba107695ff5fad": { - "balance": "12860157225353000000000" - }, - "99d16a5955d43723ed8e2b1a642f8f1195f38b64": { - "balance": "62907829047000000000" - }, - "99df609926ca536ed3be80e35dbaecc42ae67f2f": { - "balance": "316809833612000000000" - }, - "99f3faf97a36fabea7306979b30b08fa70110e29": { - "balance": "173292373556000000000" - }, - "9a26110067b473e3bdc0fc32951b39596c967a56": { - "balance": "78192198764000000000" - }, - "9a3a8eff6fb82377da6c17ba658dca87ca0dfe26": { - "balance": "50000000000000000000000" - }, - "9a3b06257088ef8c17410a8f2d63392edb9b55ce": { - "balance": "239567000000000" - }, - "9a426842301802866cca0ef89794d928d3e8f843": { - "balance": "776173297821000000000" - }, - "9a5f2c0a6d41131d9aacdb4f8c274958cbdd377e": { - "balance": "441954000000000000000" - }, - "9a6893023ac6f34b493d33e4dc63ef697169a58d": { - "balance": "439689418527000000000" - }, - "9a86eefd848acafcbd9960003e90b22162b15ef9": { - "balance": "294190908093575000000000" - }, - "9aa711f3e4eb67d2f6405b5ee6290a014d203a72": { - "balance": "9101556549634000000000" - }, - "9abf9ccf6abb8d55ede458d2d12a279d0a823944": { - "balance": "17609693072000000000" - }, - "9ac1909b983c754f0800559174025c0f0baa9d31": { - "balance": "80921948093000000000" - }, - "9ad62cd855d629e1ddab632874a6dc2b812f2348": { - "balance": "2068118534000000000" - }, - "9afc2c33aa2c9a42600abb18aedaefa433326122": { - "balance": "2485353229354000000000" - }, - "9b18d230b221a99c74877d4a1dbdee2214c7d60c": { - "balance": "4024172228743000000000" - }, - "9b18e27788c9d59053072032a480569e142595a0": { - "balance": "110789164888000000000" - }, - "9b4535b23af0b8e5f488a6f318ff6badf71d16c1": { - "balance": "84756740661000000000" - }, - "9b5e7cf43aece7b38ea2af6d08bebe2d3b926840": { - "balance": "262771268227000000000" - }, - "9b77dac92fedd0ad3eb4326d4fafe0f4315a8844": { - "balance": "3616321626000000000" - }, - "9b8f6f223641f9b1bab319dd1e88c49fd411a765": { - "balance": "2054417462086000000000" - }, - "9b9f94861d80365464912e5c7213403405a6cd8d": { - "balance": "2367093088000000000" - }, - "9ba24397002929e6239848596b67b18a8dea1eef": { - "balance": "5000000000000000000" - }, - "9ba99736c5ac468d6b644e39b8d515c39151f51d": { - "balance": "311900650761999999999" - }, - "9bf2d4ff366e1bb2313ae9a93ccca75d6bc0d232": { - "balance": "764870206925000000000" - }, - "9bfce7dbfc9ae62d450e862261d1e21e68bac92c": { - "balance": "1000000000000000000000" - }, - "9c003e74b62f192a864045d678639580c672fc22": { - "balance": "50000000000000000000000" - }, - "9c128bd2c0c96b896db6c0f398e908c98302809e": { - "balance": "3251059363800000000000" - }, - "9c255daa89ee16f32fc0ab1ed8e22db39342e6ca": { - "balance": "37695843594589000000000" - }, - "9c32e714bcb601a56a8a4e6b3f7bcd9e1c7a1b54": { - "balance": "50000000000000000000" - }, - "9c503e087b04a540ed87056c9371d591afa72df2": { - "balance": "64229084991000000000" - }, - "9c54297dd3527cbbb8ca8c305291b89bfb7ab39d": { - "balance": "61682466962052000000000" - }, - "9c55bb1db3b2bb06e605a66ced9ea2ac95718205": { - "balance": "16512365324000000000" - }, - "9c59dbc48b9cf53fe668784e89d30493da9995b3": { - "balance": "50000000000000000000000" - }, - "9c61b58aa760265f7fd1b9e749df70122ea81175": { - "balance": "50590272373000000000" - }, - "9c6c7eaf4bec0566a7bf8acd30e10311a963267c": { - "balance": "999999999580000000000000" - }, - "9c91dd4006f9d01d8caf5f5fb4f2c4f35ee63ffc": { - "balance": "175730980227000000000" - }, - "9c99275f5dee14b426302b1a47a8488c16432f2b": { - "balance": "2000000000000000000" - }, - "9ccf7b23528d062da63f6af3e26531b775c83c52": { - "balance": "928373869120000000000" - }, - "9cd21c30ccbc1087c9b351395fdea17ad669cc2e": { - "balance": "529762292313000000000" - }, - "9cfee47d6f24880af7b281cc00e1fc58e0a4a718": { - "balance": "198888257958000000000" - }, - "9d08251f7d4cfd66d15c17e1ea6bae5c795e290b": { - "balance": "813841349140000000000" - }, - "9d5411490ce89359bfbacf9f9957ebfbbc18debb": { - "balance": "22263187467000000000" - }, - "9d61e1dfaa7d0e0c5f5d733a24a1883c4e201f3d": { - "balance": "144000000000000000000" - }, - "9d754d94a15ab6d738e511fe4c775ee6d20a53ee": { - "balance": "20000000000000000000000" - }, - "9daccedf104fdcc3c39f2961ddfa1c64eb632476": { - "balance": "1237093270947000000000" - }, - "9dad4968c0e44aa729fc5732f3ee903c6799637b": { - "balance": "838788687517000000000" - }, - "9db73ca677bacbb622f44fe90b53ee1d9f0c2009": { - "balance": "472858335000000000" - }, - "9dbcb5026e0f444a33197da240856f108db14ff0": { - "balance": "10000000000000000000000" - }, - "9dc46cf729187ceed8001c4ab14fa4fc21c35f32": { - "balance": "3320792646995000000000" - }, - "9dd895c1bdac2ed9864134aaa8c543473ee5f19b": { - "balance": "1430620966869000000000" - }, - "9de2687242cbf9fb94fee0ad873acc7494ebd2bf": { - "balance": "20000000000000000000000" - }, - "9deec036282717aac93ad5cc1b6d4a5354e85c2e": { - "balance": "2048627955362000000000" - }, - "9df8dc66395aeae9b4c831b4d63bdf48db08811a": { - "balance": "215874670561486000000000" - }, - "9e1fe68a70abd8ab517878b03961da8564b43eb5": { - "balance": "67908329894526000000000" - }, - "9e33293006982abc668e199aab20260b9b754463": { - "balance": "49000000000000000000" - }, - "9e65616282a0baf89469a58915fd8fdbed210e3f": { - "balance": "829209872657000000000" - }, - "9e7b7b522834dd7e83ff2bb6b6e4cd2972330899": { - "balance": "500000000000000000000000" - }, - "9ed134b3a8feccb4056b2e511cea9a8ec58a3e77": { - "balance": "18787546978390000000000" - }, - "9edcf477687a9dee79341ed5d89d576c9a854c2d": { - "balance": "500449025554000000000" - }, - "9eeb06d4b532118afa013a01c9e89216fe0475ae": { - "balance": "1823939486758000000000" - }, - "9ef20a338e85044922f08f3648355e834874d551": { - "balance": "50000000000000000000000" - }, - "9f0855f9cc429fd3590c6ad05bb66a9e038efdca": { - "balance": "8017999878252000000000" - }, - "9f3befcc1884d16b65ae429228d26fffc146c8dc": { - "balance": "1016482445089000000000" - }, - "9f4571748463eee19e59ff9bd734a62a66613850": { - "balance": "20000000000000000000000" - }, - "9f51de282745f77b8e531e1de0b7c14e3369ba54": { - "balance": "1010657089383000000000" - }, - "9f6527175a2b581cc79f2a68c35202e0a7f2af20": { - "balance": "216495522463000000000" - }, - "9f70204d1194f539c042a8b0f9a88b0a03bbcd8b": { - "balance": "10000000000000000000000" - }, - "9f70e44704049633110ecd444f9540e241b50783": { - "balance": "9139000000000000" - }, - "9f73fea741e8506ba7acb477745dab1cfab8366e": { - "balance": "4461472359634000000000" - }, - "9f88d33d26c90e74c39c9676b8b580d21bbad124": { - "balance": "54437240781000000000" - }, - "9fa47455be14ad2eecce495281ed0eea926ec6a6": { - "balance": "10000000000000000000000" - }, - "9fbb15b595d154754a2ae77c77283db9d4e9f27b": { - "balance": "6195722646556000000000" - }, - "9fc480ab1823a59fd6130c3948980f95ac99f1d2": { - "balance": "24101151540000000000" - }, - "9fe5f054165fbf1943b1b02c01063f04e0c3890b": { - "balance": "1000000000000000000" - }, - "9fe7d3d5976e7b8b5ad6baa15ceae96c43c60fea": { - "balance": "55000000000000000000000000" - }, - "9ff116ea0e219814970cf0030932f5ce2cd9a56f": { - "balance": "36000000000000000000" - }, - "a01f6c36193839bc3a31e6d0792324771040fc05": { - "balance": "48298750000000000000" - }, - "a0264706d668522b737bbdbe949ce3e5a60fe314": { - "balance": "1423066922869000000000" - }, - "a02b13bb3b13027045ffb9b44bc7380a942e8ebb": { - "balance": "86845430807181000000000" - }, - "a03d246a931c3d422e5d2bf90f64975923a93643": { - "balance": "5834171660287000000000" - }, - "a046caaee59425ea1040867c62a6fcda11652a23": { - "balance": "83087966538000000000" - }, - "a04b57b2dd8b2082c53517d956f5909d25e14b69": { - "balance": "4518538234851000000000" - }, - "a074ef9e0ffe15619103e3de490f5813be53dcbb": { - "balance": "4568113810000000000" - }, - "a07bae42b44c085067de16e7d9846db529059acf": { - "balance": "4000000000000000000" - }, - "a08530e5fb7e569102b2c226aa5e53dc74483e4e": { - "balance": "2325665286793000000000" - }, - "a095a2c666f4f3203a2714fb04867c13c2add4be": { - "balance": "14768043990000000000" - }, - "a0a967418a3fcb3ee3827a08efa851347c528a60": { - "balance": "20000000000000000000000" - }, - "a0bb293071e07418ecb2fefc073136569ebd1736": { - "balance": "25871128320000000000" - }, - "a0c6c220a53b7dc790f7a5b462a106245c761f70": { - "balance": "1000000000000000000000000" - }, - "a0f06c86c49b248f4835bff405b620d12ec80d07": { - "balance": "484572382390000000000" - }, - "a10bc9f4d05678b26c4ffd2d92ab358163020b61": { - "balance": "10000000000000000000000" - }, - "a10c1197f7bc96639d01a652df73e49c669165dc": { - "balance": "1205859101575000000000" - }, - "a1221b2001f85f71e0655551e300ce115284b8dd": { - "balance": "1376698025177000000000" - }, - "a13fce836d65124fe5bcfa2d817ab2a043acbcf8": { - "balance": "55000000000000000000000000" - }, - "a15f1f609f7464906e0eb9d5e1d26468b90d9198": { - "balance": "16000000000000000000" - }, - "a1617dcf3acda60737e5ca9e4d0ecd82a98ef667": { - "balance": "500000000000000000000000" - }, - "a165c5f151d0daab905ba4a6d1fe5d5114fd7686": { - "balance": "41039049526000000000" - }, - "a17d5bed36c1059561e184a8a90a38ce955b92e4": { - "balance": "10000000000000000000000" - }, - "a18efb4e0950e7ac95970cd4591dacc286241246": { - "balance": "12403188476000000000" - }, - "a191fa6be64f2f6d2b4a7fb5a586416a605552c6": { - "balance": "60340281461000000000" - }, - "a194c15518cefbe94edbef3a2421586b51f7e1f6": { - "balance": "4153525550636000000000" - }, - "a1d0e41aacf83fc62fbecf35f8e873f8d734ecaf": { - "balance": "9000000000000000000" - }, - "a1ddd1f615ed483ef895e341f3266b6891f9b59c": { - "balance": "180411786335000000000" - }, - "a1f4d1e03114707a56ef9069bc20c6094e810d34": { - "balance": "51949145435222000000000" - }, - "a1fe101a65616cd03e3af03092be63434b7bf203": { - "balance": "1005401878265000000000" - }, - "a25a8225ce67c54048737601eac5e0d063c2fa17": { - "balance": "272038848571000000000" - }, - "a2714999233bcaff7294fa3e3b64c63ad45a928b": { - "balance": "14560781294000000000" - }, - "a28db3f7fb1771a3d77dfb19b54f88fd55b15c8c": { - "balance": "8000940572576000000000" - }, - "a290101bfe5fbc73146c4ec3ab5266c043eb701c": { - "balance": "1397563244603000000000" - }, - "a2924cfbcd37d0b321d6abbe57c645f9ce32340e": { - "balance": "200000000000000000" - }, - "a2a26c34f3d950c795fc965f6b1df3990e111403": { - "balance": "34525064429023000000000" - }, - "a2a2855851711bfc051c1f298821ae89e4c872c5": { - "balance": "491025000000000" - }, - "a2b956dd6f1934a4a44a026a18ac345ddabe42d5": { - "balance": "20096625821563000000000" - }, - "a2b9a118a79be81711d95485aa12e3efe78ca256": { - "balance": "10451051632647000000000" - }, - "a2bcf08ddd1778b30ea7882518148edfba2d9b20": { - "balance": "347033754668000000000" - }, - "a2bd489ec4790f4145f8a9a95c9c829c5c020146": { - "balance": "100311110878000000000" - }, - "a2ee35300ddf6a2491ec0e1848f8b56defafd7fe": { - "balance": "500000000000000000000000" - }, - "a31adf082ffd212df18d5a84b105a937e83b1b1a": { - "balance": "7124891785000000000" - }, - "a32c944e6c5fe186794b88d6bcbf51c47bea55ab": { - "balance": "732129357042000000000" - }, - "a33105d543f5d2b1220d4e1ecfdcf85699324dad": { - "balance": "74798779358000000000" - }, - "a3330c73e2d79355a14e570da1ec2e80f8048c69": { - "balance": "10000000000000000000000" - }, - "a3580034590e3052b9de5abd635e514ec5ba8694": { - "balance": "10000000000000000000000" - }, - "a360d8e2519dc6d7793cc371d91ad6add75e3314": { - "balance": "192622260840000000000" - }, - "a36b9b8b2adb20fb4a84d3025bf2e35baa8b7fef": { - "balance": "20000000000000000000000" - }, - "a3771b191237bef48339aa77ad5357f6227b358c": { - "balance": "512633055119000000000" - }, - "a3892bfd25705387cfb4eeb6d21089753c22e3e2": { - "balance": "258136912825000000000" - }, - "a38c793775ebfc7330b4331fe2dc848abb862b73": { - "balance": "1193250172232000000000" - }, - "a39417002ab94845541aded4a614a5a04af8187b": { - "balance": "1185722898000000000" - }, - "a3a79a9f929b54075de43689adb665ef914812ca": { - "balance": "100000000000000000000" - }, - "a3b59ea3d366f818ca09980846ac533d4685c121": { - "balance": "59734700360000000000" - }, - "a3c7b7c594a64225922e02039669e4d0b43fc458": { - "balance": "11779233750000000000" - }, - "a3cc39a68184e51f6445d3ba681a55f4157d4383": { - "balance": "10000000000000000000" - }, - "a3d414d9f210f7b77f90790ce09f6128abe50adc": { - "balance": "10000000000000000000000" - }, - "a3dfda16e5ae534ac100f56741b77b6f86786615": { - "balance": "9000000000000000000" - }, - "a3f79b9d1fc9d6dbaaef49d48fa9c9fb5a822536": { - "balance": "108910000000000000000" - }, - "a3f87414bc9e6f01c2fbde966fc8fb6edbf58c29": { - "balance": "441000000000000000000" - }, - "a3fa3f58c802d9a9690de760716275f14449045a": { - "balance": "437227558095000000000" - }, - "a417ec5a9749064a6521ca2bf9d05f208eeaed54": { - "balance": "959205202638000000000" - }, - "a484d5b883d2b99b81b7bef27e307957ecb64b15": { - "balance": "126491152120000000000" - }, - "a488cd48258e57d66f44e73a60c121f963cb29f5": { - "balance": "20000000000000000000000" - }, - "a488e3b5096e964b21cdeba12ab423f391765b6d": { - "balance": "1712050478592000000000" - }, - "a49dba65f28909e9bd2ce5675bd091f498c6c5db": { - "balance": "216802821062000000000" - }, - "a49eb6a791022c1324facc23d8813f9954d1c639": { - "balance": "287438914902000000000" - }, - "a4cc080a5c4649f511b5844a8e0b031927e13a87": { - "balance": "20333578449000000000" - }, - "a4d2624ac5e027f72edaa625ef22134217203b5d": { - "balance": "1000000000000000000" - }, - "a4d30e35c9617eafeda82866c96c3ce6bf14400e": { - "balance": "1223254927978000000000" - }, - "a4deae7355bd2e1d57eefa56600601b8b475a501": { - "balance": "36000000000000000000" - }, - "a4ff3b5abfe4e50adad16d01aaf62c3d4cdb5260": { - "balance": "20000000000000000000000" - }, - "a502b109869ef07451576bf0e13ab294e1f236b9": { - "balance": "94843398055000000000" - }, - "a517a3b5e4324197902e16f8a29e47335cf39c11": { - "balance": "100000000000000000000" - }, - "a51e101088da23c82907e3e2c65a058f0454b131": { - "balance": "196000000000000000000" - }, - "a52bcff6a7e2e70cd714058bc30a16138fe39899": { - "balance": "30429750204000000000" - }, - "a544e84c2bc4b17859d06f136b6e377e4e398b22": { - "balance": "143977568178000000000" - }, - "a54ddacbc17a98b9fb6292aab3d92f4c5753fd0a": { - "balance": "100583192014000000000" - }, - "a557754f6637a19c1a48cb9bf58c1fe897acf434": { - "balance": "2087038692036000000000" - }, - "a56649205d9ea247b49e03dacbed6c78c21beb4a": { - "balance": "5046177099585000000000" - }, - "a568136446ee6b3bf62a20238db3b11397a065f2": { - "balance": "11652249158033000000000" - }, - "a56a7865b526e315a9eb41f4847485c7e0c952fd": { - "balance": "50000000000000000000000" - }, - "a56bab2a9aac9d08a7bc9265864a80089b68570d": { - "balance": "37138466291329000000000" - }, - "a5965a601c5df7765cd70e5dad27dd23da67ac99": { - "balance": "10000000000000000" - }, - "a5a3161c44c34c441784b7df795067760b0ee569": { - "balance": "35053289069000000000" - }, - "a5c245cf843e691956007b94e259b437a4e6b7e3": { - "balance": "18749166170000000000" - }, - "a5d7de961c3b991dc78f2d6c0448fa6225116d3f": { - "balance": "1574510758868000000000" - }, - "a5f47d2081ef728808786128549a28a5662e92a8": { - "balance": "1750000000000000000" - }, - "a610c90f5b7e5f33044956ba431a3887de1c969f": { - "balance": "25000000000000000000" - }, - "a61c1919bc3f3181dc94e2230d35574cfc972d78": { - "balance": "8990565120000000000" - }, - "a62f1aabd91cbc0112e796d1ec3727fcd26fa293": { - "balance": "1311277302001000000000" - }, - "a64fff0bb32e32f81a541c393982bc59fa183b1e": { - "balance": "8291357610655000000000" - }, - "a673dae555d367b8d4a784274577a1884615b9d9": { - "balance": "27416452091330000000000" - }, - "a6c780b585355d84d9d3c13be5bd05374588e240": { - "balance": "913657165911000000000" - }, - "a6cc1f6f51862c2798adaa1d266988022005a71a": { - "balance": "284500645805000000000" - }, - "a6d9c82784fa20dcf28266d047db441cfeb8855b": { - "balance": "10000000000000000000000" - }, - "a6dae08f99e4fb57b066a645a259d8e4f7ac2bc8": { - "balance": "9044922773690000000000" - }, - "a6f49f36f8d10a796bc2afc9e069cb0c76004ddd": { - "balance": "128555691078000000000" - }, - "a721ce1c294a0f1957ebf9be20b0fffcf90111ad": { - "balance": "3392103457630000000000" - }, - "a72b82c33bd3d6060e8a04392d236775d48ec3ae": { - "balance": "1434465940701000000000" - }, - "a7344654f2a1a44b3774e236f130dff8a4721e82": { - "balance": "100000000000000000000000" - }, - "a748cced92a87066db8b29f931fb92e827488a9e": { - "balance": "5487679824758000000000" - }, - "a78dcb2bcbec2d0a60661e1715c9a95c9d573a68": { - "balance": "346798292989000000000" - }, - "a7a6c0505e7090e0b2c21394877f91c50be6b45f": { - "balance": "4125233658872000000000" - }, - "a7dcdd9b9785a44a2dd4c5eeeb863ac1feae0f66": { - "balance": "10000000000000000000000" - }, - "a8013e9dca1bd38975748de2fb6cb3af5cae74d9": { - "balance": "10000000000000000000000" - }, - "a807bf78b15c15cd9e8edcf586849db716fedbb1": { - "balance": "1458293606310000000000" - }, - "a83410ff00fb4b913dd0ea2003b38c5c3247350a": { - "balance": "2876442029807000000000" - }, - "a848f61298a409e77a03900712017572f35a3319": { - "balance": "2783106133600000000000" - }, - "a85bb81d0dc57f824a763814759fd93fe3020569": { - "balance": "4558027813744000000000" - }, - "a860611cd098ce98974313030d9f6f462bb274d4": { - "balance": "961594154368000000000" - }, - "a8799eeff72929ee6cbfb5b0c02985cd4841be3c": { - "balance": "500000000000000000000000" - }, - "a8c29b9b1349fac0be9a65873e1911b7439c9a63": { - "balance": "1264035560749000000000" - }, - "a8c321024a3c015d881efca33bd1b2c1788b379e": { - "balance": "528752788000000000" - }, - "a8d02e8925ed48f4274d8bee62253dc0d4f2989c": { - "balance": "209083880937000000000" - }, - "a8d2bde2ccd6bad67ee1b9550c9310accb37cd79": { - "balance": "49000000000000000000" - }, - "a8d61abc6a403adc183aeb74c83e4221fd28ee1e": { - "balance": "50000000000000000000" - }, - "a8eb6aa5a0c5b6d9260a202dc76ab674d9a5f3b9": { - "balance": "1041257515142000000000" - }, - "a8efc57efc776dcaaf4003a8cfa63f215ab0284d": { - "balance": "166144142685000000000" - }, - "a8faba86d87678294e311cfa7f8cbeb6f9d8a499": { - "balance": "124541781000000000" - }, - "a912e02f8eab0cb620316129875f919455201117": { - "balance": "6454482105955000000000" - }, - "a929ac95281d1a77a3eda3b5ac90a761ef03ff16": { - "balance": "1074305309650000000000" - }, - "a92a4e40519003813f5574397ce328d046f75802": { - "balance": "9188437500000000000" - }, - "a93850ba8fff3bd18ab259f87c58bbce84165fff": { - "balance": "39018890852058000000000" - }, - "a9843660a17c2d972246028cb8045472abdd346d": { - "balance": "1052681604185000000000" - }, - "a9866c6271733971e46df3c9bb27b3d3c513c166": { - "balance": "200000000000000000000" - }, - "a9b1299c0c064e766f9f29f4301a78c6e4931fcd": { - "balance": "267785134400000000000" - }, - "a9bc33b9c99dd5a3967387c1e99766f9bc74d591": { - "balance": "65356157048000000000" - }, - "a9ccf1cd2f816b15182997e3207d9a681bf21b06": { - "balance": "17521053440000000000" - }, - "a9e54bd9826f853f65e0be1ec0bb9c28f95e0eea": { - "balance": "6260000000000000000000" - }, - "a9ef563c872342f49817a903a5725b504d455ea9": { - "balance": "50134015139000000000000" - }, - "aa0d69c7e1382cd16c527a3fee48db19c38e1398": { - "balance": "142562301500000000000" - }, - "aa12abcc3ab373d07bf560fd200652c8580fd967": { - "balance": "5509242259903000000000" - }, - "aa1d6b968b3f8046a94f128864bfc612fc2e2700": { - "balance": "489179780895000000000" - }, - "aa20b8559d6dd1543e8c528775ae4b04c6242471": { - "balance": "169000000000000000000" - }, - "aa227e9d6074a60ecd43e1cc24092ee58560374c": { - "balance": "596190898010000000000" - }, - "aa7b660fec7b05968ba656eae9a8aaef4481720e": { - "balance": "674642002744000000000" - }, - "aa9e04077d44d288978a3a3ab0d7c251c0447a4c": { - "balance": "10000000000000000000000" - }, - "aaaac1e72955e9d67625cf8bed73fa643fb1cc1a": { - "balance": "9781187987000000000" - }, - "aab46c0c2db4e330834081f97678906252746f97": { - "balance": "16440184245000000000" - }, - "aade5358c52b8aa5ad8ff285c6b297e86f49fa0f": { - "balance": "982846000000000" - }, - "aaedb3fa2cf0ebca0ef4a121a28a406264ccc900": { - "balance": "100000000000000000000000" - }, - "aaf30bf76362a03450aefaf5bd68d28b84eb4962": { - "balance": "509106199370000000000" - }, - "aafbaaa6b6369e986ba72b196bd5f08cc458e344": { - "balance": "216372214000000000" - }, - "abb03c888d61c9102827a1dc0950145beb9d96b3": { - "balance": "144000000000000000000" - }, - "abc6dc937d7703a6b0c83659a328cde0d5008e32": { - "balance": "4052429106341000000000" - }, - "abd3910139a97cb92dc09a8a0352575bcc9ebed3": { - "balance": "24028359215749000000000" - }, - "abdc3953ef293c98989802063f8cb55e0e506432": { - "balance": "64000000000000000000" - }, - "abf1a47c582bc87d36e47cfce24e0ad249f42e73": { - "balance": "71947491720909000000000" - }, - "ac0b6e7aadfb5ffafd5cb3ef3620ebb0691cc3fe": { - "balance": "10000000000000000000000" - }, - "ac1a182607046b56e7a4bbab87cc1182874f79ef": { - "balance": "453499500178000000000" - }, - "ac251b311f781ad7a43d01b0b4b20fe891004e7e": { - "balance": "304621378298000000000" - }, - "ac258cec5ef49f96612d659f66dd4e6ea88e3c87": { - "balance": "255185373455000000000" - }, - "ac4000d9ad080740ef4a2ebe4a3075877bea277e": { - "balance": "10000000000000000000000" - }, - "ac7445c09372f15259fd852cc458783d6140c0db": { - "balance": "10000000000000000000000" - }, - "ac8d29dc05ea6c2f5409a76abe04321bf9381f32": { - "balance": "22464474197854000000000" - }, - "accd52b63822d8cb5117d9deb56596e072462614": { - "balance": "20000000000000000000000" - }, - "ace63a86a2ddfc79f677344e93dc0c4750b8fdcf": { - "balance": "1355066360964000000000" - }, - "ace83deb83fa8d319979658592b75ed13bdf97c7": { - "balance": "20000000000000000000000" - }, - "acf91515df16b21f1e5f5474dbefe596e4929b96": { - "balance": "1153047238967000000000" - }, - "ad04381f7ba89220e8fcd7e200f98a476683a904": { - "balance": "2000000000000000000" - }, - "ad22225bf225d8f705f93bdcda8d301180ea28dd": { - "balance": "1272512717188000000000" - }, - "ad3f74034ff5ca89f97b2585edf12376820307ab": { - "balance": "12303261515593000000000" - }, - "ad43a3527ad2b9445417cb73cbcb42965a5f469c": { - "balance": "67607364133000000000" - }, - "ad61cf9bf560bd5da75d55738477bd9aa25fb0b8": { - "balance": "4358939446693000000000" - }, - "ad649e8a3e1436e0604b0b8c9b1a5f1c09e06d7c": { - "balance": "344000000000000000000" - }, - "ad6b584813814db4c72c4c7eb31447d224074b46": { - "balance": "18445595367000000000" - }, - "ad7d404afc67c0e457fd3ce142cd30b506408683": { - "balance": "48218702840000000000" - }, - "adaf4d39b6806d132128ac438c2862c0a1650cff": { - "balance": "500000000000000000000000" - }, - "adda124baed2e1fdc1acc7b4a048eab0cd249212": { - "balance": "1074765673925000000000" - }, - "adef437c429d90a350b99750d4b72bc8538c5f98": { - "balance": "931901903135000000000" - }, - "adf826a0ea7dc4322d26e9d8c54c4180c1827216": { - "balance": "323567723315099000000000" - }, - "ae01d8b1668f8bfe6e225bd9bc746f7e839ac0d8": { - "balance": "321211880744000000000" - }, - "ae17de3ae6127022e53ebcf9e08457174cdee0e9": { - "balance": "3817903000000000" - }, - "ae243b0186793eddc6ebbb1a2c1f0b1cd574b07c": { - "balance": "9000000000000000000" - }, - "ae3ae1d41dfb16e19a1817b3639cd4300fd166c1": { - "balance": "55437674845679000000000" - }, - "ae506999882d4c6f05cc7979c342c0ce559a8df0": { - "balance": "1391755905401000000000" - }, - "ae524cee5aa23025d6ad185ccab75a6974335d53": { - "balance": "797132751509000000000" - }, - "ae5a55075d0541f179b085152bfc8c72c74abe23": { - "balance": "589408139567000000000" - }, - "ae63d02b18b464f0bbab4de943766bdc7ba2926d": { - "balance": "300261019201000000000" - }, - "aed8ffb86a49c09ae3a83e93d9045851434a9f0c": { - "balance": "1031991707237000000000" - }, - "aee18a9a2ccdf6025d61005827753ce4f510f7e8": { - "balance": "1818639022863000000000" - }, - "aee67910c514fa63a228769d5e15ca40bc4b26c2": { - "balance": "5688989238568000000000" - }, - "aef744eb2ec682dca128dc3149afcf881e367121": { - "balance": "818801643225000000000" - }, - "af04430b3e40e746127623532353a0f177a88fe3": { - "balance": "100000000000000000000000" - }, - "af181833edb15c9b2ee2329dcf1845b977361b7d": { - "balance": "93228805338000000000" - }, - "af30db29765b4fda6f075af96e8acd5046b099c4": { - "balance": "1000000000000000000" - }, - "af31fd30cfb10f1b0a12c2e7dd7ca56bdf517745": { - "balance": "36000000000000000000" - }, - "af70d6820e1d26194b0a9965b55254a287b162f3": { - "balance": "87593999609754000000000" - }, - "af96a573fa86c07389a71db797bea689419b23ca": { - "balance": "36000000000000000000" - }, - "afa4c5b674934e31a9aa5e3e723d85060d51c4d0": { - "balance": "10000000000000000000000" - }, - "afa6e4b4060c2e5969c2329d13cc42924412efde": { - "balance": "127502378589556000000000" - }, - "aff2308ac607f85392f4c8a6a043af67b7b849cd": { - "balance": "11130371831000000000" - }, - "b00ea9c459105b650def1e8569c85fa01837454d": { - "balance": "94928352162000000000" - }, - "b02a7d16ea8663c88416e6f64eaf57787d230be3": { - "balance": "17215604601000000000" - }, - "b03f4e9aa5c352cb1cec953d1123c2f22cd94b5b": { - "balance": "206022552274000000000" - }, - "b051459b91d253c5e8251a5a68282c291833466a": { - "balance": "297127749975000000000" - }, - "b055bdc874ca5a7d2f4bcbc51f1cfc3671b55f72": { - "balance": "1421913523478000000000" - }, - "b06156b99b891b756262c5b40db9bbe39fddc77f": { - "balance": "49000000000000000000" - }, - "b076893b9841d2775ec8883f05b74f1e5aec327c": { - "balance": "22591055478000000000" - }, - "b095de644af3c9f960f67502da6ac5eb050a158e": { - "balance": "4958067562725000000000" - }, - "b0a1f794cf70422395f74395abc9a7d0b271846c": { - "balance": "812057322000000000" - }, - "b0d36e0f426a99416425689c657fc6d64ad698ca": { - "balance": "1157727077158000000000" - }, - "b0f35fa554d6ed657bf3996cc027d045c3971fcc": { - "balance": "64000000000000000000" - }, - "b0f76b4c9afdfe35c41d588265642da60f1b97d1": { - "balance": "1000000000000000000000000" - }, - "b0f76b4c9afdfe35c41d588265b42da60f1b97d1": { - "balance": "2028311808491377000000000" - }, - "b1445842d56c56bc532d2f33ab9b93509c732a3b": { - "balance": "13522982470164000000000" - }, - "b156bafe05973bc839c4f115be847bbde8a67cb1": { - "balance": "10000000000000000000000" - }, - "b182e4d318893dc1c4c585195dbde52a84ed4ffd": { - "balance": "329498977335000000000" - }, - "b18f506e77df4db80ca57cefeaca4f1010f78f50": { - "balance": "956339304078000000000" - }, - "b1b6f617b110dd79c8fd77e729584d1fdfa9aa09": { - "balance": "16000000000000000000" - }, - "b1bba36e2d9e272e0131f4bae09bcfd92e0a63db": { - "balance": "64000000000000000000" - }, - "b2285651e57ae0ff27c619207cceacd20884d152": { - "balance": "1345938295122000000000" - }, - "b2419a93732d0d324daf7707fac3782a77b0dff8": { - "balance": "625000000000000000000" - }, - "b27206e9f2ac430841fb8da69b49d505f1558b8b": { - "balance": "29507819229000000000" - }, - "b2801fe902c7bbc987ba12ecae98765c99980fef": { - "balance": "240016083000000000" - }, - "b2843d5215ceb761e78f281402a1660c3abadf5b": { - "balance": "3335539720927000000000" - }, - "b2a22e6a04a2ce3287da3b8b6eed4ea1f18f05dd": { - "balance": "99999978999999999999" - }, - "b2d55a061fc6f90d2a05e0cbd26ffe0a1c3321c2": { - "balance": "1000000000000000000" - }, - "b326aec1cd523948ffec2fd1e8f21bd2b4308f40": { - "balance": "913000000000000000" - }, - "b32abc82b251e2d310ea7588cae4ad4acb657cd9": { - "balance": "26946233911000000000" - }, - "b36924d578973aec05ce7ab556d7ed00004949ca": { - "balance": "393041705867000000000" - }, - "b37482114c83e857c730588d7d959d300b8142da": { - "balance": "29429544454000000000" - }, - "b39998bade135ac6ccadff41cd709e161d01aa60": { - "balance": "26272579375000000000" - }, - "b3a995ee94f1d63d12f10cea5ab3d596c7c6f284": { - "balance": "64000000000000000000" - }, - "b3bf35e936fdbb7d0bbeeb1cf076f243855ed477": { - "balance": "754081187934000000000" - }, - "b3c2ac85b99abed4a2a52b5f96a2c98040d16022": { - "balance": "50000000000000000000000" - }, - "b3d1a2c0ab2d8987446d74f49e357adf5bf15986": { - "balance": "10000000000000000000000" - }, - "b3fbcd24c8394a5d2b7fe877f18681a109a404e5": { - "balance": "2558689648423000000000" - }, - "b4110f4e38405adfc054e55ff73c55842db8e2cd": { - "balance": "129000000000000000000" - }, - "b417f4681fdd4e53cfdf8550e3d326dbb0a557ec": { - "balance": "1000000000000000000" - }, - "b422970fb8799d83642b7ff715fc941d69e86053": { - "balance": "81000000000000000000" - }, - "b4237be71920497715826eae8d85c26cb3c111a8": { - "balance": "10499979000000000000" - }, - "b431839de4b21dfb44150cfc6ed00ea430a81687": { - "balance": "26839560174813000000000" - }, - "b43a0d6399c7d1be943c4b45838156a47c88f909": { - "balance": "10000000000000000000" - }, - "b44ec608b95d0d51105ce5f4b48de5dd72f346fd": { - "balance": "448125120000000000" - }, - "b47f63e14f6de6c3413b2be95a725e367ac18fb6": { - "balance": "500000000000000000000000" - }, - "b48071cd1b15f45028e9dec2237f14f10b7aedf9": { - "balance": "38042711385000000000" - }, - "b4b874b323b560aa0e4811ca574bd48b65b3fc72": { - "balance": "18063913676592000000000" - }, - "b4e4d4af0667f8158cf817bf1bc3eada08a551ca": { - "balance": "2149067370317000000000" - }, - "b4ecd625ffe470ee1fa1d97832e42ddf3f9ddf6a": { - "balance": "1181738860120000000000" - }, - "b53f380ce92787c1db461524290e8fcede552fe7": { - "balance": "12640674931821000000000" - }, - "b547e04ab8a44d3cae38704356f1f59408457b67": { - "balance": "286604155735000000000" - }, - "b562e4010a0a5fd0906a4cd9f47fc28f6f51e210": { - "balance": "1000000000000000000000000" - }, - "b584de7b38a2a2e3d9ff9c055b309ca56e5da5a9": { - "balance": "237896887904000000000" - }, - "b5c1129961c4a43673324aaedb8296f5ade82516": { - "balance": "4213058948283000000000" - }, - "b5da6711c72bf27c87923aed4a39349b4192e6b4": { - "balance": "55180742586465000000000" - }, - "b5eac5e7e03b9d31e40393e16e956cd588cb7566": { - "balance": "4508019435556000000000" - }, - "b5fd46ee4e02946dca3485439f98bdab290c82b7": { - "balance": "108321600045000000000" - }, - "b5ff2a3caef6ec30365f4f0ecbecbdeec1cacbba": { - "balance": "979696597242000000000" - }, - "b609d05242f7c13a4ae4036f6da9c0bae18dd70c": { - "balance": "229121731278000000000" - }, - "b611156a2f87fb45c431a5cf5740ded90c2dc542": { - "balance": "401783365700000000000" - }, - "b61c7623144afbd0f6cf44c951e4219ef8096119": { - "balance": "36000000000000000000" - }, - "b61cbe0e58ff6fa4c810ad03c759c79d9ff052a5": { - "balance": "1034495371371000000000" - }, - "b622bb67e95a03f58dc9aecf82c217e86f2cf7c3": { - "balance": "500000000000000000000000" - }, - "b62a50be3ce0e7cf8f61991daf8fa7e23775141e": { - "balance": "1000000000000000000" - }, - "b63cbff6b1747ad5cda101d5f919ce81dd67e363": { - "balance": "2570089937000000000000" - }, - "b65e80551a8687c9cef2d852949177c0e3b56e51": { - "balance": "100000000000000000000" - }, - "b68126ebbcb5ab9b0371b62597a38d5c1685b0df": { - "balance": "671140851028000000000" - }, - "b69f5830c371cad5a74ae823eb8892d153ef3c23": { - "balance": "18446744063709551616" - }, - "b6b4468c4db64e0b85cddc251d02f32fffcd1f7c": { - "balance": "10308006217291000000000" - }, - "b6c129312505e571148dbe69833d30550efc12c9": { - "balance": "5105834767567000000000" - }, - "b6cee8ef00b8674a9a96447e4511b30d6564ff67": { - "balance": "667754569888000000000" - }, - "b70f805aeba260d44f0730f0a9dec60f2b4f54a1": { - "balance": "2751303297000000000" - }, - "b71a901dc4b6c6463f7d221f868677bcadbcc680": { - "balance": "169000000000000000000" - }, - "b7385bd8f8257331f4c7a87c7a23724f615cff8e": { - "balance": "196000000000000000000" - }, - "b755692bc027e30730dc1d0e0b2a883830a84115": { - "balance": "30713083153428000000000" - }, - "b765305dda3c1e069a7a022ec127ff2140d0a820": { - "balance": "603122990932000000000" - }, - "b77403a4c56ffc7715b4bfdfe4b054336aeca466": { - "balance": "130840969728386000000000" - }, - "b78b2f6dc731d7d84b7eea151805f9208a1d0cf0": { - "balance": "142084687500000000000" - }, - "b792a0fd762c002a7585cfdefd36cf7ffb42fc05": { - "balance": "10000000000000000000000" - }, - "b7ccd7164aa7fb871726d9d043a8f8f890068c0f": { - "balance": "1170997140237000000000" - }, - "b801f49018317caf30f310dbe116f4e876184874": { - "balance": "50000000000000000000000" - }, - "b81ca2bc63cb4008cebdda3ce8f4eaba322efca6": { - "balance": "4678481047354000000000" - }, - "b82e3d50bf8c5b471c525ec8dd37b06688ed6178": { - "balance": "1202448975553000000000" - }, - "b841162a7a8876296f10794d8847d8095426aa54": { - "balance": "73500210754000000000" - }, - "b8421d375c3f954e22b6fd304235dd7c43b68bd0": { - "balance": "6499782706009000000000" - }, - "b859b76d77eb604728093c61fcabe6f9d22433b0": { - "balance": "196000000000000000000" - }, - "b86536268ace9be93a1db2012d6e3e59023ef2cb": { - "balance": "52878034904067000000000" - }, - "b87e1ac4fc423ab37e10ffd221df8056537b1d03": { - "balance": "119159824674000000000" - }, - "b8825a99806c5a968423e69d22f2b61a2f0ae9e4": { - "balance": "999999999580000000000000" - }, - "b8835acaf63e0e5d41fb743eb0f954040a38d381": { - "balance": "64000000000000000000" - }, - "b8844c74b227781d4b3fafd32e39ff6fa9857f77": { - "balance": "490694157000000000" - }, - "b8962e8bcbcf0f69144f8fcd2ec3ae8e54c05034": { - "balance": "1425313342735000000000" - }, - "b898b4ece8e0eea375f6eb85615652cc5c221593": { - "balance": "2284038029169000000000" - }, - "b8a949bfd9751c29c4cd547cca2e584d8dac4e12": { - "balance": "50000000000000000000000" - }, - "b8ad5ce2ae781e2d245919c15bbbc992185e5ada": { - "balance": "733786526623000000000" - }, - "b8cb6a9bc5a52b9cfce26869e627b2af0ff5ed4a": { - "balance": "98364826821577000000000" - }, - "b8cf6aac7b9028649f0d55a57b61640d70cef120": { - "balance": "104799890645000000000" - }, - "b8e827b5d1e10a3944039adb1a3dd7ff6949145c": { - "balance": "172413427060000000000" - }, - "b8f6d7f33ee5755ba56647ab8fc9ca27b8aba677": { - "balance": "1430769696978000000000" - }, - "b9221177e2b09725bc95f08c72c17c42887eea62": { - "balance": "1212779749827000000000" - }, - "b936e0d83cde9bb810b85ad58eb5ff0fa9c11654": { - "balance": "4999580000000000000" - }, - "b961d435c457e205fdbed5442c8614ecfd59616c": { - "balance": "27847452621284000000000" - }, - "b969e9d89f32002cd4f90ef5907bebbbdca6fe6a": { - "balance": "12455448454838000000000" - }, - "b981c9137cfca5389f0123927852278d2d7ff618": { - "balance": "92180707865000000000" - }, - "b98abf0fe91b0d3a16c6ed37aea446baea33fd23": { - "balance": "560454425563614000000000" - }, - "b99ab4e6ae277b9fb04537adbb781e8390b490ad": { - "balance": "32814665223319000000000" - }, - "b99d0a433d7994743dd675894c18ed03164436e1": { - "balance": "16000000000000000000" - }, - "b9d8b6f0a505d217709bb9327f3b9b3f84813e00": { - "balance": "81000000000000000000" - }, - "b9dbd64e3c8e6ad84c9c67c66e678c06ea7bcb91": { - "balance": "1161140466507000000000" - }, - "ba361f7a6dff16a96f957c63e08267dec8f9ecf7": { - "balance": "2170060167590000000000" - }, - "ba47f4136f74b566f62ba373651332b59e74e1db": { - "balance": "906249296535000000000" - }, - "ba5287cf15de91daeaea2465da4d4c1a14dea716": { - "balance": "98978398162000000000" - }, - "ba77d056d52f84e740579aa527792f826591c858": { - "balance": "50000000000000000000000" - }, - "ba895406774ced5fd2e759b58f9ffaed5e04fb14": { - "balance": "10000000000000000000000" - }, - "ba96fab21a4926fd1137558ae996b52ec14538a6": { - "balance": "10000000000000000000000" - }, - "baacc247801eddbf152fd6ec39d659f265935743": { - "balance": "2661902597584000000000" - }, - "bab2eb9fab8e699a958699b15ddc7ada5428d33a": { - "balance": "27006404153000000000" - }, - "babeacd7933c817472875c86bf126e6d11886f8c": { - "balance": "2461234517292000000000" - }, - "baf7021d4d754d4478d3c3624c2376e3f1d4ee5e": { - "balance": "1352066301857000000000" - }, - "bb0760bd1da973d8f70dd0caa6cadfcfd8199231": { - "balance": "177674700430000000000" - }, - "bb278c6a52eebd0b8950e9b78ba211453ccb1b6a": { - "balance": "25000000000000000000" - }, - "bb327e5f260b2dfe25fb180c2d3f4b63211c1dee": { - "balance": "7694972715000000000" - }, - "bb643e768ab20c135e7df3f400284cf04c40a6f7": { - "balance": "385756449779000000000" - }, - "bb73d1d1c289b4953d0033b52d9d2d0d92573d22": { - "balance": "11000000000000000000" - }, - "bb89936d562b19e4c599826ce7cd0c60cb02b512": { - "balance": "725910446589000000000" - }, - "bbc509b7999b0e94534477b98ec8927cba879677": { - "balance": "20000000000000000000000" - }, - "bbcfa9ab62f4eab14d6a1b09c1aa554dae113183": { - "balance": "589417352665000000000" - }, - "bbe78301134249b52b74d73ee3855e7e3d288a40": { - "balance": "4456159000000000" - }, - "bbe7bb4c4f1b506b58f7e3334e6c89011cf2d6a7": { - "balance": "3889127030000000000" - }, - "bc016690596e077273465d1728d18553b185654c": { - "balance": "185932953686000000000" - }, - "bc16b2ab9c7ab309249f93b496b75c6a7392cb10": { - "balance": "5000000000000000000" - }, - "bc254e5405b154b98abb5fe5508d3e7c98663f4e": { - "balance": "144000000000000000000" - }, - "bc258aeb0f18150d3ca253c6bb04f63d657d99ac": { - "balance": "6011905701701000000000" - }, - "bc2620b5ebac12a88b287b625fa5b336568e7869": { - "balance": "534886892259000000000" - }, - "bc318687cfaae2be4c5ece4a18bb9252486a19d0": { - "balance": "147226513970000000000" - }, - "bc32dd123fcc2ef0dc36484c3ab1bae5d9890761": { - "balance": "16000000000000000000" - }, - "bc5c5151be06aaf6180bc9c1058b181a5a30366e": { - "balance": "113865120384000000000" - }, - "bc66241ca430dc31a3e2f44dedba868e16b9a6a1": { - "balance": "50000000000000000000000" - }, - "bc7c371af0688b1c409f4b07662609a1c9efd120": { - "balance": "20000000000000000000000" - }, - "bc9454f7efc86e25d18a8e8b6e230de42a51d967": { - "balance": "148103676062000000000" - }, - "bc9d5456b975bf0b95c161c3355e4ceb28898fd9": { - "balance": "28083912047000000000" - }, - "bce0b47bf13e4517c53bbbe6e51544b99f3147f6": { - "balance": "919711480389000000000" - }, - "bce2d1ec7c41b426f72b352f5f2b7da3edac4157": { - "balance": "908085365725000000000" - }, - "bcf0756789a57f16206dd78bf6e1322ba9b9b85b": { - "balance": "110888224252000000000" - }, - "bd0bc4a0730f9f55a2f65f62662c7553db52238e": { - "balance": "8440290043000000000" - }, - "bd29fda37c2581a3f040c77eead3143cff24a346": { - "balance": "126022762542000000000" - }, - "bd4c1270322a26a1b825040b239008a447c31918": { - "balance": "727012140904000000000" - }, - "bd6a3da2db66dc9fa26fa2b63b14003d26ef91d0": { - "balance": "5492112771780000000000" - }, - "bd80fcccac60078fcf09f5bddd8a25a92fb9cfdf": { - "balance": "10000000000000000000" - }, - "bd92dc94b6e81a3da5dc3ae6bd80782622658196": { - "balance": "10000000000000000000000" - }, - "bdb35c2c595fe7a2864ebe20dd56d6ddaf9d447c": { - "balance": "4346566125000000000" - }, - "bded4718cbad2150c9b6df9ee7356e0f5c713cea": { - "balance": "311694803600000000000" - }, - "be1804630ecd95ac411b935566cecc5a24c6f18a": { - "balance": "85033246331000000000" - }, - "be2318ad50b0a85b95870a81dce5c31029636159": { - "balance": "5185298019030000000000" - }, - "be3de52fc1119f02f4707f353c040b7c4222d847": { - "balance": "25267399461000000000" - }, - "be4feae01d429c872601ae84dfae8fddc3372686": { - "balance": "20000000000000000000000" - }, - "be7c09d704d16e4b2c9e19cc8c07808bb335f926": { - "balance": "25000000000000000000" - }, - "be873a9525899bdad5e4376b0115950e534dea2f": { - "balance": "404116929377000000000" - }, - "be891b1680ad835aab1ac05a30c0813306cf20f2": { - "balance": "144000000000000000000" - }, - "be8ed2d85a5e3f83c6105db1a1f304e9f174bfce": { - "balance": "50000000000000000000" - }, - "beb1cd80c2f8fabc27ee3a3b2a15e35fa52e7879": { - "balance": "11539095431000000000" - }, - "beb67375e46950830906bf281209be133075452f": { - "balance": "1305262446956000000000" - }, - "bebe54437722c6000bc6a8843f159538a2abf613": { - "balance": "41042548942568000000000" - }, - "bef2a05e283ae948efa9b0e3a6ab5d26a57f1de0": { - "balance": "180614450853000000000" - }, - "bf03950f265a4182b4402703723a0311158eef4f": { - "balance": "158997402149000000000" - }, - "bf06393654baa1ad15c2e717e06dbaa61834c214": { - "balance": "34409427774000000000" - }, - "bf2b867313a44bd04aceaa644771d1e95317c881": { - "balance": "10000000000000000000000" - }, - "bf350ccad91a2a2aff4cf27a291323a297a78009": { - "balance": "124593326152000000000" - }, - "bf3d86edfcf52733e91a9c59be606a95bd921885": { - "balance": "20000000000000000000000" - }, - "bf5b21d5e339752b33b180064d0e6047338650a5": { - "balance": "1000000000000000000" - }, - "bf64c2715db8f353600a45b9264e1f22a40ef8c1": { - "balance": "2952972677360000000000" - }, - "bfaff32c8b04a61658ff94f94e4687232b8d2d7a": { - "balance": "1117691379350000000000" - }, - "bfb00182321502e0729d9a0862ec1df1b3e2208e": { - "balance": "500000000000000000000000" - }, - "bfcdfc9f60610f0ca279ca2c89b9af831332aece": { - "balance": "1431082635308000000000" - }, - "bfe14356e86f6b2ad470bc77d250517c8dc03d15": { - "balance": "310115085185000000000" - }, - "c008bd3fb881da9dca4cadcc56b1d99c56db9abd": { - "balance": "12899598792000000000" - }, - "c01efea456d30360a78ee10c790d46bcb889ee61": { - "balance": "103203021492000000000" - }, - "c03d622627bba7d5db1a9f699924e9d5ff5640f2": { - "balance": "95102233308870000000000" - }, - "c0465ed806ce7ee730e5b6eb7b86a754bfd196a9": { - "balance": "1654379359619000000000" - }, - "c061c5b0d0ce7af95ded1805abb23f743e13c455": { - "balance": "500000000000000000000000" - }, - "c074f2024f79cf8d7aab2d858dd110fc2ee89d41": { - "balance": "18382732686000000000" - }, - "c085147a76d0336b4bd6e7d5b60d394bfd3c6f42": { - "balance": "3236912707535000000000" - }, - "c089416d2d679cb2abf44251de227d0a08fa1206": { - "balance": "497124416350000000000" - }, - "c09d8cfd85989397dc723f2df821dbfb2c0c39b3": { - "balance": "833485701262000000000" - }, - "c0aaf130e3b67250d9775d62e7cd3963daf0a627": { - "balance": "1249947125780000000000" - }, - "c0aebdb5c2e8c5ff9870535c738bfe892c9365dd": { - "balance": "360097616959000000000" - }, - "c0db5680ba88052652bfd5a617c4e8a5be188077": { - "balance": "509051625766000000000" - }, - "c0ee350e5e09a2daeff332a66a6e117fad102112": { - "balance": "10000000000000000000000" - }, - "c12c0a3fd42501f8772e4ad5d262eef3f0bc4701": { - "balance": "120398848512531000000000" - }, - "c135b48c7fd11670bbfba923b28767d21d7923ea": { - "balance": "20000000000000000000" - }, - "c1397c66b7f150c0062b0e87c981c107d771b109": { - "balance": "87751498250000000000" - }, - "c1507ee435cf506fc5d8e4cb62515f2ea0f3a7ae": { - "balance": "4935384099000000000" - }, - "c150d185e2cf203054a6e328b72d8c35bfbbcc33": { - "balance": "21044148271000000000" - }, - "c163098f8b8f0736862274860b3842cf14bd2288": { - "balance": "119025568966000000000" - }, - "c1687fbbc7d504b73fe3e71af440b3dec0da88b2": { - "balance": "229520711528000000000" - }, - "c172bf224080d448261b3b66453074b28628daf7": { - "balance": "7903438287958000000000" - }, - "c18e9bc05dfee2a39fe2b6778a24a48d5bf0f141": { - "balance": "500000000000000000000000" - }, - "c198fec4069c95300d34b9c7109d7441b8e62745": { - "balance": "50000000000000000" - }, - "c1b4134f4757d19a687d05bd7087872b5625405f": { - "balance": "20000000000000000000000" - }, - "c1b43ca2af534ac6bcad8f23c30c07ba07e7e8fb": { - "balance": "194999622000000000000" - }, - "c1c2249507d2dcaf4a9103fcea2cfb47aa4957f7": { - "balance": "571416394325000000000" - }, - "c1e90af40fb64427aeb79a13607debbae9270b52": { - "balance": "50000000000000000000" - }, - "c1ffc8938f3412d19d428b8450f17fd394ae539a": { - "balance": "36000000000000000000" - }, - "c20013e25ae53d0d41bf365aa767822bbbe70936": { - "balance": "10000000000000000000000" - }, - "c20e9eadffa5529ce58a39f5898f39906dcd4b78": { - "balance": "757301065305000000000" - }, - "c211fc2623d51846d26952628d140643efa5156c": { - "balance": "865384323985000000000" - }, - "c2546c312570b30ad2ed05edb13b6469494c5b92": { - "balance": "5000000000000000000" - }, - "c25b2280ed0f835538f8ffd9dfc08a3b853f1ccf": { - "balance": "1000000000000000000" - }, - "c260e43b89a7a4e84bcc4c21dc43d4b5e6923f3a": { - "balance": "1000000000000000000" - }, - "c26aeef0e1f382c88bbdb1eb8c01afa7f58218ce": { - "balance": "79774757760000000000" - }, - "c27dd2645254bc30b6cf7bf418803b02ac808b5e": { - "balance": "4419594173874000000000" - }, - "c2b4f6cf92d6d63a20034e409a358df1803159b8": { - "balance": "1630820442000000000" - }, - "c2ba4a7ea6ca2d17231fb17ebd5dd2dfc0964de4": { - "balance": "221662324727000000000" - }, - "c2bc18f24b8097208a8b2418c444ea58beb94281": { - "balance": "1766754009521000000000" - }, - "c2c028dd17f8a89b9131b7daaeae9cb1dddf86e7": { - "balance": "10000000000000000000000" - }, - "c2ed78a0cb850c12ce8e6ff3873e8c18ffc9f4b9": { - "balance": "1017518755567000000000" - }, - "c2fd7296210b7013d476205d2517d51b21c9e76c": { - "balance": "500000000000000000000000" - }, - "c3041d3d650ff6ac3e35b60371b6798360727651": { - "balance": "1011071365226000000000" - }, - "c328ab9ce1fddd5623e0383828714a7e3ff12eff": { - "balance": "285042661579000000000" - }, - "c34ab008ddddf376dd866cccae4a4d6eb88403e2": { - "balance": "2798642711076000000000" - }, - "c3511391c4515cf8f27e9bc0f777a02a4125c8b1": { - "balance": "20000000000000000000000" - }, - "c36916a9fdf656bb1a8c2f7fb752a3489020f6ff": { - "balance": "689483152953000000000" - }, - "c37598a388d6f4e8e046923265ee9256456e40ab": { - "balance": "62865106394696000000000" - }, - "c38813db256eb221a7142d042b81ba2babab2c31": { - "balance": "98477603778000000000" - }, - "c3acd30f0bc3146fc2cab8d54904f98289021374": { - "balance": "17820000000000000000" - }, - "c3ede34dc1cd995fda1c5cb6e9ffd0c0da080587": { - "balance": "1080428143758000000000" - }, - "c3f04dffe2be55a1d6cdaa78e5c09a79d0477e7b": { - "balance": "59747493842929000000000" - }, - "c3f09f681cfb57d3cabc547dc32a71d2a6585c1a": { - "balance": "1757648436173000000000" - }, - "c3f3bb6444d853614f18c04a3c81f7d26e62e96a": { - "balance": "9022830778000000000" - }, - "c3fe4534327a2fc4144e2d3d3392f7b78d2aabc5": { - "balance": "1759225739027000000000" - }, - "c424f5be9490ec7f0f1e2debc3f72bd83e35f587": { - "balance": "1774372626989000000000" - }, - "c434f64eb937207f80e9a02d2f77ca34bfc63aa2": { - "balance": "960850858644000000000" - }, - "c438b6fa5801a4b8dea450530d975f174cdd47ef": { - "balance": "64000000000000000000" - }, - "c446effb984ff3e5ed92280e7b3dcdb1284230b3": { - "balance": "503490303680000000000" - }, - "c453ae9f94253ebdb871e9dac19056b13d1747a3": { - "balance": "1621494076559000000000" - }, - "c4a473b5e3a6bfb51f963d4dcf109bddedf4fb43": { - "balance": "104273242373000000000" - }, - "c4b8058e9e5416e526ea16e37f29dc221d28a003": { - "balance": "1833513486496000000000" - }, - "c4c09f4bbae0ee06f2a52ff0ef0de1978b5305e9": { - "balance": "20000000000000000000000" - }, - "c4c5981f5ac0a9a3701663b887c4aaac3a3a4d1d": { - "balance": "1411640000000000" - }, - "c4f7a493d16aab4d18e88e530e75e3095a3439ee": { - "balance": "191606419322000000000" - }, - "c5259c18bbd8b0485ca83d069d5ac235b28f24ea": { - "balance": "1276479076242000000000" - }, - "c526ef1124c7d0549b117e7b7463539a24209290": { - "balance": "9106523141000000000" - }, - "c5278b9eeff2221604f30f002c307ca2882fba97": { - "balance": "20875716591000000000" - }, - "c527ca73562846de9fca1649fe5144e5068a2f6e": { - "balance": "25000000000000000000" - }, - "c52a960c5df55169ed5d5cb0109a576321ab82fa": { - "balance": "1097338876493000000000" - }, - "c533ab799e5a04e0ba4e4780d632e0044262d216": { - "balance": "200529941482000000000" - }, - "c5389e3ee2f043ac2b6481f254440a97a9cf3bdb": { - "balance": "84047554571000000000" - }, - "c5594292b324c1d63f797c588a589c895c680ed0": { - "balance": "334298857161000000000" - }, - "c55d7ae4f29d857182d5f1ac2a78cbf35a694dc2": { - "balance": "500000000000000000000000" - }, - "c55ead0ece8fcfbecc573666c0170228e089aefb": { - "balance": "438775082956000000000" - }, - "c55f7d73491cdba391b631581029de32755a09b8": { - "balance": "1340000000000000000" - }, - "c56cb4e8308d6462eded0bbc74965ee135e23e11": { - "balance": "568187503785000000000" - }, - "c5b0c5f840f579536d5977a77262458d72ef1490": { - "balance": "5880686297881000000000" - }, - "c5b129c764daac8bfbf023646b9306d817a8ebdd": { - "balance": "10000000000000000000000" - }, - "c5bba43db949e2ed3de3036caf7a6e42558b1ef2": { - "balance": "763947031151000000000" - }, - "c5d57171e5b9cbafaba7d2c13cca3ec9d81bda49": { - "balance": "25000000000000000000" - }, - "c604e6c539c857ae9e60ca20d1906308ba431892": { - "balance": "100000000000000000000" - }, - "c607bdc5ad2f189e9356edb4d7975c7ba9300836": { - "balance": "55828814399000000000" - }, - "c60b0d2341ecada6c3faf1efcc9027125d99e17a": { - "balance": "121000000000000000000" - }, - "c61e1b993c3fd91a1023ba5b92d06a0aa539d92c": { - "balance": "23863993763643000000000" - }, - "c624656ee5298786cb3d0de045b0ac089c5341d6": { - "balance": "2210389938000000000" - }, - "c6573a023d6f4b5e151f266af4ec0045df0d1518": { - "balance": "52505006485983000000000" - }, - "c66b1d84c42018b16dbc4777409bf50a49febba9": { - "balance": "9078953000000000" - }, - "c69e4de93457f251b1e0879b5250b26e57839fec": { - "balance": "500000000000000000000000" - }, - "c6c51205c9f0bcaea05dce8e47e91d94a3f63c2a": { - "balance": "2720612321571000000000" - }, - "c6d237e0936c4714e701823aadb368fdc471451d": { - "balance": "541700595551000000000" - }, - "c6dcac15739872089cb3d23287e8cd546487ecf2": { - "balance": "1023857245227000000000" - }, - "c6f40b81a5860dece34305f53570be61cdf9a8fa": { - "balance": "20000000000000000000000" - }, - "c7147a95cc4f6bedce6292e8f95539caf550e9d6": { - "balance": "20000000000000000000000" - }, - "c7185b1a680d8b0893065d8213de54375d086420": { - "balance": "11564622085000000000" - }, - "c71b3876613c928197aadf3dd7888db3665f28f0": { - "balance": "112276274428000000000" - }, - "c72200bb380db62a3fd741713d332be77bc1a4ed": { - "balance": "6962060809000000000" - }, - "c7345cd5a7eafc9d7ebdc17d674f83e23336538c": { - "balance": "4425703195684000000000" - }, - "c734f9dc3ee2d857ac826b101129eb77a4a22256": { - "balance": "100000000000000000000" - }, - "c736fa9550b73f4a4ca0ac1cd94bf6f42ccbb11b": { - "balance": "449139000000000000" - }, - "c74128ea37f5d1ee016086a38e470bb332eb5270": { - "balance": "40479951869000000000" - }, - "c7647ec91e823cfe57e8a3433ddafd7b4f675b80": { - "balance": "307102062000000000000" - }, - "c76d49334ce25f5fc62841e5a87d4e03ab3edd9f": { - "balance": "109999979000000000000" - }, - "c771093ed5c4df518536b76e013e8142ecc3f9ed": { - "balance": "5247752820195000000000" - }, - "c780dfb4cdcba4dc89245a8be8a93de1a3e82d3c": { - "balance": "205580199482642000000000" - }, - "c79c6c3a0a46052f723a26b1f107a332474df3a1": { - "balance": "50370325181000000000" - }, - "c7a4e02d2c0f00fa56662cc9f323cabeff82759f": { - "balance": "1163435680762000000000" - }, - "c7c0632cff11812130c30163c83746839a625f95": { - "balance": "10000000000000000000000" - }, - "c82238664bedfa8ded51e91969a39f13a8262a37": { - "balance": "10000000000000000000000" - }, - "c877d228c350ec0d8d97802e7d874d3130171813": { - "balance": "199845203467946000000000" - }, - "c88b8a2e498fee366a1290a575a7f09da12ea8b2": { - "balance": "50895598476000000000" - }, - "c8bbd0e52b11ae6a20adc5f6bbe4d34d7440e8ca": { - "balance": "114566193776000000000" - }, - "c8ca2bd1bef02b505f0333996bcb6bf730648390": { - "balance": "1177250974576000000000" - }, - "c92c3358910418fdb3950e1a378af7246553ae38": { - "balance": "81000000000000000000" - }, - "c9325c9b6d2af226bc5ae1cc975e00cc11274cd1": { - "balance": "2927587698197000000000" - }, - "c95ae8dbc8bb075e7dcb2b2c6d9411bedf26244e": { - "balance": "931878010706000000000" - }, - "c98fc33c1d980052d75fee8b34d08796734b6a4d": { - "balance": "8671327034000000000" - }, - "c99fba8321d16cb19c55703b407c54ed106dcdc4": { - "balance": "20000000000000000000000" - }, - "c9a0da2a3be799e751738e61b9cc376eb06e2b00": { - "balance": "50000000000000000000000" - }, - "c9afc551058c32e89bc2d6704d0d00e92f5ef6d7": { - "balance": "11135553563900000000000" - }, - "c9bfa2ad4b3e9c624255c6ede116421b04487d65": { - "balance": "105514983171000000000" - }, - "c9e4b61d8ddeee339e31ba088efb5d608c3464a5": { - "balance": "20000000000000000000000" - }, - "c9e9090d9f95f401c87c7240f3bf88ca9b540f8b": { - "balance": "553735838243000000000" - }, - "c9fd40bb35284e3d7f0dd3b43a1d9e958f7c86e0": { - "balance": "50480449695128000000000" - }, - "ca038c7c9e66531ad79e4d67b42d7920b7f05c26": { - "balance": "64000000000000000000" - }, - "ca0d08f6019884f94f2b5b191ac9bb247150cd13": { - "balance": "25078089364984000000000" - }, - "ca2c6e6ed3d6a1d030807f91e1fd5c79d36af86f": { - "balance": "849454139892000000000" - }, - "ca7c7bbc24cac0f3aabfdccc77df21004672e634": { - "balance": "6952718700000000000" - }, - "ca998c74383b55c8dcddd46b49f95456fb056b7a": { - "balance": "2000000000000000000000" - }, - "caa989e6a1e934532aaae6cad282c18b1a0b9fd6": { - "balance": "2335540529729000000000" - }, - "cab32ee5cce74e0ee88bbd4b505aa587ef2e4bbf": { - "balance": "75914058971000000000" - }, - "cabe9f0d0a18de8d3495dd063b04c6a33584a8c1": { - "balance": "116083536145000000000" - }, - "cacde94daeafc06e46c86b1e20387a23d909ace8": { - "balance": "1521003430346000000000" - }, - "cafbad01b81ad6cc401883773994a9dd6e6ed913": { - "balance": "10000000000000000000" - }, - "cb343b882cfe866f73cd5f0f31fc68cebaddd882": { - "balance": "221801563082000000000" - }, - "cb3a7aa2e97517b6ea8d9ed0ac270a6a9cc6e079": { - "balance": "958830201738000000000" - }, - "cbd2c4916211ab2c234bc8a51e6f680b59aff782": { - "balance": "24279462419000000000" - }, - "cbea4ed5e8d2ffad442e482fa5f8d551ef2a58e6": { - "balance": "26730000000000000000" - }, - "cc001ce4f4417505116486bed9fdf04bf97ca246": { - "balance": "31740534557000000000" - }, - "cc0b53b26b6dee9f8226f25b834085bde13f5eb5": { - "balance": "132440104515963000000000" - }, - "cc174862456f02f349303d1b8328495de8ccd789": { - "balance": "155951512603000000000" - }, - "cc2af3921727d6d2de31d5f656f837a5475de6cf": { - "balance": "10000000000000000000000" - }, - "cc3201749f55f0d7b450110bc11f65b1ce165d2a": { - "balance": "123428947550000000000" - }, - "cc3f37ad6b449e39c544e26bbdf4d7be66b9dab0": { - "balance": "348574664284000000000" - }, - "cc5b36c9ecea12ebfd0721a58ac11b0c340a3f44": { - "balance": "384197170701000000000" - }, - "cc5b410c7797faa05ac4233eb31b468ee4bf279f": { - "balance": "10000000000000000" - }, - "cc60b223554cc6425374c5e2424df7007621368a": { - "balance": "1128118098000000000" - }, - "cc7027381d98c2e883c82bb9c2f85b985e1e7b4c": { - "balance": "1370000000000000000000" - }, - "cca378f16e07258b9c15921233110fb4729645d2": { - "balance": "151974946930000000000" - }, - "cca781d996c3ef985bf7d2b4d68d55f52efe1905": { - "balance": "2217463190039000000000" - }, - "ccd0b9f6ffb0383553c355c6a14be1200966d47d": { - "balance": "12917165349191000000000" - }, - "ccfa4594129bbb9d07cb4ae8dc2b1c8f3bf98508": { - "balance": "524845286088000000000" - }, - "cd19c879df458106d179bbb5b7f44609d68e6e5f": { - "balance": "8601633489844000000000" - }, - "cd1c55037a0570e8f9aaa95ef157ae81a1969250": { - "balance": "10000000000000000000" - }, - "cd1e47695b0fc93b82cffd0326852dc04d8441f0": { - "balance": "144000000000000000000" - }, - "cd1f90c388d76b3aeaf77850f2191f12a2311f51": { - "balance": "1728456799866000000000" - }, - "cd3aecd58de07f80b64044875fa6ad4f18f72789": { - "balance": "2648597880142000000000" - }, - "cd4f39123ece1e0ab52cfa2a5d059b49c4d63c3f": { - "balance": "1661718859439000000000" - }, - "cd6ed2f7ab49515f8fd70aeb4d72bfae8956b5f1": { - "balance": "183807926254000000000" - }, - "cd9d9d07fcf476a8ee7240324a602449606d75f4": { - "balance": "100000000000000000000000" - }, - "cda66d375a10a22f13dff8a9c40b63461daddab3": { - "balance": "1116940051064000000000" - }, - "cdb0832ee5b26da24b1775c4cf0dfd669b94ce00": { - "balance": "23919219542965000000000" - }, - "cdba5805f17df1f3e47647464de978944ed36b62": { - "balance": "4204539000000000" - }, - "cdd1df8bd54941e26ea26eebbd537e751f64f5f7": { - "balance": "5000000000000000000000" - }, - "cddf5b34342200c37ba96eb0dd662ca4c29f89f8": { - "balance": "10000000000000000000000" - }, - "cdf6c838980afd91a600e3fff755a4848d138568": { - "balance": "25000000000000000000" - }, - "cdf7f55a5a16572d2f2bbf7faeffe3c4d64f86ab": { - "balance": "3115969322502000000000" - }, - "ce0f1dbbfa3490a21ee4b28232db612f44bb7bf1": { - "balance": "9227310122000000000" - }, - "ce33184573c33dd859450304984fa63ea4f2b62d": { - "balance": "7055925237496000000000" - }, - "ce33a3db107f01c51d30b24a8db80faf05308bb7": { - "balance": "10996113113089000000000" - }, - "ce4922b3daef62914f0580a55c524e6a02e31d83": { - "balance": "5541295938315000000000" - }, - "ce4ce8a8540678dda16380c211482dd8c8b71092": { - "balance": "6224176337062000000000" - }, - "ce62cfd71abb9979a0acc398c17dbb5cb6da4721": { - "balance": "13448605175000000000" - }, - "ce724bb30c7821a9c847e0a3e9c12843c3471f9d": { - "balance": "252657175031000000000" - }, - "ce8af01494c2c5b4e74bb02dc6de982e7234fed2": { - "balance": "77349533545000000000" - }, - "ce8c774b7f92045faec43e9cc1711224a3b32435": { - "balance": "370287579971000000000" - }, - "ce8c9ed5018559f36ec72e5a9b0701724e498b51": { - "balance": "142866501748000000000" - }, - "ce995c13568a8b1521d4c9721cfc11da4891860b": { - "balance": "1000000000000000000" - }, - "ceab9dddc767a9651e98527fcf51f6e85c9ae402": { - "balance": "5251411770975000000000" - }, - "ceace25f8c7cf853500a461df007f9c9703ac4a5": { - "balance": "1428847332255000000000" - }, - "ceb0c49dad36f6169ec82a2f0d80da36c87e4209": { - "balance": "459821324064000000000" - }, - "cee8083233bcb4d50ddbf2121c90b5c2019ca58d": { - "balance": "557985245088000000000" - }, - "cf0c6bcc66eb75899bc7f8ed4b8d2b29437bfe85": { - "balance": "3252418478000000000" - }, - "cf32c5bf1d7ef0cb0f2f190f8468b01a4f2d93e2": { - "balance": "6593164924646000000000" - }, - "cf6e47463382153fcf0ec6738880925dbc08116a": { - "balance": "1091910654350000000000" - }, - "cf7539096fd0cd97cd316efcfe9d3c87a101a74c": { - "balance": "741847588809000000000" - }, - "cf9439bf2fbab65cecd783e135a37127f585f1e5": { - "balance": "50100000000000000000" - }, - "cf9bdc902604fab070c611ebf6a989ac4a785c82": { - "balance": "1501000000000000000000" - }, - "cfbbefc0e6013fa2caeabc54ac05f45dbf17ca13": { - "balance": "230809632301000000000" - }, - "cfd53f18ac7d94cadd032a0f4cdbdffaf4765d6e": { - "balance": "64000000000000000000" - }, - "cfe66dc4aa9ac9c9f87fdd05c1b2b95da5211703": { - "balance": "1656993051100000000000" - }, - "cff376eef4d69c4a47d6c7916583228fab3b5967": { - "balance": "5904462494391000000000" - }, - "cfffcb819302d05ed763026bdf84b48818938fb0": { - "balance": "289619807900000000000" - }, - "d000aa72a77d55911a5e66c2906da9206db86633": { - "balance": "3008989624945000000000" - }, - "d02d7b42213e873f91e789cbaffc734ffabd1087": { - "balance": "144960809826000000000" - }, - "d02db5279e918b3e93ff81d00d4025cc71dccaf6": { - "balance": "2386625717975000000000" - }, - "d0802cbcca2bb516f251b873eb20bb5e94af7f37": { - "balance": "9287997718210000000000" - }, - "d0c07380308972a36f57d1cd9081d7389d0421cb": { - "balance": "1280367167470000000000" - }, - "d0c131c1b60891b91e58fbed787ee4567e3f2038": { - "balance": "6360752089492000000000" - }, - "d0c71159d46c4d2af7699f682a055c79a1a68a0d": { - "balance": "1527974433762000000000" - }, - "d0d5d9f242f2613079b3b443c359c2e18ed5faab": { - "balance": "637334647476000000000" - }, - "d0dd208ce92da02eee3ee3de335e67f819581a33": { - "balance": "100000000000000000000" - }, - "d0e55ec0ad0f8986dd9fa9d738007c5bdc22f840": { - "balance": "53012893797000000000" - }, - "d0f222cec657ee444e284c07228d585155b82c0a": { - "balance": "7368748129592000000000" - }, - "d11efb07887d8b5b87a77d8fd388190614e8c077": { - "balance": "4703283503278000000000" - }, - "d129f1b89045ebfb4d1df1d9077e9359fd2990f7": { - "balance": "14496053137000000000" - }, - "d15a509424c4e04868bdcf59cbee09882ba04c8d": { - "balance": "65042393236903000000000" - }, - "d162416912b03fa65f3972a63e357ceaa3b621f7": { - "balance": "325650177224000000000" - }, - "d166183164b81bd049b2146a3ccfcc78cc6a0bdd": { - "balance": "1000000000000000000" - }, - "d173d759f0916e61400d56ca690cbf1743fe27b0": { - "balance": "53550838679000000000" - }, - "d18dc883e3881bf4c7db2afaa097bc2d33656724": { - "balance": "5000000000000000000" - }, - "d19dc9b5ae689dea1ccbfea8b44ec6034559e326": { - "balance": "135552499885000000000" - }, - "d1c79160d0b8c1a1546b86db5123e87645a45d13": { - "balance": "10000000000000000000000" - }, - "d1cccaa22259c547993df3c147d5b545f003adb8": { - "balance": "10000000000000000000000" - }, - "d209c9f32f3292ac4d15ef353fbe6f6efcd4e49d": { - "balance": "81000000000000000000" - }, - "d21ac89a20d67e309f96f64adf05fc48f55918a9": { - "balance": "500000000000000000000000" - }, - "d21f6e7adbf480600295af683091f9b9833f5330": { - "balance": "1229445878922000000000" - }, - "d22700a47a0edb137d2f0348aa0f8d4b6dbc5850": { - "balance": "21301422923000000000" - }, - "d258ddc9372e3b70ff53da171252239655ca9886": { - "balance": "16000000000000000000" - }, - "d274c69317dd836df48562455e8f5a7bd2e47d19": { - "balance": "156091832558000000000" - }, - "d286b68a358fcf8a6cec70b83467079664632ae9": { - "balance": "90377010699000000000" - }, - "d29284915d9b924ae5673e8a4a557478f68a7471": { - "balance": "324678197320000000000" - }, - "d297e64ac2bd8e98e6d276d6fe080679c398a26a": { - "balance": "3401930527000000000" - }, - "d2a1e7b51f6b5930a0d9e2ee55736f3d83a1b323": { - "balance": "44578900750000000000" - }, - "d2c9b0b0bbe61de504e4f210c168fa5999c9c23d": { - "balance": "76537483113000000000" - }, - "d2d49f650d222ec3e2cecba163ee92f0e934ca14": { - "balance": "3312486482635000000000" - }, - "d2d803bf10ba18adef5716b4056c1b1d61c45abf": { - "balance": "964679698000000000" - }, - "d2f673b589df7ef5cb32fdeef842d48d66130567": { - "balance": "1079010447581000000000" - }, - "d2ffaceef1af3f1c3e3f35e4062cd9f9abd1da59": { - "balance": "3041453068594000000000" - }, - "d30a74f5041ec6e73d066a375a105116699ce177": { - "balance": "21814020745000000000" - }, - "d30d849a2d8ff5041304014ecf6752dc769bf004": { - "balance": "1247532881540000000000" - }, - "d3113f558c6376321691931c9b21205e31f4a56e": { - "balance": "572224428451000000000" - }, - "d314bac1bf85eedeac0b359dd2106dbae8fc6947": { - "balance": "20000000000000000000000" - }, - "d3283e17112028b324327ef64a238183ba189207": { - "balance": "136000000000000000000" - }, - "d33ce3c3b64d1b3d399651432c15ecb943d16c70": { - "balance": "10000000000000000000000" - }, - "d33e1e4b10a98e82810f6d161df5d35e5677e35f": { - "balance": "10169656674000000000" - }, - "d34699fd152fe38caacd3c096f6abb1cd79e88b2": { - "balance": "25056644550000000000" - }, - "d369c0e01b9a9d519b3b099a98fead19867c019c": { - "balance": "100000000000000000000000" - }, - "d388dcfe55a9b710d05c686f033fdbdd7861ab71": { - "balance": "1439589263065000000000" - }, - "d391a7d45c7b454b743bd867f8f62f56894f9b65": { - "balance": "484904747488000000000" - }, - "d39a75b4831543e1bc99e7a5ca8875c4f69da45b": { - "balance": "10000000000000000000000" - }, - "d39ed6978b6a90fea29e735f8ea3f1d20e0fbd15": { - "balance": "144000000000000000000" - }, - "d3a0a1a00dcbd6bc44c9803ce351a4b36a69c929": { - "balance": "191222401916000000000" - }, - "d3bf1c0a6b0470c30fc49d995025af5e6b639e61": { - "balance": "10000000000000000000000" - }, - "d3cda762bafaf204469f85e6896ec64147a3452c": { - "balance": "468094119213000000000" - }, - "d3d04d78c1ab9e6887a9467b8b1e31b5c9910e5c": { - "balance": "81000000000000000000" - }, - "d3e1bfdd9396aba00d3e78646ddcdaf139a967c0": { - "balance": "833333174120000000000" - }, - "d3e502c42ff0274da12ba87ffd45fa593bba052a": { - "balance": "100409899947269000000000" - }, - "d3e76066c2e32d9a693161de07f2d3b7e6ea07eb": { - "balance": "10000000000000000000000" - }, - "d3e8d577323d97407246b198c4c61f7943c468cd": { - "balance": "10000000000000000000000" - }, - "d3fd4d1b0edbc314b103d350fff023ab75b7d7cd": { - "balance": "84129547428000000000" - }, - "d40087fca8feb72d130bbc9622575d4987f12895": { - "balance": "1000000000000000000" - }, - "d407d4126cbf3619a422c532ccf20c3da1495dbd": { - "balance": "99622000000000000" - }, - "d41a28761c8e5de8c803813667f1dc0918a105be": { - "balance": "157507410260000000000" - }, - "d46ed38228a3c3d78065b2d8b71b325bf0f0e685": { - "balance": "6787045850000000000" - }, - "d4a7463d202e804b39a93bccd77491d8791baf58": { - "balance": "171694163573000000000" - }, - "d4c20716ff7288d811d05fd6f0696a9f5627a11d": { - "balance": "100000000000000000000" - }, - "d4d95059c808cf41e64f7f353246ffae635419d4": { - "balance": "10000000000000000000000" - }, - "d4ef925157c6d0e2d649332f44416b85f8abe69e": { - "balance": "1392945162611000000000" - }, - "d4f0cb25801794f6d803306878763e08209d19f4": { - "balance": "64000000000000000000" - }, - "d55fbebc4dcf2de6341c2325448e9c198f0f06a3": { - "balance": "14206622892000000000" - }, - "d566968c40211fb25114105e36b5a7219cde9d5f": { - "balance": "4898442964000000000" - }, - "d5817b95c6b504a6d07f64faccc9aedf408b0ac4": { - "balance": "54387832478000000000" - }, - "d59679fc40a71897065bf1b3a73f331226cdae72": { - "balance": "20000000000000000000000" - }, - "d5a7deec4a5898f094e1600f9b15768d8aada258": { - "balance": "100000000000000000000000" - }, - "d5b91c29bf772ad3ba04033dfb86b672b245ad77": { - "balance": "100500000000000000000" - }, - "d5c1a9bcc5e68b7547354178fefb3d870572fd67": { - "balance": "2252066779089000000000" - }, - "d5da2a826f5909a221bfd8561dbd7dbf4aca4c35": { - "balance": "13839784966766000000000" - }, - "d5dcc82fa169b4677a3fc26d78f38e27dcc763f3": { - "balance": "10000000000000000000000" - }, - "d5f344ee8a1b954ae5fd8fc7ac702174749bc8a4": { - "balance": "1398836216771000000000" - }, - "d61cd03afbfc1bea186e5a3a51347c2c4ee3a2c3": { - "balance": "109879472702000000000" - }, - "d647fd7ca17203a0049c28ec6759612d767cfcce": { - "balance": "162681136487000000000" - }, - "d656d14acfb2f0fbde2ed2a137a52d852bb6288b": { - "balance": "20000000000000000000000" - }, - "d68130b421b19c193d03a9017b2dc687c7307d26": { - "balance": "128569735484000000000" - }, - "d69a41f7ca76b40ee94b0d04a3780a00c6c651ba": { - "balance": "2801054372864000000000" - }, - "d69af2a796a737a103f12d2f0bcc563a13900e6f": { - "balance": "7412286547000000000" - }, - "d6a5a7e149cbccb72a50b0a3ae00e6756b0a7eda": { - "balance": "1075352201657000000000" - }, - "d6aa9957f141f0dfed77e943c39aeed978834fdf": { - "balance": "20920740110000000000" - }, - "d6e99ccb72d24e8a60f24d47afd4074b1d1fd336": { - "balance": "15415994387186000000000" - }, - "d6ea4a9dda8d5bc832229c916fa45f05f99c093a": { - "balance": "27075799893190000000000" - }, - "d71de419d746ac277baa955761cced4b34c376ec": { - "balance": "1388473506822000000000" - }, - "d71ec6b5e5d4c604f741bafde0974eca49c56156": { - "balance": "61938809628000000000" - }, - "d72f90d9879f6d2d407b4fdf5d128b98d518f1a5": { - "balance": "10000000000000000000000" - }, - "d743d7925a0cfd08150814cce8cd5d3f7099e1c9": { - "balance": "25681376856000000000" - }, - "d7575a09e7498f21cda3e9e7266b7fde91dfe19b": { - "balance": "9841565066000000000" - }, - "d75c2eb5e0a2b2ee72ef4fa7249c1a1ce03f333d": { - "balance": "134491489751000000000" - }, - "d77088329ec1e280ea7a087ad20c5e965721ff4d": { - "balance": "3949070941222000000000" - }, - "d78d564bb79ea19e4a93975a38fe0882018f177c": { - "balance": "992717434142000000000" - }, - "d78efb176b252ce67b5648e04088d12c4668aad1": { - "balance": "10070463674000000000" - }, - "d7a25e43d7d4e23744f0b10e2b4f2911fd3b3bc1": { - "balance": "1000000000000000000" - }, - "d7a941cd82f8aa63c55baa81db44bcb347b8e529": { - "balance": "49000000000000000000" - }, - "d7b34387880daede6cbdad11bb3db67daf942975": { - "balance": "20000000000000000000000" - }, - "d7bca0770e2f890c1e93c3595641241454a31045": { - "balance": "2000000000000000000" - }, - "d7cb675cea1c0dafded44f611c9c344e2a5e053c": { - "balance": "25000000000000000000" - }, - "d7e53a2d8eaefd18e02bbadb7e64906ca8613151": { - "balance": "166599594268000000000" - }, - "d8076b9db0b7496efbd198b73c4bfcf51ac080fd": { - "balance": "210272077089000000000" - }, - "d81dcf5756da397ff1f783ffe5391d1ffd4ff227": { - "balance": "500000000000000000000000" - }, - "d833c6d08f5fff8f77628ab1e86584d052976d1f": { - "balance": "10000000000000000000000" - }, - "d835732e85953baf2af9e49f770bac1caa1dac23": { - "balance": "152211441541000000000" - }, - "d84005fea447e8c6aa0b5436ad79654a75348456": { - "balance": "22563694224690000000000" - }, - "d84d9c59a445911922e88c0f22cc6534f33ca3de": { - "balance": "3054115413381000000000" - }, - "d84e69926216065749e624d87783e90ce3015b82": { - "balance": "1420803164313000000000" - }, - "d884bdbdb7e13cc523e7f192310230c7bdbb4a07": { - "balance": "10000000000000000000000" - }, - "d88eedca1dd9249702f5ffc807c1e439eee1c5e5": { - "balance": "36000000000000000000" - }, - "d8a23fd234bada1c726622925ade62d3021e0037": { - "balance": "1567046607931000000000" - }, - "d8b1aee24264efebd1c677fcab6ada6e0f000cc5": { - "balance": "20000000000000000000000" - }, - "d8ba7afbb8bf2910b983a114aedec626eb7426c1": { - "balance": "275491152435000000000" - }, - "d8c8af55ebf116ba3c3904f8ac39d3a7d31aadc5": { - "balance": "1499999998278000000000000" - }, - "d8d97645f5f62aa89bf0046362dd0f45d40f821f": { - "balance": "25000000000000000000" - }, - "d8ea0e24a7e28285c4454f54181d581324da2583": { - "balance": "53039425000000000" - }, - "d8f5d258164747ccf790f5ed358162c756de49db": { - "balance": "323009990690000000000" - }, - "d9477bb62d3eb668a83a9679f3a7ef43f17c9e4d": { - "balance": "14045557127869000000000" - }, - "d9585e1b03fc86636dde1e64aed3cad77868549a": { - "balance": "1000000000000000000000" - }, - "d975f9ce3fe773fac3f8338a034a757c58f6e11f": { - "balance": "25000000000000000000" - }, - "d97e490faf19de612fb49c041d3f9e7877d3c0bb": { - "balance": "65766847746000000000" - }, - "d98117b74b2f2888d7078d3116d5758e2d09bfca": { - "balance": "1749157484422000000000" - }, - "d990b3f69ec700bdc095c184b3804551c832d612": { - "balance": "509385034698000000000" - }, - "d99b35298e709e5f54e6a5c612a326a83f4268c4": { - "balance": "71963571266000000000" - }, - "d99d9ec76005da26ccc721ec26be4ed9b3b1c586": { - "balance": "469607736824000000000" - }, - "d9bc61075c3201351584a026e5bdfb7cf9a7b6ab": { - "balance": "200000000000000000000" - }, - "d9d07b72f83491b6db26602f6b7039aeebfe6b61": { - "balance": "144000000000000000000" - }, - "d9f6f1ddf03e836b3744d008b62a6424544c67a5": { - "balance": "74347470143000000000" - }, - "d9fceff07ad69bf3b4aef54a7eee541368980cf6": { - "balance": "1143407707495000000000" - }, - "da0285fb7e37fd4be66fb862b248cea94ea8f6db": { - "balance": "80770216661309000000000" - }, - "da05c7aa330fcc5834e19deeb0a808e9ab7f3d99": { - "balance": "169000000000000000000" - }, - "da129e4481bd25450e6c7b42fe417c87ee2ce7a7": { - "balance": "256000000000000000000" - }, - "da32e3ec421993db088c71e256263158f7855b61": { - "balance": "18540215888567000000000" - }, - "da3c99669acd202ccbe6f80902c807588eca0880": { - "balance": "1000000000000000" - }, - "da72a7bec114d43aee6449db830d2d3f16e4d9b6": { - "balance": "744534872932000000000" - }, - "da72ec2cd7b8e3924f8baaea75d5ed23ef39394c": { - "balance": "38646377617204000000000" - }, - "da73078957f491827d62cb3ca0c484c2d1004ba7": { - "balance": "891774109242000000000" - }, - "da828e50c7c8580c6ce81718f11fbd43b2b0541f": { - "balance": "66094097819000000000" - }, - "da91483db6a6a034e068e69a6b46674838c5bc80": { - "balance": "4000000000000000000000" - }, - "da9551b635c3619f81641571e267755b89f7fe1e": { - "balance": "670841942250000000000" - }, - "da9b43a9c1c574580ec43da9f6acb687fc2f8c68": { - "balance": "761695404114000000000" - }, - "daa7f446923f7481115ad285ca468c865147e563": { - "balance": "10000000000000000000000" - }, - "dac6bfd15954efa4c9254e24e5831ab1884f8d67": { - "balance": "960042043423000000000" - }, - "dad85d0b8bb5ebf6ef811d0d35c89f9f343c833c": { - "balance": "37664599958479000000000" - }, - "dad9b01652de5d50bf30f9bcb0c6edc6315139e3": { - "balance": "21500996724000000000" - }, - "dae9c7d6bb0efe3f7ea20442b184f6d99b2a2c12": { - "balance": "937830189066000000000" - }, - "db0d6c28e9b913f611accaab15cc887f9b770f58": { - "balance": "20000000000000000000000" - }, - "db0e5341d64817885721c5abff04c30bd38df40f": { - "balance": "62600679700000000000" - }, - "db387dd404d14478babb60bad2391720d68b92ed": { - "balance": "115096708329000000000" - }, - "db3fb19e8a4a6ace4d8c6c02085d4cbba528b532": { - "balance": "1000000000000000000" - }, - "db4f05a66c0ccf0532ea1ecb931e05a400a6f4a7": { - "balance": "20000000000000000000000" - }, - "db571f1cdf8e83fbff6fb48cc0c81ef95ede12a0": { - "balance": "118317387393000000000" - }, - "db6a6a6db2aef3f43afbfe23027b670ebb3d33bf": { - "balance": "9960755220000000000" - }, - "db8bed34f8f34f45cb83ab19ed33fad76437d217": { - "balance": "21003651205000000000" - }, - "dbeba6a2a7f66c20c6db7b9270a5aee74de3f441": { - "balance": "4086905723945000000000" - }, - "dc04efeac13b2dab3d07833a7e7fa728fc23d18a": { - "balance": "1161834099120000000000" - }, - "dc092386c3a3e28b6b2d7d70db8f3d11e79ef5df": { - "balance": "124362293793000000000" - }, - "dc10be66aa11acbd42a2b1953714f09b5281681b": { - "balance": "20000000000000000000000" - }, - "dc2d58a383ce0bd40bed859ec2f25412b68eca0a": { - "balance": "104917823922000000000" - }, - "dc2e38183dceb2bc82b23e8ccf48dd96ea1c97b6": { - "balance": "2847787376064000000000" - }, - "dc5d9d94530d88451cf081fe7f2ac33667af9d8f": { - "balance": "65321904051000000000000" - }, - "dc993112a8d89136e0e73d67e2f26191583a50ec": { - "balance": "1000000000000000000" - }, - "dc9bb69b295945589a41feb794406558ce65dedc": { - "balance": "104077637254454000000000" - }, - "dcb0109d4fca2dace08ddca5d989a09d470161a0": { - "balance": "28897833222000000000" - }, - "dcce3a4ec516d833f5a9790c40ad0334b0d2dd01": { - "balance": "25000000000000000000" - }, - "dcdb21cc811ab733c2a80a2d5c8e5bb49cb2ddc4": { - "balance": "16000000000000000000" - }, - "dcdf8dd3ce03a2fe0d72835dbbd58725e1ed2c57": { - "balance": "113330414284000000000" - }, - "dd2165839ab95d6b24591307adcde9ee1819927a": { - "balance": "20260199589072000000000" - }, - "dd3015a5fdef66e749a000585d5574f975e3432d": { - "balance": "85465001652000000000" - }, - "dd37c478727f44943c5fd79ace30f21fae5a589a": { - "balance": "108577233510000000000" - }, - "dd3fb5810c31d37652bd17b92497ed479faf123d": { - "balance": "669996966072000000000" - }, - "ddc3bda30f7cf36bd535de4e20c9becb78d159f4": { - "balance": "99998278000000000000" - }, - "ddcce2d2431b67d4157c7ac4bd77f20c24831de6": { - "balance": "36160893899000000000" - }, - "dddcebe609f8b4354a1f27ab1915135e25800344": { - "balance": "1457846339959000000000" - }, - "dde223eb48f81748abde6cbc08cf1e6b0e8e4e5a": { - "balance": "1501921107087000000000" - }, - "ddf4ba402007060d9940a96f8e7c39f0a2c6108a": { - "balance": "377268151287000000000" - }, - "de05d9ada6626a8492acd137c7c7f7080a987cd1": { - "balance": "222144234923000000000" - }, - "de0fab89f79c4edf9766c3b7b1f508cb43c5495e": { - "balance": "8278000000000000" - }, - "de1070f3ff6c47237768fbdead88b2d5184fbe2f": { - "balance": "1000000000000000000" - }, - "de2b16d7f36f630329287822f550ec19415acb3a": { - "balance": "25000000000000000000" - }, - "de3faf6884337a99e54ac5d3f08b34be51b0755b": { - "balance": "51926806905184000000000" - }, - "de4614fd632ddac888d177de0858e62bbbf7dc11": { - "balance": "52506376589000000000" - }, - "de54cabb241dc5def530191f948f67db942a85b0": { - "balance": "9691177060000000000" - }, - "de81e488284acc4f8f6061d3a73bad112efa7a40": { - "balance": "14654060992000000000" - }, - "dea86ac3a661272691c877c1bad8355789382b69": { - "balance": "903877103000000000" - }, - "deadfc79f2a722dbf1c1a92f2824da8874189fea": { - "balance": "98905944986000000000" - }, - "decf1af47e153f6f3749a1b7abadefdcf1607a0f": { - "balance": "529000000000000000000" - }, - "dede5fa984f0def639d5b633f54c60fc5aaa272a": { - "balance": "8193771708654000000000" - }, - "df23607c63b3fd4b5fde6aab093c0c56d1188f95": { - "balance": "14687379916000000000" - }, - "df5b74bf02902e4c466821de798406b663d4d73e": { - "balance": "9000000000000000000" - }, - "df6402ee3f37389e7f65720561b54e26e5f1cbaf": { - "balance": "358266132937000000000" - }, - "df83ea5b770d5abeccac7f0cae803e8bd7b9831d": { - "balance": "25000000000000000000" - }, - "df92802ffe9892c7704875755bdec648914430e6": { - "balance": "20000000000000000000000" - }, - "dfa108bcd80e824a255679a38b2450d428e2f939": { - "balance": "489209553654000000000" - }, - "dfa9f18e859353796afe384d05353dc80b3ffc43": { - "balance": "121000000000000000000" - }, - "dfb0d6580f011e68a39d7727818b0890e70f3036": { - "balance": "537675412560000000000" - }, - "dfdf006abf2293aadc58feea6af6b35db428675e": { - "balance": "9000000000000000000" - }, - "dfdf2ba93bd47d7243b7419413458a947effcf67": { - "balance": "45080282196110000000000" - }, - "dff01277ac23a8cf93383595a80a7c070eafe5c6": { - "balance": "312778552103000000000" - }, - "e0450154c441e52c5e507e8316d4e9376c59c12b": { - "balance": "170163401434000000000" - }, - "e059374d6a7e6c63e609b65642272869fa3b2b3c": { - "balance": "300122497803000000000" - }, - "e0c0d8e739a2f274a43f019a07f7f61d7d8e11a7": { - "balance": "2630310240000000000" - }, - "e0e779e4e3573ea77096daec252ac2b3f1c0013a": { - "balance": "10000000000000000000000" - }, - "e1325eb586180a67873718a2016172afeb03c6a5": { - "balance": "531691399657000000000" - }, - "e13958af480da6443b9ec1067f0f33440634a282": { - "balance": "10000000000000000000000" - }, - "e142daac753b2c4d215372797999e9c88b65dfc9": { - "balance": "585813299366000000000" - }, - "e142ea343bc36ec49989fd43ad5c403c70a40dbe": { - "balance": "656734902975000000000" - }, - "e14d0a3d259db6bfec2fc4ef6e18729e4d93b007": { - "balance": "210234446279000000000" - }, - "e16a5316e3a113f27bafdf3d4fe44fe30ae9c210": { - "balance": "16000000000000000000" - }, - "e1770944aec145a96c9491497eacf7f3fb03c1b2": { - "balance": "335417250470000000000" - }, - "e199ac237661dcac0a4cfab404876abde72ee209": { - "balance": "340000000000000000000" - }, - "e1ad427471023f38cbdf07fdca3728ec343810c4": { - "balance": "343957267368000000000" - }, - "e1ae0223cecd738c8e530a0007ef05e8f3b33769": { - "balance": "950528515289000000000" - }, - "e1d2d4ef39f01a60c3bb5d671af91c5298d87711": { - "balance": "121000000000000000000" - }, - "e1d4a8888cbb383f3671ca96e7b55310b59a2541": { - "balance": "242387826125000000000" - }, - "e1da9039ddfe117e6a0b484fd3962426c112871c": { - "balance": "3710499693813000000000" - }, - "e1da9f16d57c601af8b6d102323c20408af8531a": { - "balance": "3135322588771000000000" - }, - "e1e1c163f391ffad2d0be68641253b0860485a95": { - "balance": "10000000000000000000000" - }, - "e1ec6361df67ad915df9e9661cd0932186db034a": { - "balance": "4279936304854000000000" - }, - "e224050bcd723e63f1fc0567a86942546aaf8d13": { - "balance": "12007628539000000000" - }, - "e2342c7f411d7ca3a86484af59a9c3f3180e2f0f": { - "balance": "16000000000000000000" - }, - "e26f2b026a258ce5801c90bb8fd6f7a152b8d267": { - "balance": "304593714834000000000" - }, - "e2717eb5fd0a1da51272b50ca8d12858009c7016": { - "balance": "506943817535000000000" - }, - "e27546d5620e6398829260e58e8cf4a3a03f4164": { - "balance": "3000000000000000000000" - }, - "e2762bb64e0606a5d635032e15164b01f612a74f": { - "balance": "884716158811000000000" - }, - "e2882066ed0a3c041d09c00c8532850fc42eac06": { - "balance": "42441412728970000000000" - }, - "e294c5d64daf7b7c0994aa9d03669c4b2658c9cf": { - "balance": "6996693830997000000000" - }, - "e2b179f0ed6870a6268aea64b0c7b39d98d97fcf": { - "balance": "334205318353000000000" - }, - "e2d1f6f7e3128340b789565b527bb91de96d54bf": { - "balance": "100000000000000000000" - }, - "e2f136d3693aa0b2346a968a22aca6707fc1d0e5": { - "balance": "10000000000000000000000" - }, - "e2f229054293e32cf3e83f9bb88d9cf1d6acd66b": { - "balance": "20000000000000000000000" - }, - "e33b8f4c9a49554c8b134861f88c8fffc399e456": { - "balance": "83552502198000000000" - }, - "e33cfc7727b1460324b34277dde14cc49bcb273d": { - "balance": "100000000000000000" - }, - "e36af9bfed4f912cae21f3d899f7354e1c902601": { - "balance": "31474316356000000000" - }, - "e36eff7c061dec48446d47675f176b4da3c2e950": { - "balance": "10000000000000000000000" - }, - "e383f3cf431f3cf645f26c7d5e5e2f77348ede6f": { - "balance": "776224304171000000000" - }, - "e398b9f004a4f891cf871a57d9124a97b56e89e9": { - "balance": "84846187740000000000" - }, - "e39ab2415144b46db522e92ed51b8089a5ec01fd": { - "balance": "4158925896363000000000" - }, - "e3aa7ac7e15e9a8a6f54565067234a9d4bf7b569": { - "balance": "1080385576951000000000" - }, - "e3ec5ebd3e822c972d802a0ee4e0ec080b8237ba": { - "balance": "2129139289000000000" - }, - "e3f1fbff8686af23ab95eeeee6a6a03782d72416": { - "balance": "401776848194000000000" - }, - "e4001b830fbd86df257ebab54aec0c66314ef9aa": { - "balance": "518220809325000000000" - }, - "e40790bff894f0b3e534942b5ad6f6592cd6e896": { - "balance": "25000000000000000000" - }, - "e409170a296e46fc96d85a2395e4324212a470ee": { - "balance": "1072528749756000000000" - }, - "e41546f68bbe1771febbdac2a4a5999eef50edf3": { - "balance": "1000000000000000000000000" - }, - "e425d63d711a9996c09d928ba8df94c88163aea9": { - "balance": "10000000000000000000000" - }, - "e4432ff1aee13f97f73a8407e4c7d6e768b8040b": { - "balance": "700508995102000000000" - }, - "e4690f5d024a395355a7cb5238fb7e0dc921b1e8": { - "balance": "1000000000000000000000000" - }, - "e4829684fb36f054766a61fb2a8f6ecdf27c9e87": { - "balance": "73885178137000000000" - }, - "e48a68e1ac007e14ac08c1b3b0df2b5602081ec2": { - "balance": "1389262869176000000000" - }, - "e4d699b3f4117eba7ed27b323048c9ffcb46ed42": { - "balance": "183131036697000000000" - }, - "e4db688c29fdf9a1c16114f99797d8409545955f": { - "balance": "16000000000000000000" - }, - "e535b94d370190d1e0955d3c0d12480e558f00dd": { - "balance": "20000000000000000000000" - }, - "e53966d4bb17fa9b50d29b44ddf3951c9ca67caa": { - "balance": "6400630678000000000" - }, - "e56f2656fdd1a5f7d3716e65dd89a37dd6e42dcc": { - "balance": "1000000000000000000" - }, - "e5a364113076273352e0c31bf505028e0b7edbaa": { - "balance": "10000000000000000000000" - }, - "e5a3c80518fab6a0a721ccbdc3e673680a65f6de": { - "balance": "171727917465000000000" - }, - "e5c71c7170e5c9b07e62cc307d81a4a3053ed64c": { - "balance": "10000000000000000000000" - }, - "e5fb6408db128c55cfb3e7fa1942d6347e34932c": { - "balance": "10000000000000000000" - }, - "e606883236f8b2045393c574153a100675cd4b90": { - "balance": "14005226900000000000" - }, - "e61869d1cf72f25e195898217f5bf5bcec9c9038": { - "balance": "50000000000000000000000" - }, - "e61e2e29c0719457ab1bf7d6d9fe442bd6107b07": { - "balance": "30943034333100000000000" - }, - "e61eb97093e9ee609647bd55f434a27bb30a9401": { - "balance": "200951434577471000000000" - }, - "e62812ad5834747f17c92435d863639e84d132fc": { - "balance": "3017271391299000000000" - }, - "e630b92aa8443eb077e1f6990a2e194d99cf53ec": { - "balance": "1000000000000000000000000" - }, - "e656fd1641c15e1a4b753be41bc4aa438b44b42c": { - "balance": "26972744083000000000" - }, - "e663f0257b98dfa80602a2af1bea1f901c4a7612": { - "balance": "97075813547000000000" - }, - "e66e411a8a9d019b53bf2e0a7e44703e1aa93ac1": { - "balance": "25000000000000000000" - }, - "e6712675d13fff27af43bb1cb3f2f283755bacf5": { - "balance": "227572496234000000000" - }, - "e68e8f04b2cff484da2d41dd639ae8880920f781": { - "balance": "20000000000000000000000" - }, - "e6972b5d7e0fe8c722dec9146b92f89291a0207a": { - "balance": "2115924954211000000000" - }, - "e698b491330cb55ecc4cc4b74015cd94eb927fc4": { - "balance": "1038111785278000000000" - }, - "e6c411e67b90109dbb0fa75f0f07ae8a504e9637": { - "balance": "123792105420000000000" - }, - "e6fb1dabc624edb45b040ad66f30dae010a6b634": { - "balance": "16076893670852000000000" - }, - "e71dac161206e7d3686d13b98fd922ab73587988": { - "balance": "500000000000000000000000" - }, - "e773f9be9b3f4b35ac149b4d759b9e47c8000bdb": { - "balance": "329623043336000000000" - }, - "e781cbbd2dccfdf68595d54fa44104a80d52dd22": { - "balance": "188679476509000000000" - }, - "e793666c7850a409b1d5494f576d122e85cfed9c": { - "balance": "1141845197779000000000" - }, - "e7a5527c6deb922e9f84309c502048f49f0c8f14": { - "balance": "81415566708000000000" - }, - "e7b0f75f9c69ae464b1b63cf295555d0815fc532": { - "balance": "10000000000000000000000" - }, - "e7b43cc673e321e607190a6fde996b71508f4d81": { - "balance": "103958781426000000000" - }, - "e7bfcf3125e37755e57804dfe4479657b212a8ca": { - "balance": "10000000000000000000000" - }, - "e7d33cbbd4eb38365c5be04ce32658a5ac741cfa": { - "balance": "1545192252109000000000" - }, - "e84cfbd7844f6aa3e830258a6b1069b6a7ff5b7e": { - "balance": "543989509107945000000000" - }, - "e8aa0cbc5c1f59fadf3ec122fa8a59ebfc60b5b6": { - "balance": "61271973066000000000" - }, - "e8adb5303c30a8ee044dc09c49818c02a16f4254": { - "balance": "737375689166000000000" - }, - "e8aeef5114e19d467c3064938c5965d04830f2ae": { - "balance": "51130466380000000000" - }, - "e8b5a83497198a513fb2e244bcf05f9d4cf09d62": { - "balance": "10000000000000000000000" - }, - "e8b6818cf0d24bd0e7ded854b3d368662a150dab": { - "balance": "63697741112000000000" - }, - "e8b68b9cb24169fd688db7a626d79d0363777c75": { - "balance": "427222669643000000000" - }, - "e8b8b57b23ea953943da3ef7efaefced9cdbb44c": { - "balance": "16000000000000000000" - }, - "e8f85dca364d26c2149b767904c6c06249c3d88a": { - "balance": "199342917246000000000" - }, - "e916c7801cdcf1b6cf640fcd9dcc1e3148c80105": { - "balance": "9000756000000000000" - }, - "e93cbef13277324caae7816c3d601e2f6bb42589": { - "balance": "121000000000000000000" - }, - "e9415fedcdf8939b551999900128530195a2a5f0": { - "balance": "85165078941891000000000" - }, - "e9a79ade714ce48a07fe88532a20d8f8ed27bac9": { - "balance": "30768493367842000000000" - }, - "e9b35c7ca775661bbd3a4844e2c6bc5effcdea58": { - "balance": "134719523000000000" - }, - "e9b819dffb600373bfd1b1608fc9744cc9167855": { - "balance": "1537634693002000000000" - }, - "e9c5ef50d4a194e53928659b4486a1c456df9e56": { - "balance": "50000000000000000000000" - }, - "e9e21f4523b11567516f6fc525e8967ac707f988": { - "balance": "2498740681000000000" - }, - "ea02821d6c730e061a9947b75188eb8bc0bbf9f1": { - "balance": "12822292582000000000" - }, - "ea3bca3a17c7e724ac0e15acab6442f222cd8688": { - "balance": "2789689549000000000" - }, - "ea4f7923d7045a148d50153f5f4620dbd31a74da": { - "balance": "113595858930000000000" - }, - "ea6d4cbae3cfe49ffd36653bb0d64c01b2bbc0b8": { - "balance": "49325017701000000000" - }, - "ea76cd4cff825301932a5c1d3a1de55a0ff00797": { - "balance": "1282028021000000000" - }, - "ea8e4c8c6500856777e2b41832ff00443db291ce": { - "balance": "553674550359000000000" - }, - "eab52191e5afc804b8685fe13d7ad6f5dc64fc12": { - "balance": "244412435341000000000" - }, - "eac1b0868b710e40d6d5c66a461dfc8f78abbaa9": { - "balance": "10000000000000000000000" - }, - "eacac2c75920b8f6e65f37ad81deb113d526d031": { - "balance": "53028042076000000000" - }, - "eacc9ef8b534143560f420031a8a7f030ff1a36e": { - "balance": "381111853842000000000" - }, - "eaf2cc9fdfe6272de269f32486b2d4c248a05afe": { - "balance": "2793234915237000000000" - }, - "eb0220406832a8a5d4f242538e82c80bd83d0ac6": { - "balance": "10000000000000000000000" - }, - "eb20efc0e0af48c8e6da4b21efa9c9f02d92d29f": { - "balance": "152958793764000000000" - }, - "eb41bce8e3aac2bcf662854a3151e3c83d98c6f3": { - "balance": "219455327737000000000" - }, - "eb44c591306972c29a7084079720d8ee5fb9b0a1": { - "balance": "49000000000000000000" - }, - "eb4b26ab55dc35df2e78d47a90fc43148a6de881": { - "balance": "12139574483030000000000" - }, - "eb4f53510db5edcaad6ea169e521bd094e8da4b1": { - "balance": "100000000000000000" - }, - "eb4fbfb7c0082aa0e7edaed934c5166fee955e5b": { - "balance": "299713748180000000000" - }, - "eb6067ab544af6289a73111e7693dc449d5c2134": { - "balance": "20000000000000000000" - }, - "eb86fea82d10d309b1365237e4855a48684e0e49": { - "balance": "81510415589000000000" - }, - "eb8abbcadeb6e19ab4392cded7a407c8d5df2d5c": { - "balance": "25000000000000000000" - }, - "eba44ca2d6f36df8221a2021bf0644cf6cb59452": { - "balance": "500000000000000000000000" - }, - "ebacbc0eace170f66415df48f74d98eb31828d15": { - "balance": "19046465915296000000000" - }, - "ebc72fb8a1029139d8abdc08da23dc559f87e1a8": { - "balance": "24177703742991000000000" - }, - "ebd561bb9001991cb6b02c8ff9e7ece8a3d73dde": { - "balance": "6684606759000000000" - }, - "ebe1dc3ee857ae4add6fa6636b678af8451d1701": { - "balance": "1485349608007000000000" - }, - "ebe68dc904c737be83aa2ee7f613dd51a6d436e4": { - "balance": "11206782120918000000000" - }, - "ebecf4db55a99f018bf136173ae823528f211380": { - "balance": "191817711082000000000" - }, - "ec15ad0aafe0c0f18089de50b2397509e15a20de": { - "balance": "20000000000000000000000" - }, - "ec2e56973a6cbd8b37d0294b16ef806ab5943ec7": { - "balance": "12031630315394000000000" - }, - "ec432a6a4685ebf6c1e872001d1de246140c8d98": { - "balance": "280056522277000000000" - }, - "ec866ba1bdadb91ca25f5ae035b0f69421ed4377": { - "balance": "431849961155000000000" - }, - "ec9be854224d3d371b79ffc1230fe704ba03be2b": { - "balance": "3692428502391000000000" - }, - "ecc2d6e129c7daa37a93f559c6d4f575171d8386": { - "balance": "20000000000000000000000" - }, - "ecc3aca2a21cb317c5b9debdcb2090f3931d5cd7": { - "balance": "100000000000000000000000" - }, - "eccc9a49ff40aa4b07aa0e1271cfb6713de683dd": { - "balance": "617207728367000000000" - }, - "ecccf24530629033fd6234ae32bde2052ebaa640": { - "balance": "16000000000000000000" - }, - "ed16770d5a56dced87224d4ff68a361a2285fef2": { - "balance": "10000000000000000000000" - }, - "ed23b8e782d5ddf203f9b80e5df83ec32e484fc6": { - "balance": "5000000000000000000" - }, - "ed3244e4168e669ae9d54175173c3f0f0e7c4c7a": { - "balance": "803397672115000000000" - }, - "ed48f39d3f022b321c0864d4955e1cdc8cf54834": { - "balance": "64000000000000000000" - }, - "ed4cb42fa6737cbbbf095f181e1425b3bc3ab4f6": { - "balance": "8974148344000000000" - }, - "ed560f7d83c27a26965f84dcface3930bc447fc5": { - "balance": "2092287996000000000" - }, - "ed6ace91369ec3b06cce474e67d1ce4aba6475a6": { - "balance": "1227081000000000000" - }, - "ed8249dd4a91f70176ffff310e5546e7e0c30b91": { - "balance": "813069034369000000000" - }, - "ed8987fa3d4d42bb8f009c99cda5868633d94f5a": { - "balance": "174952234860000000000" - }, - "ed99b72a58a519ca7aa8f46b8d254c3f1eeea0d6": { - "balance": "10000000000000000000000" - }, - "edb720c9bde4801e204e90282de2a6cf1c44c4ad": { - "balance": "10000000000000000000000" - }, - "edbea23cd0cfde3705d83aada88e78b9f4bb1a50": { - "balance": "4000000000000000000000" - }, - "edc1f174655205bb961ddf94a997cdfd24f1c2ed": { - "balance": "65211537189000000000" - }, - "edd1d2dcba881202bc546943194d64e59bf74bfd": { - "balance": "10000000000000000000000" - }, - "eded28fbd959f2351b4252abc71f0e809562fd4c": { - "balance": "1000000000000000000" - }, - "edfe4d4c83c7db76e5e8a9ccafa34d9841669dac": { - "balance": "2578239411258000000000" - }, - "ee1ef79de869b89334d883ba766e65150f3f6cf5": { - "balance": "779780646165000000000" - }, - "ee27b2da240e862f0848d31116a7b4ed91835c8d": { - "balance": "111637484977461000000000" - }, - "ee3195bdb69e97796911c63fdd3fcebad61ffe9b": { - "balance": "214483035823000000000" - }, - "ee43306530c21793c4fd6039b51cf54fbc912bf0": { - "balance": "374531713769000000000" - }, - "ee4515e30ee1b8dba4779ef213d89e8dfff26ea6": { - "balance": "1166743135013000000000" - }, - "ee591e9ca7948b8485eb210e2a3f706b97e6f9e2": { - "balance": "27793157052774000000000" - }, - "ee5ba6c854d633a04f7656d311817e5104c6de14": { - "balance": "289361919166000000000" - }, - "ee909db4ee48bff3adb9e43db940245a8e5e094d": { - "balance": "582143490064000000000" - }, - "ee94d1afa82de70eb65aad0662f48ef3170495cb": { - "balance": "242490158636000000000" - }, - "ee97e18e09bbb16137a7b4aaae464e97d70e6606": { - "balance": "442709862861000000000" - }, - "eebe957af00050c2841f3ef8768c6a77a5394012": { - "balance": "9000000000000000000" - }, - "eec052f4e2902f7cc496162ca6525997d2b3ede4": { - "balance": "69349303517000000000" - }, - "eed30e1a939d5f0b4a39598967a5f149a7b7cb8c": { - "balance": "1637195595000000000" - }, - "eed7bf1ba39bfdad0ce1b6b8d4c9bb31dc1a9843": { - "balance": "203331701702000000000" - }, - "eee276140ea24e36eccb4fd748f675df1acd3b73": { - "balance": "1000000000000000000000000" - }, - "eefb33b290741c4cded862cea777efe4b14a76da": { - "balance": "64000000000000000000" - }, - "ef17a60d15ecf68a62b4bfd5e3acd6201e1931af": { - "balance": "113292502078000000000" - }, - "ef3f4df42127d3e94b4b5883ca97ee63f90b68b5": { - "balance": "17819622000000000000" - }, - "ef4aa6833a69cf72fbf3eaac57da236970aa4241": { - "balance": "1638520372091000000000" - }, - "ef958a1db06e5b8e12547148f3b01da9a8841aad": { - "balance": "12847752197000000000" - }, - "ef9fa861eefe12a3b4c161a47db5d94b1fa873a9": { - "balance": "49000000000000000000" - }, - "efd9b1ce6bc3932961e41e875edaaa367d318b36": { - "balance": "1626378762077000000000" - }, - "efdce7f577c77f0dac6afc78dcbf5ebadc1c3a73": { - "balance": "627500067619000000000" - }, - "eff3f26bc45638d89f28b3ea7a5471af0b680b72": { - "balance": "1650959950189000000000" - }, - "eff6d78814ddae79d6d09d830dd44de55f3f919d": { - "balance": "44409266093000000000" - }, - "eff739e22b9aeb3781dc301da70761fdd178f08f": { - "balance": "574842224234000000000" - }, - "f0059b3c8a32d3d012b4fcb993431a484b67762f": { - "balance": "516933429840000000000" - }, - "f06747d8e2c76b8827bbd0bf4ea3a68d390ee8f3": { - "balance": "8124594790100000000000" - }, - "f0e29fc0aecc36d1bdd818148878ea7d01957476": { - "balance": "79821431871000000000" - }, - "f0e42acf4e027aa61ac2f56e3d2c171ec0fd6ebf": { - "balance": "672499252575000000000" - }, - "f14338307bc5e6ab71fa202447ce240947568b3c": { - "balance": "13990001528784000000000" - }, - "f14f9a1206eb436a3d2e4ba9b3976137f67a6596": { - "balance": "1086707451000000000" - }, - "f15fcf1772fa5b2a578ce4f9270996430d533000": { - "balance": "496026996898000000000" - }, - "f18c691a5827ff1fdc44b54bd9a64fabd53c1cf4": { - "balance": "3112912699000000000000" - }, - "f1960640b52af75fc71101aec2611499c17cd9c6": { - "balance": "195957678178000000000" - }, - "f1abf01ddd474949713bd7fa67ec81d6b56c87b7": { - "balance": "121000000000000000000" - }, - "f1b93a6cfd4b1c7e0e89ebed119c5fe55af2035e": { - "balance": "1000000000000000000000000" - }, - "f1d14c7659a10ff38f4ea74ff5b07ac035984b6a": { - "balance": "9986323720000000000" - }, - "f1dbf37470a2c4fef98b1023026870ae8f7df2c0": { - "balance": "132757602000000000000" - }, - "f220b958b619d5d848597dd00824ab8b1401ebd2": { - "balance": "1461699635849000000000" - }, - "f2484911e0aa707f88d9dd970db21e8f24b9de2f": { - "balance": "20000000000000000000000" - }, - "f264c15790fd7a36d9ce7a454f6bfbe878708a50": { - "balance": "64000000000000000000" - }, - "f2662356cb3ae7b82efd6c82c3591ee40854892b": { - "balance": "50000000000000000000000" - }, - "f27ae5783b96ef637bde4179080a8f5af63ae692": { - "balance": "784985848611000000000" - }, - "f2a62fc212717e411f72f9a694e30b8da21bb31b": { - "balance": "614971541702000000000" - }, - "f2d0a9594231efb87ac833c365b80944251f29d7": { - "balance": "478622654587000000000" - }, - "f2df99a3df0b9b448d0ea48b9fd5cb1ce9ce50cf": { - "balance": "851116673037000000000" - }, - "f2dff0ae1f5f74808624e4f26fa814e4e19c216a": { - "balance": "404457730686000000000" - }, - "f2ea1ac6282364ad5904c6f058827a4382111d94": { - "balance": "5502482915000000000" - }, - "f2fafdcdb2d887eb13b5362eb76be2a682868643": { - "balance": "6174264174000000000" - }, - "f314adfc2fbf632a6e5d8a261385b6054aca31b6": { - "balance": "1267558242119000000000" - }, - "f31a66a88394ed7dd6609aff07dd26a60a219bd8": { - "balance": "346102834465000000000" - }, - "f3535f2b42d8613363e6d9717cc21a8ec3a74fe0": { - "balance": "35723093185103000000000" - }, - "f36a149466982c030ce3b9717f34b593613804d5": { - "balance": "10000000000000000000000" - }, - "f3828b0eaba4acfbbcf3c58277ceb4616a34b630": { - "balance": "633998941064000000000" - }, - "f38f767eeb8002ef051b32fe2f40193bf0751d92": { - "balance": "50000000000000000000000" - }, - "f39bce177817a7338b1adaf713222e515c0d762b": { - "balance": "1128231726329000000000" - }, - "f3ac7ea27a1cefc7787e5ba54dacfd8385ee4afc": { - "balance": "11364602682758000000000" - }, - "f3d9ea511335ed418b1837766da11832aedf5578": { - "balance": "29188596603509000000000" - }, - "f3ef05ccd19df167e06797d962f6afe16037e134": { - "balance": "144000000000000000000" - }, - "f3f630148eccea0ad7bd67bb806bd5676a4ea4cb": { - "balance": "87187208643000000000" - }, - "f3ff31784e0b8c3cd2f7e18cfd07c682a42d1c8d": { - "balance": "10515373125000000000" - }, - "f40b976e8519a2c97f64783bca495ed3f2e4a7c0": { - "balance": "780184503985000000000" - }, - "f416a3af7f3181ad9c8a916989949d35b0b636ec": { - "balance": "16114504005275000000000" - }, - "f419759927eea6afe77701c4cf4a98791a709ad1": { - "balance": "1032589347112000000000" - }, - "f4368f9c9ad8236b56413f174562d6b6fef21d1c": { - "balance": "5447645343000000000" - }, - "f43c57f984b0e2b7ce4d703e82f41195585504a4": { - "balance": "1135809111749000000000" - }, - "f4449f52895de96a4638c927dc389f010bbd530c": { - "balance": "693196063498000000000" - }, - "f449bd417a674c8bfa1db3a3e09c2b03da0f0c04": { - "balance": "106343287319000000000" - }, - "f44dec8340986c06d64dc98d78772a8a9cdc41ec": { - "balance": "1379381904815000000000" - }, - "f4642be1a7685aea0dc7b362d36f58f15d806b72": { - "balance": "4717509847323000000000" - }, - "f4712925f57391043e0cc2e671f33124a0bc8613": { - "balance": "419736833200000000000" - }, - "f47317fba5927dd8dffc4049d4f3277fcef503d6": { - "balance": "149279442682000000000" - }, - "f47ce4c5aaef82692e47f7a810ba38d1faec0eea": { - "balance": "10000000000000000000000" - }, - "f491ffc412bf142788bb82d48bd4eccbe9e0a286": { - "balance": "77276422315000000000" - }, - "f4a1e27e669c29f15b9f89ac15f702340a135743": { - "balance": "324000000000000000000" - }, - "f4b5cbfa50a6c4f5f7db7a93fa565362cc7aceac": { - "balance": "195951823248000000000" - }, - "f4b949c6e10615b651675016f0d7d6ff64e31aee": { - "balance": "35516207325223000000000" - }, - "f4c5e2f043ef3548a2c1c27d968087bec65e2f7d": { - "balance": "100000000000000000000000" - }, - "f4c79ea9c6f7297e016c39296d86f0304070c31d": { - "balance": "71036374423000000000" - }, - "f4dde3733a72872a7efc095cb412672c50928f1b": { - "balance": "129914864759880000000000" - }, - "f4ed736a413464eb93f8a430e093a64f0bd4222d": { - "balance": "10000000000000000000000" - }, - "f4f07e45560fb63d5207ed7e8d7cf4fe29e06d18": { - "balance": "293103814503448000000000" - }, - "f50eac35eef0a1bfa23ba31020ef60e89bf8e9df": { - "balance": "10000000000000000000000" - }, - "f51236dfd888929ccb2fe1f1fc5554abc5df4ce2": { - "balance": "25000000000000000000" - }, - "f521eb42e9092350f2ad4391ddb42bfe7abb4db9": { - "balance": "217462745186000000000" - }, - "f54e7062b6a9a8b283acf00fcbad58aca0737676": { - "balance": "7327357122437000000000" - }, - "f553301efd81629d0856d9c95c70f4a962e602ed": { - "balance": "1500355826530000000000" - }, - "f55c555b0991b2413f2f2764d8ed6a0d77825965": { - "balance": "1174679810163000000000" - }, - "f56ff110d521ceaec29dbf2842f1e78b24463cea": { - "balance": "20000000000000000000000" - }, - "f573fec366236ab87ba041f7dc6a88d92b1fc9b7": { - "balance": "4659857040000000000" - }, - "f59987743b239379aac9353e17e0e4442aa2c684": { - "balance": "25000000000000000000" - }, - "f5a9ca298e88c5492dd44a66d815b649c2f01d39": { - "balance": "95879585325000000000" - }, - "f5b4933164c55b5ba99db906ecaa52bba4f95164": { - "balance": "25663623936000000000" - }, - "f5d20af68c6fed98144718b6beab82fde00dfedc": { - "balance": "16000000000000000000" - }, - "f5e49ce72be9b17ff39688860e5cf6fd500a886c": { - "balance": "106142276914000000000" - }, - "f5f472405a4530075805fbc11928544770fd61fe": { - "balance": "64000000000000000000" - }, - "f62096c7305eb97b221bb637f4269246fe59262b": { - "balance": "855993602798000000000" - }, - "f622bf9b8f7be2f75d5ed73d318a0e7fa62a587f": { - "balance": "20000000000000000000000" - }, - "f6231f31d524ccc444bd046123ba33bc224bdd52": { - "balance": "97550810879000000000" - }, - "f641b4a721dcefa497274fd06888eb998b9bc038": { - "balance": "39401014566340000000000" - }, - "f64f0c5172c99d74b2450a4685c3ec715b379922": { - "balance": "28337413668000000000" - }, - "f65841061cd55cbf20843d9594bce9ee133aa644": { - "balance": "9064540188290000000000" - }, - "f65f0106f3d148d0660547f0683ded4dffc12fe9": { - "balance": "87334071785367000000000" - }, - "f677961296ed933db9e1dd887711387540c0436d": { - "balance": "3982789899000000000" - }, - "f68ba7530f423b8df1625cee36f8df2363a57c49": { - "balance": "5000000000000000000000" - }, - "f69c6eaf077b795f19a9590ee8b578543558e4c4": { - "balance": "10000000000000000000000" - }, - "f69dfe3f0f76e50e2850e44e9e36b6966e277eaa": { - "balance": "288231750575462000000000" - }, - "f6a73c4b958b4d6044f3f4da7147d0fa80e2ea31": { - "balance": "50000000000000000000000" - }, - "f6b0864be5f7bbc4210a3420aa3ead614a8fe7e2": { - "balance": "880968828000000000" - }, - "f6f43a6d9517471436d2ce5047a2b707580e7149": { - "balance": "20000000000000000000000" - }, - "f6fb414d1ca7c29be35b5f97096c817bbf70b070": { - "balance": "15156317416682000000000" - }, - "f707b491ac27b2d2e5e1f9d4123635ee0af92c5c": { - "balance": "500000000000000000000000" - }, - "f71179583a471767a1b399842d7d29caefe57a5e": { - "balance": "429648186876000000000" - }, - "f71ed909eca6bfd574cd670389bc9250493d686d": { - "balance": "38189267531000000000" - }, - "f72ccdc70b7878cdb94f42ee72ca5b4b35a46238": { - "balance": "86065647347000000000" - }, - "f74035e85dbfdb961037bf689ee7dfdcfaf32d64": { - "balance": "398451682882000000000" - }, - "f77668db085a87b0a0405a275e1c2516d3e02b66": { - "balance": "10000000000000000000000" - }, - "f78990d9e50876b49f933e9d74bda44197e9aa7d": { - "balance": "51984216556000000000" - }, - "f79b9df28b7d94d1b4491fca1cbe50bd36aedb3a": { - "balance": "11546152485156000000000" - }, - "f7c773b89be413848dc4a96f064693a0c3a2eab0": { - "balance": "7084247258755000000000" - }, - "f7e29c20bb0023e9ae079da589346fdfd960dae3": { - "balance": "93132014782000000000" - }, - "f8124428ea619d30a335ecc4c2f64e36500abdcb": { - "balance": "8838170798391000000000" - }, - "f843c9d70226e6c2c8cd4cef78e2db66a8eac027": { - "balance": "498377670361000000000" - }, - "f84bb3c0d872dcdbe99d6abcc57c6b5c2b2e35ad": { - "balance": "1405105232436000000000" - }, - "f8679b915ae94e4668f2e27d1094cbb2d97cf428": { - "balance": "1000000000000000000" - }, - "f86dbb82c634cdfa818e4d0dbcfcc9a5c47a9ddb": { - "balance": "196000000000000000000" - }, - "f88bad7726aa66bc1d0ca5824044072f3551fd15": { - "balance": "37432374800000000000" - }, - "f8ab07d0751a2c283ebe2a7e28c5b6e57867e1d1": { - "balance": "25000000000000000000" - }, - "f8afb4f5684c56ff7ce71b4e4cf7e42062470e08": { - "balance": "10000000000000000000000" - }, - "f8c28df0d1a0982289ddfa2a6d562e5c75a5dd01": { - "balance": "1447386977682000000000" - }, - "f8cca137f9c12b48eafd43f038e55e2d3c481919": { - "balance": "35370515421000000000" - }, - "f8e50d1816a5e5c649756ae208209b03b1ece0c3": { - "balance": "48449640035000000000" - }, - "f8fb33ba1d93112d9c3672806e0939083f09a88e": { - "balance": "419743187776000000000" - }, - "f903bebfcc6a7050fc2c5bd14248af9b300f1600": { - "balance": "473363252199000000000" - }, - "f90ab9078f26dd881fb054b4b6e3b3e17fa94718": { - "balance": "156449634345000000000" - }, - "f93e3f392efc057f0af3a91416858a515c1ed996": { - "balance": "1147663044625000000000" - }, - "f94eac538ca66931869c312acb67721c4337842f": { - "balance": "368103335377000000000" - }, - "f94fda503c3f792491fa77b3702fd465f028810d": { - "balance": "317241487661000000000" - }, - "f95dcedbefee8ed01086c91d91a4c115ad8fc947": { - "balance": "147059838786000000000" - }, - "f961a293bbce366a6fcc98d2ba0342e2ef3c5519": { - "balance": "10000000000000000000000" - }, - "f966fdbc4a42f055f8f52d31c23ad7b6a07a5e22": { - "balance": "10000000000000000000000" - }, - "f9a3a61a2f1469835240bb0641eae40c07451e30": { - "balance": "218000000000000" - }, - "f9adcf232180378b08a46d6c8d9d97f01802e01b": { - "balance": "15658216517944000000000" - }, - "f9c68991ff7ac307e41ea1c673f8ebb1a6afbd99": { - "balance": "10000000000000000000000" - }, - "f9cc0c60431d7bdb0c7581a9ae7f011b0abefeb1": { - "balance": "16000000000000000000" - }, - "f9d43c329b61ca2169600e45c8fad3c94226adb8": { - "balance": "120128558137000000000" - }, - "f9ef5d4e2ca8888216b939d3d938438a34dd9da2": { - "balance": "144000000000000000000" - }, - "f9f3d14cd3bd09e2c4c89035b4f50e93f6175cef": { - "balance": "725000000000000000000" - }, - "fa0f5a03601bd1fc76865cdd69d9671ba6073592": { - "balance": "225298289139000000000" - }, - "fa12f10db0eb552b719194becef20af9f45de8db": { - "balance": "1012484659496000000000" - }, - "fa146c58a0709951bc2e9bccddcd002c5a0bb7dd": { - "balance": "199563276701000000000" - }, - "fa159185c156f35fa450b77c48846c2dab6349b7": { - "balance": "100660066567000000000" - }, - "fa193312655f79c7b0ee7d7ef904486836180026": { - "balance": "48141690266000000000" - }, - "fa2484de744918bd8c91350fbabc0dab8b8a44f0": { - "balance": "36000000000000000000" - }, - "fa36dc463b026d8edfeb8ac4acac43a51d643457": { - "balance": "9608761064478000000000" - }, - "fa84199010be2bf53e803c23771e0d15fd025386": { - "balance": "1474902394742000000000" - }, - "fa958bbfa367a745bcd0904db2c4e30445edaefb": { - "balance": "175679888121000000000" - }, - "fa98bcaeb55285ad7ead12ccaa15cf488f567ede": { - "balance": "136105143781000000000" - }, - "faa1be631da42b41a026774f4166c1b831ef41e9": { - "balance": "86358861589000000000" - }, - "faaa857e7f149968434f313ab8db596e1b0ae75d": { - "balance": "36000000000000000000" - }, - "fac2b85ab274055cf1415d57394e8aca4541857d": { - "balance": "289000000000000000000" - }, - "fb23a508ccdb4e91b252f5c06c465c55ed59b1db": { - "balance": "14698710175236000000000" - }, - "fb24d4e47ba70aa4b984372b4852ad3d082daa24": { - "balance": "4526648424830000000000" - }, - "fb27a7e8b8b4ae43c69ce025b46187e538608769": { - "balance": "121000000000000000000" - }, - "fb2cdb5e85872f52c99985f219b8fb4125c6a8b7": { - "balance": "8568367153000000000" - }, - "fb3d76c8165bcb3c93fd3b2b10c20588d0fa97aa": { - "balance": "500000000000000000000000" - }, - "fb5161b2cc9d48a53f47d66002905f0458e3cd9e": { - "balance": "225000000000000000000" - }, - "fb72756c4845f18ab35d29f632b662c0c0d4b94f": { - "balance": "883095068524000000000" - }, - "fb8b7efb02ea5292304c0f0abc8c555684653587": { - "balance": "10000000000000000000000" - }, - "fb9ee61e337a5c7b57c5140e84919101570e2cb7": { - "balance": "16000000000000000000" - }, - "fbae69f44b116c186a86cb0de79323ca3d6b99eb": { - "balance": "1359504686067000000000" - }, - "fbbd399eb9e5d3dd67efc48927973601dcd84321": { - "balance": "2049018637367000000000" - }, - "fbc9a3c3c429990cc306710b3dd44174dcc72ad4": { - "balance": "55507457947000000000" - }, - "fbce66a6898ecd70893db6b4b8c3d00afef8e20b": { - "balance": "20857164902458000000000" - }, - "fbe8fe04084fc93dff8228861fe100bfeeb057b6": { - "balance": "10000000000000000000000" - }, - "fbfb717f902ad79ef63565f9ab57f041ff5f7626": { - "balance": "16000000000000000000" - }, - "fc0b6c8c6be79bf0c9554f7855dc8c4a617d02c9": { - "balance": "17347593956000000000" - }, - "fc17518d05e605807847bbf6f407da89037bca00": { - "balance": "1796383702108000000000" - }, - "fc2793424c809cc80938a1be1292813adbc8ac8c": { - "balance": "10000000000000000000" - }, - "fc35930abb108ae6cae33fd065dfb799808ea326": { - "balance": "912737460000000000000" - }, - "fc5a9209799e563ae8d958774dc86345a3bc7ed2": { - "balance": "29049176573000000000" - }, - "fc8011850c09c9288e737ea58ca5c15cded6dc8d": { - "balance": "10000000000000000000000" - }, - "fc9183ed137be071ad183d025395a0ebe2674654": { - "balance": "500000000000000000000000" - }, - "fc98c9d88b1fbbb68dbdd6448aa6a32e8282800d": { - "balance": "900000000000000000000" - }, - "fc9f4b9da7a46c2bfcd50cafe1f892b9984be0ee": { - "balance": "21577116424370000000000" - }, - "fca525b732a673b953f1c23083c276cc8cbcb86c": { - "balance": "77653618624000000000" - }, - "fca57b6a4798f33478b6e23622173cda3fe1b9a0": { - "balance": "793368066098000000000" - }, - "fca79b446c513a7bed643603c42f35ff0fa89f49": { - "balance": "998082799053000000000" - }, - "fcab42f7f07735a7b09074c1f1769287069c88c8": { - "balance": "94824830574000000000" - }, - "fcacbbc6810c586522012ad32c3dfac80eb563b4": { - "balance": "10000000000000000000000" - }, - "fcb38809b63810b6673dcb4c947e01f7b49fb1b3": { - "balance": "725937240372000000000" - }, - "fcc0e531d9f6265672aa885af361534464a11015": { - "balance": "22121462657000000000" - }, - "fcc49c62d7738fa1b92aa6a69a12b671e4c7c8d9": { - "balance": "50000000000000000000000" - }, - "fcc95394fd796ca5bd8f3814883b1150d74dd9a5": { - "balance": "144000000000000000000" - }, - "fccdb068dfd599d7d5c290a6ae65eba9151d5b29": { - "balance": "5369426564000000000" - }, - "fcde41ae28bdf9084a28f47a9348d8aac5b3dd43": { - "balance": "409599263197000000000" - }, - "fce5816f066ca32d1fa02e9e8b5eb8a7fa3e4dea": { - "balance": "1193272309645000000000" - }, - "fcf9fb8996d6d9175ade6d6063be0742de20ea1f": { - "balance": "16852526239339000000000" - }, - "fd10488d55e6861cb67f7f50950d78892e7032ad": { - "balance": "165069902909000000000" - }, - "fd23e8263d89256add0dfe93da153d305ad917c7": { - "balance": "26633825496000000000" - }, - "fd3a98cc3b3f1439af35f806de2fb05fef98f279": { - "balance": "1043321187464000000000" - }, - "fd3d79185a91984a117ee6f9fd304725875094e2": { - "balance": "2349991833898000000000" - }, - "fd5e6ac22634f04ec4ace5da8996c2b7b70b22f4": { - "balance": "10000000000000000" - }, - "fd62ed1cf7a535c989fbd742b1660205a2f69dd0": { - "balance": "49000000000000000000" - }, - "fd645043bd4d7b71e63e30409b91e9fdda3a86c0": { - "balance": "362957768837969000000000" - }, - "fd7014fc1c70af482115247ff94ff6bdbd3d364d": { - "balance": "743383172317000000000" - }, - "fda0cfe95df9021497752b04863c3ec44d13e853": { - "balance": "15586809617955000000000" - }, - "fdb5b964808bcb974d3e888cbb45bcd57e57c907": { - "balance": "5549247772273000000000" - }, - "fdbaaa865ec38da13e80554b6d0abc437f60d8a5": { - "balance": "3736861227131000000000" - }, - "fdbb8693b3c20c0eac5fb585e2347d41debbffce": { - "balance": "100000000000000000" - }, - "fdbdaec57829f25ad48e18d94e0b8533f2801818": { - "balance": "6934630922926000000000" - }, - "fdc318ba5b1f8ad33e00528828b93a840592e2fb": { - "balance": "10000000000000000000000" - }, - "fdcf6a997bb10806e4d87eb4222e9f93b4202179": { - "balance": "1000000000000000000" - }, - "fde5a9911a10770d733db4d32ca9a5493478399c": { - "balance": "20000000000000000000000" - }, - "fe39185a6b84378820ee215f630533e658731ca9": { - "balance": "17022202932000000000" - }, - "fe3b1032e524674cba5f329f940c837850fa53ed": { - "balance": "50000000000000000000000" - }, - "fe3bc4ff2c3b66bc582558314b80030407e7de96": { - "balance": "1669870860988000000000" - }, - "fe668dbb1f3de744d16e13e0ed6f5708c2c15d1f": { - "balance": "39974355655263000000000" - }, - "fe95bfb97fa60341f8af2ad621e606b85e3c2e57": { - "balance": "528601649597478000000000" - }, - "fe99cf2a1fbbe7c46e4235b2d135a3a093fcf16c": { - "balance": "7271022106877000000000" - }, - "fec1f6ed4b3ff01e7ebe13fb53f60ee5a3b9e191": { - "balance": "1316316072034000000000" - }, - "fed9bec1b2145452ed5535e4ba29fafac6c35fbb": { - "balance": "10799354586000000000" - }, - "fedced7aa1cf3f3a7eec321cc0274759b154ea8e": { - "balance": "11740927210323000000000" - }, - "fef5063701a93ad02676fe0b99d0f4d2da0ccd67": { - "balance": "10178531012000000000" - }, - "fefd5627a408ca099587892ee2a46fa8cc89be19": { - "balance": "458504035686000000000" - }, - "ff1fc0f6f26188cbe18cf65d8a344d3775aecc6d": { - "balance": "81000000000000000000" - }, - "ff4fe483b3c04ebc8d6705c699ecee3e92071715": { - "balance": "1000000000000000000" - }, - "ff51bfe823394b2bce05947a6068bd5158d4af0e": { - "balance": "692533626783000000000" - }, - "ff6652e4e45f6b0f95ad4c9ec2bc80476e3f7fc6": { - "balance": "46457898024000000000" - }, - "ff68246ac7640091e5e58345736b249e036364fc": { - "balance": "2626125272000000000" - }, - "ff6d4b8a8393a503047ff829dbf2bf8e9172dc6d": { - "balance": "2865001878255000000000" - }, - "ff6fe19e056a7211b7e484c2c540d5aa5f1d83e5": { - "balance": "36000000000000000000" - }, - "ff7fa33529e1781c1b2951e57581780b229e3fda": { - "balance": "10000000000000000000" - }, - "ff82d1052538539d07cf3955476cc9a5027d8e4e": { - "balance": "83572023121000000000" - }, - "ff8acfe75afcc1efb1bc44be9f9bb242a94f73f7": { - "balance": "7556034521000000000" - }, - "ffa2b5f1685de9fcf1af4653cd3a584db1beed64": { - "balance": "114892199805000000000" - }, - "ffb1e9be68ae8be8d7d066c473589921e68825a2": { - "balance": "484660652980000000000" - }, - "ffbf91a9d1a6377b7435e3e734132e7b34188dac": { - "balance": "20000000000000000000000" - }, - "ffbff1fab9f2bc2f387d0cc9cc28f6aac533c813": { - "balance": "10000000000000000000000" - }, - "ffc4ff6433ea35544e7a07fda170e62c451301df": { - "balance": "29238210920000000000" - }, - "ffc7534b64a8fe8760e931a710883119d28ae106": { - "balance": "500000000000000000000000" - }, - "ffda6b8e3de72d7f7c18b892e6a8b80b886d5fa5": { - "balance": "214366938289000000000" - }, - "ffddb1fb7521c9772ea4886aaf022c4375ef904d": { - "balance": "554864446437000000000" - } - } -} diff --git a/ethcore/res/ethereum/st_peters_test.json b/ethcore/res/ethereum/st_peters_test.json index ee88008f66..768e6057fd 100644 --- a/ethcore/res/ethereum/st_peters_test.json +++ b/ethcore/res/ethereum/st_peters_test.json @@ -36,6 +36,7 @@ "eip145Transition": "0x0", "eip1014Transition": "0x0", "eip1052Transition": "0x0", + "eip1283Transition": "0x0", "eip1283DisableTransition": "0x0" }, "genesis": { @@ -58,8 +59,46 @@ "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + } } } diff --git a/ethcore/res/ethereum/tobalaba.json b/ethcore/res/ethereum/tobalaba.json deleted file mode 100644 index 043367cc72..0000000000 --- a/ethcore/res/ethereum/tobalaba.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "name": "Tobalaba", - "engine": { - "authorityRound": { - "params": { - "stepDuration": "3", - "validators": { - "contract": "0x1000000000000000000000000000000000000005" - }, - "maximumUncleCount": 999999 - } - } - }, - "params": { - "maximumExtraDataSize": "0x20", - "gasLimitBoundDivisor": "0x400", - "minGasLimit": "0x1388", - "networkID": "0x62121", - "eip98Transition": 0, - "wasmActivationTransition": 7250000, - "eip140Transition": 7250000, - "eip211Transition": 7250000, - "eip214Transition": 7250000, - "eip658Transition": 7250000, - - "maxCodeSize": 24576, - "maxCodeSizeTransition": 7250000, - - "registrar": "0xb8624dc8cb3ca3147c178ac4c21734eb49e04071" - }, - "genesis": { - "seal": { - "authorityRound": { - "step": "0x0", - "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - } - }, - "difficulty": "0x20000", - "gasLimit": "0x800000" - }, - "accounts": { - "0x1000000000000000000000000000000000000005": { - "balance": "1", - "constructor": "6060604052341561000f57600080fd5b5b60048054600160a060020a03199081167310000000000000000000000000000000000000061790915560028054909116731000000000000000000000000000000000000007179055600080546001810161006a8382610115565b916000526020600020900160005b8154600160a060020a036101009290920a9182021916734ba15b56452521c0826a35a6f2022e1210fc519b90910217905550600180548082016100bb8382610115565b916000526020600020900160005b8154600160a060020a036101009290920a9182021916734ba15b56452521c0826a35a6f2022e1210fc519b9182021790915560038054600160a060020a0319169091179055505b610160565b8154818355818115116101395760008381526020902061013991810190830161013f565b5b505050565b61015d91905b808211156101595760008155600101610145565b5090565b90565b610a208061016f6000396000f300606060405236156100ee5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166303aca792811461013d578063063a54c91461016f57806311ae9ed21461019e578063170f9291146102055780631cd3e85814610237578063480b4619146102585780636c1247e5146102bf5780637a1a9e60146102ee578063830f0bc6146103205780638da5cb5b146103525780639b2ae4c614610381578063b6f783f2146103a6578063b7ab4db5146103d5578063c55642be1461043c578063e2de215e1461045d578063fe5d935c1461048c578063ff7a071b146104f3575b34156100f957600080fd5b5b600454600160a060020a0316600036604051808383808284378201915050925050506000604051808303818561646e5a03f4915050151561013a57600080fd5b5b005b341561014857600080fd5b610153600435610518565b604051600160a060020a03909116815260200160405180910390f35b341561017a57600080fd5b61015361054a565b604051600160a060020a03909116815260200160405180910390f35b34156101a957600080fd5b6101b161055a565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156101f15780820151818401525b6020016101d8565b505050509050019250505060405180910390f35b341561021057600080fd5b6101536004356105c3565b604051600160a060020a03909116815260200160405180910390f35b341561024257600080fd5b61013a600160a060020a03600435166105f5565b005b341561026357600080fd5b6101b16106d1565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156101f15780820151818401525b6020016101d8565b505050509050019250505060405180910390f35b34156102ca57600080fd5b61015361073a565b604051600160a060020a03909116815260200160405180910390f35b34156102f957600080fd5b610153600435610749565b604051600160a060020a03909116815260200160405180910390f35b341561032b57600080fd5b61015360043561077b565b604051600160a060020a03909116815260200160405180910390f35b341561035d57600080fd5b6101536107ad565b604051600160a060020a03909116815260200160405180910390f35b341561038c57600080fd5b6103946107bc565b60405190815260200160405180910390f35b34156103b157600080fd5b6101536107c3565b604051600160a060020a03909116815260200160405180910390f35b34156103e057600080fd5b6101b16107d3565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156101f15780820151818401525b6020016101d8565b505050509050019250505060405180910390f35b341561044757600080fd5b61013a600160a060020a036004351661083c565b005b341561046857600080fd5b610153610918565b604051600160a060020a03909116815260200160405180910390f35b341561049757600080fd5b6101b1610927565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156101f15780820151818401525b6020016101d8565b505050509050019250505060405180910390f35b34156104fe57600080fd5b610394610990565b60405190815260200160405180910390f35b600180548290811061052657fe5b906000526020600020900160005b915054906101000a9004600160a060020a031681565b600254600160a060020a03165b90565b610562610997565b60018054806020026020016040519081016040528092919081815260200182805480156105b857602002820191906000526020600020905b8154600160a060020a0316815260019091019060200180831161059a575b505050505090505b90565b600080548290811061052657fe5b906000526020600020900160005b915054906101000a9004600160a060020a031681565b60035433600160a060020a0390811691161461061057600080fd5b600254600160a060020a038281169116141561062b57600080fd5b600680546001810161063d83826109a9565b916000526020600020900160005b600280548354600160a060020a036101009490940a848102199091169184160217909255815473ffffffffffffffffffffffffffffffffffffffff1916908416179055507f78603ac34f42fe53d8aad96b7b37aeee79dc7ed07c26f57a13cdf64ac72b0f1181604051600160a060020a03909116815260200160405180910390a15b5b50565b6106d9610997565b60058054806020026020016040519081016040528092919081815260200182805480156105b857602002820191906000526020600020905b8154600160a060020a0316815260019091019060200180831161059a575b505050505090505b90565b600254600160a060020a031681565b600680548290811061052657fe5b906000526020600020900160005b915054906101000a9004600160a060020a031681565b600580548290811061052657fe5b906000526020600020900160005b915054906101000a9004600160a060020a031681565b600354600160a060020a031681565b6001545b90565b600454600160a060020a03165b90565b6107db610997565b60008054806020026020016040519081016040528092919081815260200182805480156105b857602002820191906000526020600020905b8154600160a060020a0316815260019091019060200180831161059a575b505050505090505b90565b60035433600160a060020a0390811691161461085757600080fd5b600454600160a060020a038281169116141561087257600080fd5b600580546001810161088483826109a9565b916000526020600020900160005b600480548354600160a060020a036101009490940a848102199091169184160217909255815473ffffffffffffffffffffffffffffffffffffffff1916908416179055507fadcbcb6339ee0b34abbe8d1524c53b813794e1537a43136c6a7768019599625781604051600160a060020a03909116815260200160405180910390a15b5b50565b600454600160a060020a031681565b61092f610997565b60068054806020026020016040519081016040528092919081815260200182805480156105b857602002820191906000526020600020905b8154600160a060020a0316815260019091019060200180831161059a575b505050505090505b90565b6000545b90565b60206040519081016040526000815290565b8154818355818115116109cd576000838152602090206109cd9181019083016109d3565b5b505050565b61055791905b808211156109ed57600081556001016109d9565b5090565b905600a165627a7a72305820e9d3839061bfeb56c1cc57b2b2ec8dd7882afd848b4ae489c218d6f9674316660029" - }, - "0x1000000000000000000000000000000000000006": { - "balance": "1", - "constructor": "6060604052341561000f57600080fd5b5b60028054600160a060020a0319167310000000000000000000000000000000000000071790555b5b610abb806100476000396000f300606060405236156100885763ffffffff60e060020a60003504166303aca792811461008d578063170f9291146100bf57806340a141ff146100f15780634d238c8e146101125780634d655aff1461013357806375286211146101625780638da5cb5b14610177578063a6f9dae1146101a6578063c476dd40146101c7578063d69f13bb1461022e575b600080fd5b341561009857600080fd5b6100a3600435610252565b604051600160a060020a03909116815260200160405180910390f35b34156100ca57600080fd5b6100a3600435610284565b604051600160a060020a03909116815260200160405180910390f35b34156100fc57600080fd5b610110600160a060020a03600435166102b6565b005b341561011d57600080fd5b610110600160a060020a036004351661064d565b005b341561013e57600080fd5b6100a36107a1565b604051600160a060020a03909116815260200160405180910390f35b341561016d57600080fd5b6101106107b0565b005b341561018257600080fd5b6100a36107ed565b604051600160a060020a03909116815260200160405180910390f35b34156101b157600080fd5b610110600160a060020a03600435166107fc565b005b34156101d257600080fd5b61011060048035600160a060020a03169060248035919060649060443590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965061084495505050505050565b005b341561023957600080fd5b610110600160a060020a0360043516602435610926565b005b600180548290811061026057fe5b906000526020600020900160005b915054906101000a9004600160a060020a031681565b600080548290811061026057fe5b906000526020600020900160005b915054906101000a9004600160a060020a031681565b60035460009033600160a060020a039081169116146102d457600080fd5b600254600160a060020a031663b31610db8360006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561032d57600080fd5b6102c65a03f1151561033e57600080fd5b50505060405180511515905061035357600080fd5b60008054600019810190811061036557fe5b906000526020600020900160005b9054600254600160a060020a036101009390930a9091048216925082916001911663b31610db8560006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b15156103e157600080fd5b6102c65a03f115156103f257600080fd5b50505060405180518254909150811061040757fe5b906000526020600020900160005b6101000a815481600160a060020a030219169083600160a060020a0316021790555060018080805490500381548110151561044c57fe5b906000526020600020900160005b81546101009190910a600160a060020a0302191690556001805460001901906104839082610991565b50600254600160a060020a0316635caf5a6a828263b31610db8660006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b15156104e457600080fd5b6102c65a03f115156104f557600080fd5b5050506040518051905060405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b151561054257600080fd5b6102c65a03f1151561055357600080fd5b5050600254600160a060020a03169050635caf5a6a83600060405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b15156105ae57600080fd5b6102c65a03f115156105bf57600080fd5b5050506000194301407f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89600160405160208082528254908201819052819060408201908490801561063957602002820191906000526020600020905b8154600160a060020a0316815260019091019060200180831161061b575b50509250505060405180910390a25b5b5050565b60035433600160a060020a0390811691161461066857600080fd5b600180548082016106798382610991565b916000526020600020900160005b81546101009190910a600160a060020a0381810219909216858316919091021790915560025460015491169150635caf5a6a9083906000190160405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b151561070357600080fd5b6102c65a03f1151561071457600080fd5b5050506000194301407f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89600160405160208082528254908201819052819060408201908490801561078e57602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610770575b50509250505060405180910390a25b5b50565b600254600160a060020a031681565b73fffffffffffffffffffffffffffffffffffffffe600160a060020a033316146107d957600080fd5b6001805461079d916000916109e5565b505b565b600354600160a060020a031681565b60035433600160a060020a0390811691161461081757600080fd5b6003805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b73fffffffffffffffffffffffffffffffffffffffe600160a060020a0333161461086d57600080fd5b7f8498b6f07a5f800443a5fd85ac8171cf40cda44faea60caabe9b297d9dfa8424838383604051600160a060020a03841681526020810183905260606040820181815290820183818151815260200191508051906020019080838360005b838110156108e45780820151818401525b6020016108cb565b50505050905090810190601f1680156109115780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a15b505050565b73fffffffffffffffffffffffffffffffffffffffe600160a060020a0333161461094f57600080fd5b81600160a060020a03167f31bc112157435aab6dd7e9a059abea7f0fce172e3e68e272a6375bbb01eb96c18260405190815260200160405180910390a25b5050565b81548183558181151161092157600083815260209020610921918101908301610a36565b5b505050565b81548183558181151161092157600083815260209020610921918101908301610a36565b5b505050565b828054828255906000526020600020908101928215610a255760005260206000209182015b82811115610a25578254825591600101919060010190610a0a565b5b50610a32929150610a57565b5090565b610a5491905b80821115610a325760008155600101610a3c565b5090565b90565b610a5491905b80821115610a3257805473ffffffffffffffffffffffffffffffffffffffff19168155600101610a5d565b5090565b905600a165627a7a72305820cae3ca62c5821766e8122461884affeaabdc6c2fe79f5a3200207a536e5b0e260029" - }, - "0x1000000000000000000000000000000000000007": { - "balance": "1", - "constructor": "6060604052341561000f57600080fd5b5b60018054600160a060020a0319167310000000000000000000000000000000000000051790555b5b6101bb806100476000396000f300606060405263ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166318def8ef811461005e5780635caf5a6a1461008f5780638da5cb5b146100b3578063b31610db146100e2575b600080fd5b341561006957600080fd5b61007d600160a060020a0360043516610113565b60405190815260200160405180910390f35b341561009a57600080fd5b6100b1600160a060020a0360043516602435610125565b005b34156100be57600080fd5b6100c6610161565b604051600160a060020a03909116815260200160405180910390f35b34156100ed57600080fd5b61007d600160a060020a0360043516610170565b60405190815260200160405180910390f35b60006020819052908152604090205481565b60015433600160a060020a0390811691161461014057600080fd5b600160a060020a03821660009081526020819052604090208190555b5b5050565b600154600160a060020a031681565b600160a060020a0381166000908152602081905260409020545b9190505600a165627a7a7230582085b261e548fa6e3065a32e485c6417d200c7145f3548c0097d4c92022ac7fb1e0029" - }, - "0x4ba15b56452521c0826a35a6f2022e1210fc519b": { - "balance": "0x7E37BE2022B2B09472D89C0000" - }, - - "0x0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "activate_at": 7250000, "pricing": { "linear": { "base": 3000, "word": 0 } } } }, - "0x0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "activate_at": 7250000, "pricing": { "linear": { "base": 60, "word": 12 } } } }, - "0x0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "activate_at": 7250000, "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0x0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "activate_at": 7250000, "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 7250000, "pricing": { "modexp": { "divisor": 20 } } } }, - "0x0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 7250000, "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0x0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 7250000, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0x0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 7250000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } - }, - - "nodes": [ - "enode://a9327d37d07799817d4a3e13d49fb4f5cc1486d4adf3ec8a6b98be62c4d7a5453914a5139dbe124809a388514cb0be37f9fa799539abe2250672f6d3d778b821@18.191.209.251:30303", - "enode://8185e15b0e269e19b9051ba2c3bab9160f0e52a8e5e2cef626013142d957c4256f0b18e80965a9fa9acabdb2ba07890c995ad354cbda0fa812ded5a5ce878321@3.121.61.202:30303", - "enode://38fab1370b042170b37ebd758d07c17b7aa4fd4ff21db8e8f120ade9cf17835ae67fd014a047ee171952fba2a05a90505fedbe98c883b20e4501d437aec8b831@3.122.42.125:30303", - "enode://d2fdbd9efe681080410775dbe986014e21a6a096b6dfd7d2c499f3b893951adf3aae0164392404f6269d231192735bd0c8da3d022639e8a36d8d17299daa632a@3.122.18.27:30303", - "enode://9745ffa93cde2a0e22528fbd4a4f8b5102035ab8c7a781918c9ef92dee6e5a21635dfd106ccfbcf24f4fdd52e8fb513b7f3f55ced90c9b61f2cd756bccd7f660@18.210.141.224:30303", - "enode://4c36427e744783bcbc595a7fbbe785951130d8d4fe9f2206c78538fcf43fb19172df8a577c4ae0c91b7627b057bdf148666a7e4e428650e677f9c443e59479e4@3.86.127.87:30303", - "enode://b447c1eaad456996ae4ce965a01d543b8f4b0d7e78e23d2cc2d328fe0e0b87dac55eaebe9a27ae24fb879cf056b52b11d967d37a731f5f5987ec4fc0dfb4d908@34.236.121.163:30303", - "enode://916dba32ba88b7a5554d862b5a01b5eddf805788545f2ba6ee682f1cfe08eac132b71a4d725bc73c7b687496e525bf414e7d90cd223dacebe1946e3bb464bca0@18.136.95.237:30303", - "enode://a46393687ee9fbe798aba517d8f92443e45ed7e5ea85aa996c62998088607d57b000001945063045584861652802325d93828cef29a9eb966772f75521dff8c6@3.0.157.214:30303", - "enode://94b92761837031a7afbbc7e6a4363baf6c5f04c7766ab63f4f5b47c98be30faef6e5e91d30cc08dd682a6dc16cdd4f85ec6843f4ac9f18887d4da20b04878ea6@52.220.46.9:30303" - ] -} diff --git a/ethcore/res/ethereum/transition_test.json b/ethcore/res/ethereum/transition_test.json index 3f1c420dd6..bc28ebd509 100644 --- a/ethcore/res/ethereum/transition_test.json +++ b/ethcore/res/ethereum/transition_test.json @@ -57,9 +57,46 @@ "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "5", "pricing": { "modexp": { "divisor": 100 } } } }, - "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "5", "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "5", "pricing": { "linear": { "base": 2000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "5", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": "5", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "5", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "5", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + } } } diff --git a/ethcore/res/ethereum/volta.json b/ethcore/res/ethereum/volta.json new file mode 100644 index 0000000000..9ac6f9afa4 --- /dev/null +++ b/ethcore/res/ethereum/volta.json @@ -0,0 +1,207 @@ +{ + "name": "Volta", + "engine": { + "authorityRound": { + "params": { + "stepDuration": "5", + "validators": { + "contract": "0x1204700000000000000000000000000000000000" + }, + "maximumUncleCountTransition": "0", + "maximumUncleCount": "0", + "blockRewardContractAddress": "0x1204700000000000000000000000000000000002", + "blockRewardContractTransition": "0" + } + } + }, + "params": { + "networkID": "0x12047", + "maximumExtraDataSize": "0x20", + "gasLimitBoundDivisor": "0x400", + "minGasLimit": "0x1388", + "maxCodeSize": "0x6000", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0", + "eip145Transition": "0x0", + "eip1014Transition": "0x0", + "eip1052Transition": "0x0", + "registrar": "0x1204700000000000000000000000000000000006" + }, + "genesis": { + "seal": { + "authorityRound": { + "step": "0x0", + "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x20000", + "gasLimit": "0x5B8D80" + }, + "accounts": { + "0x0000000000000000000000000000000000000001": { + "balance": "1", + "builtin": { + "name": "ecrecover", + "activate_at": "0", + "pricing": { + "linear": { + "base": 3000, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000002": { + "balance": "1", + "builtin": { + "name": "sha256", + "activate_at": "0", + "pricing": { + "linear": { + "base": 60, + "word": 12 + } + } + } + }, + "0x0000000000000000000000000000000000000003": { + "balance": "1", + "builtin": { + "name": "ripemd160", + "activate_at": "0", + "pricing": { + "linear": { + "base": 600, + "word": 120 + } + } + } + }, + "0x0000000000000000000000000000000000000004": { + "balance": "1", + "builtin": { + "name": "identity", + "activate_at": "0", + "pricing": { + "linear": { + "base": 15, + "word": 3 + } + } + } + }, + "0x0000000000000000000000000000000000000005": { + "balance": "1", + "builtin": { + "name": "modexp", + "activate_at": "0", + "pricing": { + "modexp": { + "divisor": 20 + } + } + } + }, + "0x0000000000000000000000000000000000000006": { + "balance": "1", + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0x0000000000000000000000000000000000000007": { + "balance": "1", + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0x0000000000000000000000000000000000000008": { + "balance": "1", + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, + "0x1204700000000000000000000000000000000005": { + "constructor": "0x606060405234156200001057600080fd5b6040516200240138038062002401833981016040528080518201919060200180519060200190919050505b600082518260328211158015620000525750818111155b801562000060575060008114155b80156200006e575060008214155b15156200007a57600080fd5b600092505b8451831015620001b6576002600086858151811015156200009c57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161580156200012b5750600085848151811015156200010857fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1614155b15156200013757600080fd5b60016002600087868151811015156200014c57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b82806001019350506200007f565b8460039080519060200190620001ce929190620001e3565b50836004819055505b5b5050505050620002b8565b8280548282559060005260206000209081019282156200025f579160200282015b828111156200025e5782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019062000204565b5b5090506200026e919062000272565b5090565b620002b591905b80821115620002b157600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555060010162000279565b5090565b90565b61213980620002c86000396000f3006060604052361561011b576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063025e7c2714610177578063173825d9146101da57806320ea8d86146102135780632f54bf6e146102365780633411c81c1461028757806354741525146102e15780637065cb4814610325578063784547a71461035e5780638b51d13f146103995780639ace38c2146103d0578063a0e67e2b146104ce578063a8abe69a14610539578063b5dc40c3146105d1578063b77bf6001461064a578063ba51a6df14610673578063c01a8c8414610696578063c6427474146106b9578063d74f8edd14610752578063dc8452cd1461077b578063e20056e6146107a4578063ee22610b146107fc575b5b6000341115610174573373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a25b5b005b341561018257600080fd5b610198600480803590602001909190505061081f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101e557600080fd5b610211600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061085f565b005b341561021e57600080fd5b6102346004808035906020019091905050610b02565b005b341561024157600080fd5b61026d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610cae565b604051808215151515815260200191505060405180910390f35b341561029257600080fd5b6102c7600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610cce565b604051808215151515815260200191505060405180910390f35b34156102ec57600080fd5b61030f600480803515159060200190919080351515906020019091905050610cfd565b6040518082815260200191505060405180910390f35b341561033057600080fd5b61035c600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d91565b005b341561036957600080fd5b61037f6004808035906020019091905050610f99565b604051808215151515815260200191505060405180910390f35b34156103a457600080fd5b6103ba6004808035906020019091905050611081565b6040518082815260200191505060405180910390f35b34156103db57600080fd5b6103f16004808035906020019091905050611150565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200184815260200180602001831515151581526020018281038252848181546001816001161561010002031660029004815260200191508054600181600116156101000203166002900480156104bc5780601f10610491576101008083540402835291602001916104bc565b820191906000526020600020905b81548152906001019060200180831161049f57829003601f168201915b50509550505050505060405180910390f35b34156104d957600080fd5b6104e16111ac565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156105255780820151818401525b602081019050610509565b505050509050019250505060405180910390f35b341561054457600080fd5b610579600480803590602001909190803590602001909190803515159060200190919080351515906020019091905050611241565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156105bd5780820151818401525b6020810190506105a1565b505050509050019250505060405180910390f35b34156105dc57600080fd5b6105f260048080359060200190919050506113a2565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156106365780820151818401525b60208101905061061a565b505050509050019250505060405180910390f35b341561065557600080fd5b61065d6115d3565b6040518082815260200191505060405180910390f35b341561067e57600080fd5b61069460048080359060200190919050506115d9565b005b34156106a157600080fd5b6106b76004808035906020019091905050611696565b005b34156106c457600080fd5b61073c600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050611877565b6040518082815260200191505060405180910390f35b341561075d57600080fd5b610765611897565b6040518082815260200191505060405180910390f35b341561078657600080fd5b61078e61189c565b6040518082815260200191505060405180910390f35b34156107af57600080fd5b6107fa600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506118a2565b005b341561080757600080fd5b61081d6004808035906020019091905050611bc0565b005b60038181548110151561082e57fe5b906000526020600020900160005b915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561089b57600080fd5b81600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615156108f457600080fd5b6000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600091505b600160038054905003821015610a80578273ffffffffffffffffffffffffffffffffffffffff1660038381548110151561098757fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610a725760036001600380549050038154811015156109e757fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600383815481101515610a2357fe5b906000526020600020900160005b6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610a80565b5b8180600101925050610951565b6001600381818054905003915081610a989190611fe8565b506003805490506004541115610ab757610ab66003805490506115d9565b5b8273ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a25b5b505b5050565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610b5b57600080fd5b81336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610bc657600080fd5b8360008082815260200190815260200160002060030160009054906101000a900460ff16151515610bf657600080fd5b60006001600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e960405160405180910390a35b5b505b50505b5050565b60026020528060005260406000206000915054906101000a900460ff1681565b60016020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600080600090505b600554811015610d8957838015610d3c575060008082815260200190815260200160002060030160009054906101000a900460ff16155b80610d6f5750828015610d6e575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b15610d7b576001820191505b5b8080600101915050610d05565b5b5092915050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610dcb57600080fd5b80600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515610e2557600080fd5b8160008173ffffffffffffffffffffffffffffffffffffffff1614151515610e4c57600080fd5b60016003805490500160045460328211158015610e695750818111155b8015610e76575060008114155b8015610e83575060008214155b1515610e8e57600080fd5b6001600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060038054806001018281610efa9190612014565b916000526020600020900160005b87909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508473ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25b5b50505b505b505b50565b6000806000809150600090505b60038054905081101561107957600160008581526020019081526020016000206000600383815481101515610fd757fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615611058576001820191505b60045482141561106b576001925061107a565b5b8080600101915050610fa6565b5b5050919050565b600080600090505b600380549050811015611149576001600084815260200190815260200160002060006003838154811015156110ba57fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561113b576001820191505b5b8080600101915050611089565b5b50919050565b60006020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169080600101549080600201908060030160009054906101000a900460ff16905084565b6111b4612040565b600380548060200260200160405190810160405280929190818152602001828054801561123657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116111ec575b505050505090505b90565b611249612054565b611251612054565b6000806005546040518059106112645750595b908082528060200260200182016040525b50925060009150600090505b600554811015611322578580156112b8575060008082815260200190815260200160002060030160009054906101000a900460ff16155b806112eb57508480156112ea575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b15611314578083838151811015156112ff57fe5b90602001906020020181815250506001820191505b5b8080600101915050611281565b8787036040518059106113325750595b908082528060200260200182016040525b5093508790505b8681101561139657828181518110151561136057fe5b906020019060200201518489830381518110151561137a57fe5b90602001906020020181815250505b808060010191505061134a565b5b505050949350505050565b6113aa612040565b6113b2612040565b6000806003805490506040518059106113c85750595b908082528060200260200182016040525b50925060009150600090505b60038054905081101561152b5760016000868152602001908152602001600020600060038381548110151561141657fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561151d5760038181548110151561149f57fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811015156114da57fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506001820191505b5b80806001019150506113e5565b816040518059106115395750595b908082528060200260200182016040525b509350600090505b818110156115ca57828181518110151561156857fe5b90602001906020020151848281518110151561158057fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b8080600101915050611552565b5b505050919050565b60055481565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561161357600080fd5b600380549050816032821115801561162b5750818111155b8015611638575060008114155b8015611645575060008214155b151561165057600080fd5b826004819055507fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a836040518082815260200191505060405180910390a15b5b50505b50565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615156116ef57600080fd5b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151561174b57600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515156117b757600080fd5b600180600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef60405160405180910390a361186c85611bc0565b5b5b50505b505b5050565b6000611884848484611e6c565b905061188f81611696565b5b9392505050565b603281565b60045481565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156118de57600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561193757600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151561199157600080fd5b600092505b600380549050831015611a7f578473ffffffffffffffffffffffffffffffffffffffff166003848154811015156119c957fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611a715783600384815481101515611a2257fe5b906000526020600020900160005b6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611a7f565b5b8280600101935050611996565b6000600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508473ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a28373ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25b5b505b505b505050565b600033600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611c1b57600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611c8657600080fd5b8460008082815260200190815260200160002060030160009054906101000a900460ff16151515611cb657600080fd5b611cbf86610f99565b15611e6057600080878152602001908152602001600020945060018560030160006101000a81548160ff021916908315150217905550611ddd8560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866001015487600201805460018160011615610100020316600290049050886002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611dd35780601f10611da857610100808354040283529160200191611dd3565b820191906000526020600020905b815481529060010190602001808311611db657829003601f168201915b5050505050611fc0565b15611e1457857f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7560405160405180910390a2611e5f565b857f526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b7923660405160405180910390a260008560030160006101000a81548160ff0219169083151502179055505b5b5b5b505b50505b505050565b60008360008173ffffffffffffffffffffffffffffffffffffffff1614151515611e9557600080fd5b60055491506080604051908101604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018481526020016000151581525060008084815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101556040820151816002019080519060200190611f54929190612068565b5060608201518160030160006101000a81548160ff0219169083151502179055509050506001600560008282540192505081905550817fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5160405160405180910390a25b5b509392505050565b6000806040516020840160008287838a8c6187965a03f1925050508091505b50949350505050565b81548183558181151161200f5781836000526020600020918201910161200e91906120e8565b5b505050565b81548183558181151161203b5781836000526020600020918201910161203a91906120e8565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106120a957805160ff19168380011785556120d7565b828001600101855582156120d7579182015b828111156120d65782518255916020019190600101906120bb565b5b5090506120e491906120e8565b5090565b61210a91905b808211156121065760008160009055506001016120ee565b5090565b905600a165627a7a72305820f1129b699b3017535535a920e15503cd06af1f5c77637c0637cc29355b1dad3400290000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000cb1437200aea736788f1fc56f327c0456c3598d00000000000000000000000074dd76e24b2cfb43c1b1a4498295d553d0843746000000000000000000000000eeb4ceee443f9e0d17bdbd6daa241681ee5e51c2000000000000000000000000a005caea55375ae20e3aaef746113535503abc19" + }, + "0x1204700000000000000000000000000000000003": { + "constructor": "0x606060405234156200001057600080fd5b6040516200240138038062002401833981016040528080518201919060200180519060200190919050505b600082518260328211158015620000525750818111155b801562000060575060008114155b80156200006e575060008214155b15156200007a57600080fd5b600092505b8451831015620001b6576002600086858151811015156200009c57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161580156200012b5750600085848151811015156200010857fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1614155b15156200013757600080fd5b60016002600087868151811015156200014c57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b82806001019350506200007f565b8460039080519060200190620001ce929190620001e3565b50836004819055505b5b5050505050620002b8565b8280548282559060005260206000209081019282156200025f579160200282015b828111156200025e5782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019062000204565b5b5090506200026e919062000272565b5090565b620002b591905b80821115620002b157600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555060010162000279565b5090565b90565b61213980620002c86000396000f3006060604052361561011b576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063025e7c2714610177578063173825d9146101da57806320ea8d86146102135780632f54bf6e146102365780633411c81c1461028757806354741525146102e15780637065cb4814610325578063784547a71461035e5780638b51d13f146103995780639ace38c2146103d0578063a0e67e2b146104ce578063a8abe69a14610539578063b5dc40c3146105d1578063b77bf6001461064a578063ba51a6df14610673578063c01a8c8414610696578063c6427474146106b9578063d74f8edd14610752578063dc8452cd1461077b578063e20056e6146107a4578063ee22610b146107fc575b5b6000341115610174573373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a25b5b005b341561018257600080fd5b610198600480803590602001909190505061081f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101e557600080fd5b610211600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061085f565b005b341561021e57600080fd5b6102346004808035906020019091905050610b02565b005b341561024157600080fd5b61026d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610cae565b604051808215151515815260200191505060405180910390f35b341561029257600080fd5b6102c7600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610cce565b604051808215151515815260200191505060405180910390f35b34156102ec57600080fd5b61030f600480803515159060200190919080351515906020019091905050610cfd565b6040518082815260200191505060405180910390f35b341561033057600080fd5b61035c600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d91565b005b341561036957600080fd5b61037f6004808035906020019091905050610f99565b604051808215151515815260200191505060405180910390f35b34156103a457600080fd5b6103ba6004808035906020019091905050611081565b6040518082815260200191505060405180910390f35b34156103db57600080fd5b6103f16004808035906020019091905050611150565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200184815260200180602001831515151581526020018281038252848181546001816001161561010002031660029004815260200191508054600181600116156101000203166002900480156104bc5780601f10610491576101008083540402835291602001916104bc565b820191906000526020600020905b81548152906001019060200180831161049f57829003601f168201915b50509550505050505060405180910390f35b34156104d957600080fd5b6104e16111ac565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156105255780820151818401525b602081019050610509565b505050509050019250505060405180910390f35b341561054457600080fd5b610579600480803590602001909190803590602001909190803515159060200190919080351515906020019091905050611241565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156105bd5780820151818401525b6020810190506105a1565b505050509050019250505060405180910390f35b34156105dc57600080fd5b6105f260048080359060200190919050506113a2565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156106365780820151818401525b60208101905061061a565b505050509050019250505060405180910390f35b341561065557600080fd5b61065d6115d3565b6040518082815260200191505060405180910390f35b341561067e57600080fd5b61069460048080359060200190919050506115d9565b005b34156106a157600080fd5b6106b76004808035906020019091905050611696565b005b34156106c457600080fd5b61073c600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050611877565b6040518082815260200191505060405180910390f35b341561075d57600080fd5b610765611897565b6040518082815260200191505060405180910390f35b341561078657600080fd5b61078e61189c565b6040518082815260200191505060405180910390f35b34156107af57600080fd5b6107fa600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506118a2565b005b341561080757600080fd5b61081d6004808035906020019091905050611bc0565b005b60038181548110151561082e57fe5b906000526020600020900160005b915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561089b57600080fd5b81600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615156108f457600080fd5b6000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600091505b600160038054905003821015610a80578273ffffffffffffffffffffffffffffffffffffffff1660038381548110151561098757fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610a725760036001600380549050038154811015156109e757fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600383815481101515610a2357fe5b906000526020600020900160005b6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610a80565b5b8180600101925050610951565b6001600381818054905003915081610a989190611fe8565b506003805490506004541115610ab757610ab66003805490506115d9565b5b8273ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a25b5b505b5050565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610b5b57600080fd5b81336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610bc657600080fd5b8360008082815260200190815260200160002060030160009054906101000a900460ff16151515610bf657600080fd5b60006001600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e960405160405180910390a35b5b505b50505b5050565b60026020528060005260406000206000915054906101000a900460ff1681565b60016020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600080600090505b600554811015610d8957838015610d3c575060008082815260200190815260200160002060030160009054906101000a900460ff16155b80610d6f5750828015610d6e575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b15610d7b576001820191505b5b8080600101915050610d05565b5b5092915050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610dcb57600080fd5b80600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515610e2557600080fd5b8160008173ffffffffffffffffffffffffffffffffffffffff1614151515610e4c57600080fd5b60016003805490500160045460328211158015610e695750818111155b8015610e76575060008114155b8015610e83575060008214155b1515610e8e57600080fd5b6001600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060038054806001018281610efa9190612014565b916000526020600020900160005b87909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508473ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25b5b50505b505b505b50565b6000806000809150600090505b60038054905081101561107957600160008581526020019081526020016000206000600383815481101515610fd757fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615611058576001820191505b60045482141561106b576001925061107a565b5b8080600101915050610fa6565b5b5050919050565b600080600090505b600380549050811015611149576001600084815260200190815260200160002060006003838154811015156110ba57fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561113b576001820191505b5b8080600101915050611089565b5b50919050565b60006020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169080600101549080600201908060030160009054906101000a900460ff16905084565b6111b4612040565b600380548060200260200160405190810160405280929190818152602001828054801561123657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116111ec575b505050505090505b90565b611249612054565b611251612054565b6000806005546040518059106112645750595b908082528060200260200182016040525b50925060009150600090505b600554811015611322578580156112b8575060008082815260200190815260200160002060030160009054906101000a900460ff16155b806112eb57508480156112ea575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b15611314578083838151811015156112ff57fe5b90602001906020020181815250506001820191505b5b8080600101915050611281565b8787036040518059106113325750595b908082528060200260200182016040525b5093508790505b8681101561139657828181518110151561136057fe5b906020019060200201518489830381518110151561137a57fe5b90602001906020020181815250505b808060010191505061134a565b5b505050949350505050565b6113aa612040565b6113b2612040565b6000806003805490506040518059106113c85750595b908082528060200260200182016040525b50925060009150600090505b60038054905081101561152b5760016000868152602001908152602001600020600060038381548110151561141657fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561151d5760038181548110151561149f57fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811015156114da57fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506001820191505b5b80806001019150506113e5565b816040518059106115395750595b908082528060200260200182016040525b509350600090505b818110156115ca57828181518110151561156857fe5b90602001906020020151848281518110151561158057fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b8080600101915050611552565b5b505050919050565b60055481565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561161357600080fd5b600380549050816032821115801561162b5750818111155b8015611638575060008114155b8015611645575060008214155b151561165057600080fd5b826004819055507fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a836040518082815260200191505060405180910390a15b5b50505b50565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615156116ef57600080fd5b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151561174b57600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515156117b757600080fd5b600180600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef60405160405180910390a361186c85611bc0565b5b5b50505b505b5050565b6000611884848484611e6c565b905061188f81611696565b5b9392505050565b603281565b60045481565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156118de57600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561193757600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151561199157600080fd5b600092505b600380549050831015611a7f578473ffffffffffffffffffffffffffffffffffffffff166003848154811015156119c957fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611a715783600384815481101515611a2257fe5b906000526020600020900160005b6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611a7f565b5b8280600101935050611996565b6000600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508473ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a28373ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25b5b505b505b505050565b600033600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611c1b57600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611c8657600080fd5b8460008082815260200190815260200160002060030160009054906101000a900460ff16151515611cb657600080fd5b611cbf86610f99565b15611e6057600080878152602001908152602001600020945060018560030160006101000a81548160ff021916908315150217905550611ddd8560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866001015487600201805460018160011615610100020316600290049050886002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611dd35780601f10611da857610100808354040283529160200191611dd3565b820191906000526020600020905b815481529060010190602001808311611db657829003601f168201915b5050505050611fc0565b15611e1457857f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7560405160405180910390a2611e5f565b857f526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b7923660405160405180910390a260008560030160006101000a81548160ff0219169083151502179055505b5b5b5b505b50505b505050565b60008360008173ffffffffffffffffffffffffffffffffffffffff1614151515611e9557600080fd5b60055491506080604051908101604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018481526020016000151581525060008084815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101556040820151816002019080519060200190611f54929190612068565b5060608201518160030160006101000a81548160ff0219169083151502179055509050506001600560008282540192505081905550817fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5160405160405180910390a25b5b509392505050565b6000806040516020840160008287838a8c6187965a03f1925050508091505b50949350505050565b81548183558181151161200f5781836000526020600020918201910161200e91906120e8565b5b505050565b81548183558181151161203b5781836000526020600020918201910161203a91906120e8565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106120a957805160ff19168380011785556120d7565b828001600101855582156120d7579182015b828111156120d65782518255916020019190600101906120bb565b5b5090506120e491906120e8565b5090565b61210a91905b808211156121065760008160009055506001016120ee565b5090565b905600a165627a7a72305820f1129b699b3017535535a920e15503cd06af1f5c77637c0637cc29355b1dad3400290000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000cb1437200aea736788f1fc56f327c0456c3598d00000000000000000000000074dd76e24b2cfb43c1b1a4498295d553d0843746000000000000000000000000eeb4ceee443f9e0d17bdbd6daa241681ee5e51c2000000000000000000000000a005caea55375ae20e3aaef746113535503abc19" + }, + "0x120470000000000000000000000000000000000a": { + "balance": "11310499300000000000000000", + "constructor": "0x606060405234156200001057600080fd5b6040516200240138038062002401833981016040528080518201919060200180519060200190919050505b600082518260328211158015620000525750818111155b801562000060575060008114155b80156200006e575060008214155b15156200007a57600080fd5b600092505b8451831015620001b6576002600086858151811015156200009c57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161580156200012b5750600085848151811015156200010857fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1614155b15156200013757600080fd5b60016002600087868151811015156200014c57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b82806001019350506200007f565b8460039080519060200190620001ce929190620001e3565b50836004819055505b5b5050505050620002b8565b8280548282559060005260206000209081019282156200025f579160200282015b828111156200025e5782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019062000204565b5b5090506200026e919062000272565b5090565b620002b591905b80821115620002b157600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555060010162000279565b5090565b90565b61213980620002c86000396000f3006060604052361561011b576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063025e7c2714610177578063173825d9146101da57806320ea8d86146102135780632f54bf6e146102365780633411c81c1461028757806354741525146102e15780637065cb4814610325578063784547a71461035e5780638b51d13f146103995780639ace38c2146103d0578063a0e67e2b146104ce578063a8abe69a14610539578063b5dc40c3146105d1578063b77bf6001461064a578063ba51a6df14610673578063c01a8c8414610696578063c6427474146106b9578063d74f8edd14610752578063dc8452cd1461077b578063e20056e6146107a4578063ee22610b146107fc575b5b6000341115610174573373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a25b5b005b341561018257600080fd5b610198600480803590602001909190505061081f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101e557600080fd5b610211600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061085f565b005b341561021e57600080fd5b6102346004808035906020019091905050610b02565b005b341561024157600080fd5b61026d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610cae565b604051808215151515815260200191505060405180910390f35b341561029257600080fd5b6102c7600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610cce565b604051808215151515815260200191505060405180910390f35b34156102ec57600080fd5b61030f600480803515159060200190919080351515906020019091905050610cfd565b6040518082815260200191505060405180910390f35b341561033057600080fd5b61035c600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d91565b005b341561036957600080fd5b61037f6004808035906020019091905050610f99565b604051808215151515815260200191505060405180910390f35b34156103a457600080fd5b6103ba6004808035906020019091905050611081565b6040518082815260200191505060405180910390f35b34156103db57600080fd5b6103f16004808035906020019091905050611150565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200184815260200180602001831515151581526020018281038252848181546001816001161561010002031660029004815260200191508054600181600116156101000203166002900480156104bc5780601f10610491576101008083540402835291602001916104bc565b820191906000526020600020905b81548152906001019060200180831161049f57829003601f168201915b50509550505050505060405180910390f35b34156104d957600080fd5b6104e16111ac565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156105255780820151818401525b602081019050610509565b505050509050019250505060405180910390f35b341561054457600080fd5b610579600480803590602001909190803590602001909190803515159060200190919080351515906020019091905050611241565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156105bd5780820151818401525b6020810190506105a1565b505050509050019250505060405180910390f35b34156105dc57600080fd5b6105f260048080359060200190919050506113a2565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156106365780820151818401525b60208101905061061a565b505050509050019250505060405180910390f35b341561065557600080fd5b61065d6115d3565b6040518082815260200191505060405180910390f35b341561067e57600080fd5b61069460048080359060200190919050506115d9565b005b34156106a157600080fd5b6106b76004808035906020019091905050611696565b005b34156106c457600080fd5b61073c600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050611877565b6040518082815260200191505060405180910390f35b341561075d57600080fd5b610765611897565b6040518082815260200191505060405180910390f35b341561078657600080fd5b61078e61189c565b6040518082815260200191505060405180910390f35b34156107af57600080fd5b6107fa600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506118a2565b005b341561080757600080fd5b61081d6004808035906020019091905050611bc0565b005b60038181548110151561082e57fe5b906000526020600020900160005b915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561089b57600080fd5b81600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615156108f457600080fd5b6000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600091505b600160038054905003821015610a80578273ffffffffffffffffffffffffffffffffffffffff1660038381548110151561098757fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610a725760036001600380549050038154811015156109e757fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600383815481101515610a2357fe5b906000526020600020900160005b6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610a80565b5b8180600101925050610951565b6001600381818054905003915081610a989190611fe8565b506003805490506004541115610ab757610ab66003805490506115d9565b5b8273ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a25b5b505b5050565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610b5b57600080fd5b81336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610bc657600080fd5b8360008082815260200190815260200160002060030160009054906101000a900460ff16151515610bf657600080fd5b60006001600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e960405160405180910390a35b5b505b50505b5050565b60026020528060005260406000206000915054906101000a900460ff1681565b60016020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600080600090505b600554811015610d8957838015610d3c575060008082815260200190815260200160002060030160009054906101000a900460ff16155b80610d6f5750828015610d6e575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b15610d7b576001820191505b5b8080600101915050610d05565b5b5092915050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610dcb57600080fd5b80600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515610e2557600080fd5b8160008173ffffffffffffffffffffffffffffffffffffffff1614151515610e4c57600080fd5b60016003805490500160045460328211158015610e695750818111155b8015610e76575060008114155b8015610e83575060008214155b1515610e8e57600080fd5b6001600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060038054806001018281610efa9190612014565b916000526020600020900160005b87909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508473ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25b5b50505b505b505b50565b6000806000809150600090505b60038054905081101561107957600160008581526020019081526020016000206000600383815481101515610fd757fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615611058576001820191505b60045482141561106b576001925061107a565b5b8080600101915050610fa6565b5b5050919050565b600080600090505b600380549050811015611149576001600084815260200190815260200160002060006003838154811015156110ba57fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561113b576001820191505b5b8080600101915050611089565b5b50919050565b60006020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169080600101549080600201908060030160009054906101000a900460ff16905084565b6111b4612040565b600380548060200260200160405190810160405280929190818152602001828054801561123657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116111ec575b505050505090505b90565b611249612054565b611251612054565b6000806005546040518059106112645750595b908082528060200260200182016040525b50925060009150600090505b600554811015611322578580156112b8575060008082815260200190815260200160002060030160009054906101000a900460ff16155b806112eb57508480156112ea575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b15611314578083838151811015156112ff57fe5b90602001906020020181815250506001820191505b5b8080600101915050611281565b8787036040518059106113325750595b908082528060200260200182016040525b5093508790505b8681101561139657828181518110151561136057fe5b906020019060200201518489830381518110151561137a57fe5b90602001906020020181815250505b808060010191505061134a565b5b505050949350505050565b6113aa612040565b6113b2612040565b6000806003805490506040518059106113c85750595b908082528060200260200182016040525b50925060009150600090505b60038054905081101561152b5760016000868152602001908152602001600020600060038381548110151561141657fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561151d5760038181548110151561149f57fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811015156114da57fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506001820191505b5b80806001019150506113e5565b816040518059106115395750595b908082528060200260200182016040525b509350600090505b818110156115ca57828181518110151561156857fe5b90602001906020020151848281518110151561158057fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b8080600101915050611552565b5b505050919050565b60055481565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561161357600080fd5b600380549050816032821115801561162b5750818111155b8015611638575060008114155b8015611645575060008214155b151561165057600080fd5b826004819055507fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a836040518082815260200191505060405180910390a15b5b50505b50565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615156116ef57600080fd5b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151561174b57600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515156117b757600080fd5b600180600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef60405160405180910390a361186c85611bc0565b5b5b50505b505b5050565b6000611884848484611e6c565b905061188f81611696565b5b9392505050565b603281565b60045481565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156118de57600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561193757600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151561199157600080fd5b600092505b600380549050831015611a7f578473ffffffffffffffffffffffffffffffffffffffff166003848154811015156119c957fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611a715783600384815481101515611a2257fe5b906000526020600020900160005b6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611a7f565b5b8280600101935050611996565b6000600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508473ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a28373ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25b5b505b505b505050565b600033600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611c1b57600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611c8657600080fd5b8460008082815260200190815260200160002060030160009054906101000a900460ff16151515611cb657600080fd5b611cbf86610f99565b15611e6057600080878152602001908152602001600020945060018560030160006101000a81548160ff021916908315150217905550611ddd8560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866001015487600201805460018160011615610100020316600290049050886002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611dd35780601f10611da857610100808354040283529160200191611dd3565b820191906000526020600020905b815481529060010190602001808311611db657829003601f168201915b5050505050611fc0565b15611e1457857f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7560405160405180910390a2611e5f565b857f526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b7923660405160405180910390a260008560030160006101000a81548160ff0219169083151502179055505b5b5b5b505b50505b505050565b60008360008173ffffffffffffffffffffffffffffffffffffffff1614151515611e9557600080fd5b60055491506080604051908101604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018481526020016000151581525060008084815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101556040820151816002019080519060200190611f54929190612068565b5060608201518160030160006101000a81548160ff0219169083151502179055509050506001600560008282540192505081905550817fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5160405160405180910390a25b5b509392505050565b6000806040516020840160008287838a8c6187965a03f1925050508091505b50949350505050565b81548183558181151161200f5781836000526020600020918201910161200e91906120e8565b5b505050565b81548183558181151161203b5781836000526020600020918201910161203a91906120e8565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106120a957805160ff19168380011785556120d7565b828001600101855582156120d7579182015b828111156120d65782518255916020019190600101906120bb565b5b5090506120e491906120e8565b5090565b61210a91905b808211156121065760008160009055506001016120ee565b5090565b905600a165627a7a72305820f1129b699b3017535535a920e15503cd06af1f5c77637c0637cc29355b1dad3400290000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000cb1437200aea736788f1fc56f327c0456c3598d00000000000000000000000074dd76e24b2cfb43c1b1a4498295d553d0843746000000000000000000000000eeb4ceee443f9e0d17bdbd6daa241681ee5e51c2000000000000000000000000a005caea55375ae20e3aaef746113535503abc19" + }, + "0x0cB1437200aea736788f1Fc56F327c0456c3598D": { + "balance": "250000000000000000" + }, + "0x74dd76E24B2CFB43C1b1a4498295d553D0843746": { + "balance": "250000000000000000" + }, + "0xeeB4CEEe443F9e0D17BdBD6Daa241681EE5E51c2": { + "balance": "250000000000000000" + }, + "0xA005caEa55375ae20e3aAEF746113535503ABC19": { + "balance": "250000000000000000" + }, + "0x1204700000000000000000000000000000000001": { + "constructor": "0x60806040523480156200001157600080fd5b5060405162002f1538038062002f15833981018060405260608110156200003757600080fd5b81019080805190602001909291908051906020019092919080516401000000008111156200006457600080fd5b828101905060208101848111156200007b57600080fd5b81518560208202830111640100000000821117156200009957600080fd5b5050929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018062002ec56024913960400191505060405180910390fd5b60018151101562000242576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018062002ee9602c913960400191505060405180910390fd5b6200025c8362000473640100000000026401000000009004565b6200027682620005d5640100000000026401000000009004565b60008090505b81518110156200042057600073ffffffffffffffffffffffffffffffffffffffff16828281518110620002ab57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614156200033e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f56616c696461746f7220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b6001600360008484815181106200035157fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff02191690836003811115620003b257fe5b02179055508060036000848481518110620003c957fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018190555080806001019150506200027c565b508060029080519060200190620004399291906200065c565b50600260019080546200044e929190620006eb565b506001600060146101000a81548160ff02191690831515021790555050505062000788565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141562000517576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6577206f776e657220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b80600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fe8ec518081a7aa1fc5d586a5443a858ab130be8b8e39b545172c879a7e242c6b60405160405180910390a250565b828054828255906000526020600020908101928215620006d8579160200282015b82811115620006d75782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906200067d565b5b509050620006e7919062000742565b5090565b8280548282559060005260206000209081019282156200072f5760005260206000209182015b828111156200072e57825482559160010191906001019062000711565b5b5090506200073e919062000742565b5090565b6200078591905b808211156200078157600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555060010162000749565b5090565b90565b61272d80620007986000396000f3fe608060405234801561001057600080fd5b506004361061015f576000357c0100000000000000000000000000000000000000000000000000000000900480639f723637116100d5578063b980490911610099578063b980490914610594578063bd21442a146105f0578063c805f68b146106b3578063d826b7f1146106f7578063f2fde38b14610765578063f3aeac02146107a95761015f565b80639f7236371461040e578063a00745b61461046d578063a6940b07146104c9578063b3f05b9714610513578063b7ab4db5146105355761015f565b8063455701d611610127578063455701d6146102eb5780634d238c8e1461034a578063715018a61461038e57806375286211146103985780638da5cb5b146103a25780638f32d59b146103ec5761015f565b8063267fa41d1461016457806334ba3c1b146101c057806340550a1c146101de57806340a141ff1461023a578063418349551461027e575b600080fd5b6101a66004803603602081101561017a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610805565b604051808215151515815260200191505060405180910390f35b6101c8610877565b6040518082815260200191505060405180910390f35b610220600480360360208110156101f457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610884565b604051808215151515815260200191505060405180910390f35b61027c6004803603602081101561025057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610965565b005b6102c06004803603602081101561029457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ab0565b604051808360038111156102d057fe5b60ff1681526020018281526020019250505060405180910390f35b6102f3610ae1565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561033657808201518184015260208101905061031b565b505050509050019250505060405180910390f35b61038c6004803603602081101561036057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b6f565b005b610396610d79565b005b6103a0610eb2565b005b6103aa611328565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103f4611351565b604051808215151515815260200191505060405180910390f35b6104166113a8565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561045957808201518184015260208101905061043e565b505050509050019250505060405180910390f35b6104af6004803603602081101561048357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506114d7565b604051808215151515815260200191505060405180910390f35b6104d16115b8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61051b6115de565b604051808215151515815260200191505060405180910390f35b61053d6115f1565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610580578082015181840152602081019050610565565b505050509050019250505060405180910390f35b6105d6600480360360208110156105aa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061167f565b604051808215151515815260200191505060405180910390f35b6106b16004803603608081101561060657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561066d57600080fd5b82018360208201111561067f57600080fd5b803590602001918460018302840111640100000000831117156106a157600080fd5b90919293919293905050506116f0565b005b6106f5600480360360208110156106c957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061194c565b005b6107636004803603606081101561070d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611aff565b005b6107a76004803603602081101561077b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611d59565b005b6107eb600480360360208110156107bf57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611ddf565b604051808215151515815260200191505060405180910390f35b60006001600381111561081457fe5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16600381111561086f57fe5b149050919050565b6000600180549050905090565b60006001600381111561089357fe5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1660038111156108ee57fe5b148061095e575060038081111561090157fe5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16600381111561095c57fe5b145b9050919050565b61096d611351565b6109df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b600060149054906101000a900460ff16610a44576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806126736022913960400191505060405180910390fd5b80610a4e81610884565b610aa3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806126516022913960400191505060405180910390fd5b610aac82611e51565b5050565b60036020528060005260406000206000915090508060000160009054906101000a900460ff16908060010154905082565b60606002805480602002602001604051908101604052809291908181526020018280548015610b6557602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610b1b575b5050505050905090565b610b77611351565b610be9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b600060149054906101000a900460ff16610c4e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806126736022913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610cf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f56616c696461746f7220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b610cfa81610884565b15610d6d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f546869732076616c696461746f7220697320616c72656164792061637469766581525060200191505060405180910390fd5b610d76816120a4565b50565b610d81611351565b610df3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600060149054906101000a900460ff1615610f35576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f56616c696461746f72207365742069732066696e616c697a656400000000000081525060200191505060405180910390fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ff8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616c6c6572206973206e6f74207468652052656c617920636f6e747261637481525060200191505060405180910390fd5b6001600060146101000a81548160ff02191690831515021790555060008090505b6002805490508110156110dd576000600360006002848154811061103957fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060018160000160006101000a81548160ff021916908360038111156110c157fe5b0217905550818160010181905550508080600101915050611019565b50600073ffffffffffffffffffffffffffffffffffffffff16600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461126757600060036000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff021916908360038111156111b557fe5b0217905550600060036000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b6002600190805461127992919061251f565b507f8564cd629b15f47dc310d45bcbfc9bcf5420b0d51bf0659a16c67f91d276325360016040518080602001828103825283818154815260200191508054801561131857602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116112ce575b50509250505060405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6060600180549050600280549050111561144a57600280548060200260200160405190810160405280929190818152602001828054801561143e57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116113f4575b505050505090506114d4565b60018054806020026020016040519081016040528092919081815260200182805480156114cc57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611482575b505050505090505b90565b6000600260038111156114e657fe5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16600381111561154157fe5b14806115b1575060038081111561155457fe5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1660038111156115af57fe5b145b9050919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060149054906101000a900460ff1681565b6060600180548060200260200160405190810160405280929190818152602001828054801561167557602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161162b575b5050505050905090565b600060038081111561168d57fe5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1660038111156116e857fe5b149050919050565b846116fa81610884565b61174f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806126516022913960400191505060405180910390fd5b8461175981610884565b6117ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806126516022913960400191505060405180910390fd5b84438110611824576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f426c6f636b206e756d626572206973206e6f742076616c69640000000000000081525060200191505060405180910390fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146118e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616c6c6572206973206e6f74207468652052656c617920636f6e747261637481525060200191505060405180910390fd5b858773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff167f729a19138e072a5a8d3a56d74ae0b5c84530f09aacd6e12b24c5b2fdc3f8a3d060405160405180910390a45050505050505050565b611954611351565b6119c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611a4c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806126066024913960400191505060405180910390fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611af3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260408152602001806126956040913960400191505060405180910390fd5b611afc81612179565b50565b82611b0981610884565b611b5e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806126516022913960400191505060405180910390fd5b82611b6881610884565b611bbd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806126516022913960400191505060405180910390fd5b82438110611c33576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f426c6f636b206e756d626572206973206e6f742076616c69640000000000000081525060200191505060405180910390fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611cf6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616c6c6572206973206e6f74207468652052656c617920636f6e747261637481525060200191505060405180910390fd5b838573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fbc459bd9db54016b1966d0fe812bbe0a82cd627ae3eacd01727dc63a432ca41b60405160405180910390a4505050505050565b611d61611351565b611dd3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b611ddc81612200565b50565b600060026003811115611dee57fe5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff166003811115611e4957fe5b149050919050565b600160028054905011611eaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061262a6027913960400191505060405180910390fd5b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154905060006001600280549050039050600060028281548110611f1257fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508060028481548110611f4d57fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506002805480919060019003611ff19190612571565b5060038060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083600381111561205057fe5b021790555083600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061209e612361565b50505050565b6002600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083600381111561210357fe5b021790555060028190806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050612176612361565b50565b80600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fe8ec518081a7aa1fc5d586a5443a858ab130be8b8e39b545172c879a7e242c6b60405160405180910390a250565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156122a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6577206f776e657220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008060146101000a81548160ff021916908315150217905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a084718a600143034060026040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083815260200180602001828103825283818154815260200191508054801561246c57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311612422575b50509350505050602060405180830381600087803b15801561248d57600080fd5b505af11580156124a1573d6000803e3d6000fd5b505050506040513d60208110156124b757600080fd5b810190808051906020019092919050505061251d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d8152602001806126d5602d913960400191505060405180910390fd5b565b8280548282559060005260206000209081019282156125605760005260206000209182015b8281111561255f578254825591600101919060010190612544565b5b50905061256d919061259d565b5090565b8154818355818111156125985781836000526020600020918201910161259791906125e0565b5b505050565b6125dd91905b808211156125d957600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016125a3565b5090565b90565b61260291905b808211156125fe5760008160009055506001016125e6565b5090565b9056fe52656c617920636f6e747261637420616464726573732063616e6e6f74206265203078305468657265206d757374206265206174206c6561737420312076616c696461746f72206c65667441646472657373206973206e6f7420616e206163746976652076616c696461746f7256616c696461746f7220736574206973206e6f742066696e616c697a6564207965744e65772072656c617920636f6e747261637420616464726573732063616e6e6f74206265207468652073616d65206173207468652063757272656e74206f6e6552656c617920636f6e747261637420496e6974696174654368616e67652063616c6c6261636b206661696c6564a165627a7a72305820c6b083565ee91eecaf8e5a6f14e1677206b36466bdfe0248a47919657b68255b002952656c617920636f6e747261637420616464726573732063616e6e6f74206265203078305468657265206d757374206265206174206c6561737420312076616c696461746f7220696e697469616c6c79000000000000000000000000120470000000000000000000000000000000000500000000000000000000000012047000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000300000000000000000000000036f67dd84e7327c10c7ead6c429a47189798fbdc00000000000000000000000020df7a4e8408add37c6a5c4afc1b1509924619fe00000000000000000000000077901f14183b1669c80e8c6137ff6721c9a26b25" + }, + "0x1204700000000000000000000000000000000000": { + "constructor": "0x608060405273fffffffffffffffffffffffffffffffffffffffe600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561006557600080fd5b506040516040806116c18339810180604052604081101561008557600080fd5b810190808051906020019092919080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a361017482610193640100000000026401000000009004565b61018c816102f4640100000000026401000000009004565b5050610506565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610236576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6577206f776e657220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610398576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416464726573732063616e6e6f7420626520307830000000000000000000000081525060200191505060405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561043f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604281526020018061167f6042913960600191505060405180910390fd5b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f4fea88aaf04c303804bb211ecc32a00ac8e5f0656bb854cad8a4a2e438256b7460405160405180910390a3505050565b61116a806105156000396000f3fe608060405234801561001057600080fd5b50600436106100d1576000357c010000000000000000000000000000000000000000000000000000000090048063b7ab4db51161008e578063b7ab4db51461023b578063bd9656771461029a578063c476dd40146102de578063d3e848f114610381578063d69f13bb146103cb578063f2fde38b14610419576100d1565b8063715018a6146100d657806375286211146100e05780638da5cb5b146100ea5780638f32d59b14610134578063a084718a14610156578063ae3783d6146101f1575b600080fd5b6100de61045d565b005b6100e8610596565b005b6100f26106f9565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61013c610722565b604051808215151515815260200191505060405180910390f35b6101d76004803603604081101561016c57600080fd5b81019080803590602001909291908035906020019064010000000081111561019357600080fd5b8201836020820111156101a557600080fd5b803590602001918460208302840111640100000000831117156101c757600080fd5b9091929391929390505050610779565b604051808215151515815260200191505060405180910390f35b6101f9610893565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102436108b9565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561028657808201518184015260208101905061026b565b505050509050019250505060405180910390f35b6102dc600480360360208110156102b057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506109d5565b005b61037f600480360360608110156102f457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561033b57600080fd5b82018360208201111561034d57600080fd5b8035906020019184600183028401116401000000008311171561036f57600080fd5b9091929391929390505050610a5b565b005b610389610ba6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610417600480360360408110156103e157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610bcc565b005b61045b6004803603602081101561042f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ce1565b005b610465610722565b6104d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610659576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f53656e646572206973206e6f742073797374656d00000000000000000000000081525060200191505060405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663752862116040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401600060405180830381600087803b1580156106df57600080fd5b505af11580156106f3573d6000803e3d6000fd5b50505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610821576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061111d6022913960400191505060405180910390fd5b837f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89848460405180806020018281038252848482818152602001925060200280828437600081840152601f19601f820116905080830192505050935050505060405180910390a2600190509392505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b7ab4db56040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801561093f57600080fd5b505afa158015610953573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561097d57600080fd5b81019080805164010000000081111561099557600080fd5b828101905060208101848111156109ab57600080fd5b81518560208202830111640100000000821117156109c857600080fd5b5050929190505050905090565b6109dd610722565b610a4f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b610a5881610d67565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bd21442a33868686866040518663ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509650505050505050600060405180830381600087803b158015610b8857600080fd5b505af1158015610b9c573d6000803e3d6000fd5b5050505050505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d826b7f13384846040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050600060405180830381600087803b158015610cc557600080fd5b505af1158015610cd9573d6000803e3d6000fd5b505050505050565b610ce9610722565b610d5b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b610d6481610f79565b50565b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610e0b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416464726573732063616e6e6f7420626520307830000000000000000000000081525060200191505060405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610eb2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260428152602001806110db6042913960600191505060405180910390fd5b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f4fea88aaf04c303804bb211ecc32a00ac8e5f0656bb854cad8a4a2e438256b7460405160405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561101c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6577206f776e657220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fe4e65772072656c6179656420636f6e747261637420616464726573732063616e6e6f74206265207468652073616d65206173207468652063757272656e74206f6e6553656e646572206973206e6f74207468652052656c6179656420636f6e7472616374a165627a7a72305820df8e72037cf9237ba09d135b3962a00a0186ba17dcbbe421274543975b2c346100294e65772072656c6179656420636f6e747261637420616464726573732063616e6e6f74206265207468652073616d65206173207468652063757272656e74206f6e6500000000000000000000000012047000000000000000000000000000000000050000000000000000000000001204700000000000000000000000000000000001" + }, + "0x1204700000000000000000000000000000000002": { + "constructor": "0x608060405273fffffffffffffffffffffffffffffffffffffffe600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200006657600080fd5b5060405160408062001b22833981018060405260408110156200008857600080fd5b810190808051906020019092919080519060200190929190505050620000bc6200010c640100000000026401000000009004565b81600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600a81905550505062000825565b60405180610f0001604052806704398372e97bae8081526020016704398372e97bae8081526020016704398372e97bae8081526020016704398372e97bae8081526020016704398372e97bae8081526020016704398372e97bae8081526020016704398372e97bae8081526020016704395680a6af46808152602001670438cfa9de4a0e808152602001670437eeee904c06808152602001670436b44ebcb52e8081526020016704351fca638586808152602001670433316184bd0e808152602001670430e914205bc680815260200167042e46e23661ae80815260200167042b4acbc6cec6808152602001670427f4d0d1a30e80815260200167042444f156de868081526020016704203b2d56812e80815260200167041bd784d08b0680815260200167041719f7c4fc0e808152602001670412028633d44680815260200167040c91301d13ae808152602001670406c5f580ba46808152602001670400a0d65ec80e8081526020016703fa21d2b73d068081526020016703f348ea8a192e8081526020016703ec161dd75c868081526020016703e4896c9f070e8081526020016703dca2d6e118c68081526020016703d4625c9d91ae8081526020016703cbc7fdd471c68081526020016703c2d3ba85b90e8081526020016703b98592b167868081526020016703afdd86577d2e8081526020016703a5db9577fa0680815260200167039b7fc012de0e808152602001670390ca06282946808152602001670385ba67b7dbae80815260200167037a50e4c1f54680815260200167036e8d7d46760e8081526020016703627031455e06808152602001670355f900bead2e80815260200167034927ebb2638680815260200167033bfcf220810e80815260200167032e78140905c680815260200167032099516bf1ae80815260200167031260aa4944c6808152602001670303ce1ea0ff0e8081526020016702f4e1ae7320868081526020016702e59b59bfa92e8081526020016702d5fb208699068081526020016702c60102c7f00e8081526020016702b5ad0083ae468081526020016702a4ff19b9d3ae808152602001670293f74e6a6046808152602001670282959e95540e808152602001670270da0a3aaf0680815260200167025ec4915a712e80815260200167024c5533f49a86808152602001670238da1d6b04400081526020016702260c5cdf4d240081526020016702138f83989f90008152602001670201639196fb840081526020016701ef8886da61000081526020016701ddfe6362d0040081526020016701ccc5273048900081526020016701bbdcd242caa40081526020016701ab45649a564000815260200167019afede36eb6400815260200167018b093f188a1000815260200167017b64873f324400815260200167016c10b6aae40000815260200167015d0dcd5b9f4400815260200167014e5bcb51641000815260200167013ffab08c3264008152602001670131ea7d0c0a400081526020016701242b30d0eba4008152602001670116bccbdad6900081526020016701099f4e29cb0400815260200166fcd2b7bdc90000815260200166f0570896d08400815260200166e42c40b4e19000815260200166d8526017fc2400815260200166ccc966c0204000815260200166c19154ad4de400815260200166b6aa29df851000815260200166ac13e656c5c400815260200166a1ce8a1310000081526020016697da151463c4008152602001668e36875ac1100081526020016684e3e0e627e4008152602001667be221b6984000815260200166733149cc1224008152602001666ad1592695900081526020016662c24fc62284008152602001665b042daab900008152602001665396f2d45904008152602001664c7a9f4302900081526020016645af32f6b5a4008152602001663f34adef724000815260200166390b102d386400815260200166333259b00810008152602001662daa8a77e144008152602001662873a284c40000815260200166238da1d6b044008152602001661ef8886da610008152602001661ab45649a5640081526020016616c10b6aae4000815260200166131ea7d0c0a4008152602001660fcd2b7bdc90008152602001660ccc966c0204008152602001660a1ce8a131000081526020016607be221b69840081526020016605b042daab900081526020016603f34adef7240081526020016602873a284c4000815260200166016c10b6aae400815260200165a1ce8a1310008152602001652873a284c40081525060009060786200078e929190620007ab565b506208052060018190555060008054905060015402600281905550565b828054828255906000526020600020908101928215620007ea579160200282015b82811115620007e9578251825591602001919060010190620007cc565b5b509050620007f99190620007fd565b5090565b6200082291905b808211156200081e57600081600090555060010162000804565b5090565b90565b6112ed80620008356000396000f3fe608060405234801561001057600080fd5b5060043610610132576000357c0100000000000000000000000000000000000000000000000000000000900480634476d66a116100bf57806394f7f62b1161008e57806394f7f62b14610451578063df6a503014610493578063e6e100db146104b1578063f91c289814610509578063fb1ac5251461067457610132565b80634476d66a14610363578063553a5c85146103a557806358ceb672146103c357806360d4b8be146103cd57610132565b80631a488047116101065780631a4880471461020357806330f6eb161461022157806333ea51a81461028357806337339a16146102c75780633d84b8c11461030b57610132565b8062f380f414610137578063078d8e7a146101815780630f411cdb146101a357806318129375146101c1575b600080fd5b61013f610692565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101896106b8565b604051808215151515815260200191505060405180910390f35b6101ab6106c8565b6040518082815260200191505060405180910390f35b6101ed600480360360208110156101d757600080fd5b81019080803590602001909291905050506106ce565b6040518082815260200191505060405180910390f35b61020b6106ef565b6040518082815260200191505060405180910390f35b61026d6004803603604081101561023757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506106f5565b6040518082815260200191505060405180910390f35b6102c56004803603602081101561029957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061071a565b005b610309600480360360208110156102dd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061079b565b005b61034d6004803603602081101561032157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108a2565b6040518082815260200191505060405180910390f35b61038f6004803603602081101561037957600080fd5b81019080803590602001909291905050506108ba565b6040518082815260200191505060405180910390f35b6103ad6108d2565b6040518082815260200191505060405180910390f35b6103cb6108d8565b005b61040f600480360360208110156103e357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061093c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61047d6004803603602081101561046757600080fd5b810190808035906020019092919050505061096f565b6040518082815260200191505060405180910390f35b61049b6109b3565b6040518082815260200191505060405180910390f35b6104f3600480360360208110156104c757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506109b9565b6040518082815260200191505060405180910390f35b6105d56004803603604081101561051f57600080fd5b810190808035906020019064010000000081111561053c57600080fd5b82018360208201111561054e57600080fd5b8035906020019184602083028401116401000000008311171561057057600080fd5b90919293919293908035906020019064010000000081111561059157600080fd5b8201836020820111156105a357600080fd5b803590602001918460208302840111640100000000831117156105c557600080fd5b90919293919293905050506109d1565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561061c578082015181840152602081019050610601565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561065e578082015181840152602081019050610643565b5050505090500194505050505060405180910390f35b61067c610eca565b6040518082815260200191505060405180910390f35b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006106c343610ed0565b905090565b60025481565b600081815481106106db57fe5b906000526020600020016000915090505481565b600a5481565b6008602052816000526040600020602052806000526040600020600091509150505481565b80600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461085e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616c6c6572206973206e6f742074686520636f6d6d756e6974792066756e6481525060200191505060405180910390fd5b80600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60066020528060005260406000206000915090505481565b60076020528060005260406000206000915090505481565b60035481565b600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055565b600c6020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061097a82610ed0565b1561098857600090506109ae565b6000600154838161099557fe5b04815481106109a057fe5b906000526020600020015490505b919050565b60045481565b60056020528060005260406000206000915090505481565b606080600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a97576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f43616c6c6572206973206e6f74207468652073797374656d000000000000000081525060200191505060405180910390fd5b838390508686905014610af5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061129d6025913960400191505060405180910390fd5b60018686905014610b6e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f42656e65666163746f7273206c697374206c656e677468206973206e6f74203181525060200191505060405180910390fd5b600084846000818110610b7d57fe5b9050602002013561ffff1661ffff1614610be2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061127b6022913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1686866000818110610c0757fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161480610c4b5750610c4a43610ed0565b5b15610cc1576000604051908082528060200260200182016040528015610c805781602001602082028038833980820191505090505b506000604051908082528060200260200182016040528015610cb15781602001602082028038833980820191505090505b5081915080905091509150610ec1565b60606002604051908082528060200260200182016040528015610cf35781602001602082028038833980820191505090505b50905060608151604051908082528060200260200182016040528015610d285781602001602082028038833980820191505090505b509050610d5d88886000818110610d3b57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff16610edf565b82600081518110610d6a57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610dad4361096f565b81600081518110610dba57fe5b602002602001018181525050610df1600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16610edf565b82600181518110610dfe57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600a5481600181518110610e4857fe5b602002602001018181525050610e8682600081518110610e6457fe5b602002602001015182600081518110610e7957fe5b6020026020010151610f8c565b610eb882600181518110610e9657fe5b602002602001015182600181518110610eab57fe5b6020026020010151611134565b81819350935050505b94509492505050565b60015481565b60006002548210159050919050565b600080600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610f825782915050610f87565b809150505b919050565b610fef81600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000438152602001908152602001600020546111f290919063ffffffff16565b600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060004381526020019081526020016000208190555061109581600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111f290919063ffffffff16565b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506110fe8160076000438152602001908152602001600020546111f290919063ffffffff16565b600760004381526020019081526020016000208190555061112a816003546111f290919063ffffffff16565b6003819055505050565b611149816004546111f290919063ffffffff16565b6004819055506111a181600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111f290919063ffffffff16565b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506111ee8282610f8c565b5050565b600080828401905083811015611270576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f4f766572666c6f77206572726f7200000000000000000000000000000000000081525060200191505060405180910390fd5b809150509291505056fe42656e65666163746f72206973206e6f742074686520626c6f636b20617574686f7242656e65666163746f72732f7479706573206c697374206c656e6774682064696666657273a165627a7a723058209c17c14dc9f6fcdd3ddef3913263be4e76376e948facfc131a975ceda79ba0d6002900000000000000000000000012047000000000000000000000000000000000030000000000000000000000000000000000000000000000000856d3dfb6e26d00" + }, + "0x1204700000000000000000000000000000000004": { + "balance": "40789499640000000000000000", + "constructor": "0x608060405260006001556a21bd8334ca74c3834c00003073ffffffffffffffffffffffffffffffffffffffff16311462000085576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602381526020018062001b5b6023913960400191505060405180910390fd5b6200009e6200010b640100000000026401000000009004565b6a21bd8334ca74c3834c00006001541462000105576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602881526020018062001b0a6028913960400191505060405180910390fd5b620017b4565b6200014a73120470000000000000000000000000000000000a6a084595161401484a000000635d408564620016da640100000000026401000000009004565b62000188735a3977e000000000000000000000000000000000691a784379d99db4200000635db8d244620016da640100000000026401000000009004565b620001c673aae0debd2a4c519364e6098537145369913b26ec6901c761ff4c24e9210000635db8d244620016da640100000000026401000000009004565b620002047336874a6000000000000000000000000000000000691a784379d99db4200000635db8d244620016da640100000000026401000000009004565b6200024273108dd64c9e0d603d56304e97656e011831ed07ff6901c761ff4c24e9210000635db8d244620016da640100000000026401000000009004565b6200028073294f3750000000000000000000000000000000006934f086f3b33b68400000635db8d244620016da640100000000026401000000009004565b620002be732fb294a0000000000000000000000000000000006902d2cd1fdffd73150000635db8d244620016da640100000000026401000000009004565b620002fc73102fb040000000000000000000000000000000006901c3c02f7b2019f50000635db8d244620016da640100000000026401000000009004565b6200033a732b250010000000000000000000000000000000006902a5a058fc295ed00000635db8d244620016da640100000000026401000000009004565b620003787335c468d000000000000000000000000000000000696abafbb89b2adcd80000635db8d244620016da640100000000026401000000009004565b620003b673c8be7a00000000000000000000000000000000006901c3c02f7b2019f50000635db8d244620016da640100000000026401000000009004565b620003f47353f3170000000000000000000000000000000000692004e50f922be25a0000635db8d244620016da640100000000026401000000009004565b6200043373dc918900000000000000000000000000000000006a0215a6ea9b07d650380000635db8d244620016da640100000000026401000000009004565b6200047173b476ee7d610dae7b23b671ebc7bd6112e97729696902a5a058fc295ed00000635db8d244620016da640100000000026401000000009004565b620004af732908b900000000000000000000000000000000006969e10de76676d0800000635d408564620016da640100000000026401000000009004565b620004ed733b2ef740000000000000000000000000000000006901c3c02f7b2019f50000635db8d244620016da640100000000026401000000009004565b6200052b731153818a2eb49f0a71b27313c32814fc02e4db50694220bb939da668600000635db8d244620016da640100000000026401000000009004565b6200056973330d6100000000000000000000000000000000006923466459b949a9950000635db8d244620016da640100000000026401000000009004565b620005a7733e5518c20876eab3a42969d032fa7c30599af912691a784379d99db4200000635db8d244620016da640100000000026401000000009004565b620005e57357f33efad76d4b783cf42c9e6cb08f4425dfe96e6902a5a058fc295ed00000635db8d244620016da640100000000026401000000009004565b6200062373a87e88f0bbc43468cb657294f2479c6f35179b80692004e50f922be25a0000635db8d244620016da640100000000026401000000009004565b62000661734cebef90000000000000000000000000000000006934f086f3b33b68400000635db8d244620016da640100000000026401000000009004565b6200069f73511909cef97475819de66b645f13464285c227ce6934f086f3b33b68400000635db8d244620016da640100000000026401000000009004565b620006dd7322fc2310000000000000000000000000000000006902a5a058fc295ed00000635db8d244620016da640100000000026401000000009004565b6200071b7347919fb8d4e7e360bef0d5a7a2411593dbcc0e776902a5a058fc295ed00000635db8d244620016da640100000000026401000000009004565b6200075973949423db1bfee1ddec99c9d24a12a6ea27cb34896901c3c02f7b2019f50000635db8d244620016da640100000000026401000000009004565b620007977343ec5680000000000000000000000000000000006907f0e10af47c1c700000635db8d244620016da640100000000026401000000009004565b620007d57367cf1c40622f39fa067b614f13aad6da5dd95f326969e10de76676d0800000635d408564620016da640100000000026401000000009004565b620008137310b9390000000000000000000000000000000000692ab13175efe0a8630000635db8d244620016da640100000000026401000000009004565b620008517376b707604cbd862050b938739637b7bde1b7ad486901c3c02f7b2019f50000635db8d244620016da640100000000026401000000009004565b6200088f73568075f0000000000000000000000000000000006934f086f3b33b68400000635db8d244620016da640100000000026401000000009004565b620008cd73d44fb8de580d34f44789408cc9335c9a9ce0ce4d691ad0235eb930a0540000635db8d244620016da640100000000026401000000009004565b6200090a727801b12345b6f10b69263cd6d4fc50b58c8d80696d688e69e3a9742b0000635db8d244620016da640100000000026401000000009004565b62000948735d66a150000000000000000000000000000000006969e10de76676d0800000635d408564620016da640100000000026401000000009004565b62000987731d258680000000000000000000000000000000006a020057f2c74d5a91080000635db8d244620016da640100000000026401000000009004565b620009c57330e311c00000000000000000000000000000000069355d7ddc4d956e6c0000635db8d244620016da640100000000026401000000009004565b62000a0373428ab4b019ee3a9b9863b2b4bf1885ce6dff9a736902a5a058fc295ed00000635db8d244620016da640100000000026401000000009004565b62000a41738081f20000000000000000000000000000000000691a784379d99db4200000635db8d244620016da640100000000026401000000009004565b62000a7f735305c8071b604da7fb45059e7ebfa1d674ddfc3569038780827d32a3ab0000635db8d244620016da640100000000026401000000009004565b62000abd7335007170000000000000000000000000000000006901c3c02f7b2019f50000635db8d244620016da640100000000026401000000009004565b62000afc733484c850000000000000000000000000000000006a0422ca8b0a00a42500000063608a9f84620016da640100000000026401000000009004565b62000b3a73ffd9b871df6e93803c0877e98fc1722b39c00d786902a5a058fc295ed00000635db8d244620016da640100000000026401000000009004565b62000b787396a5eb172efdf262ed6beaaf0e20c6af71831fc96934f086f3b33b68400000635db8d244620016da640100000000026401000000009004565b62000bb6732dd2e140000000000000000000000000000000006901c3c02f7b2019f50000635db8d244620016da640100000000026401000000009004565b62000bf473656e5569bef7781bf0db199d32027766053501ff69438ec266600555e00000635db8d244620016da640100000000026401000000009004565b62000c32731d53db7000000000000000000000000000000000691a784379d99db4200000635db8d244620016da640100000000026401000000009004565b62000c7073b5b6d8885fbf28f843cc7886de242b811d6952056901c3c02f7b2019f50000635db8d244620016da640100000000026401000000009004565b62000cae734549ef8e287b94f1c0a8b88f55ed8707d74d843c6934f086f3b33b68400000635db8d244620016da640100000000026401000000009004565b62000cec73dacd80d8e1d4f117515caa477ee7599cdfc766196902a5a058fc295ed00000635db8d244620016da640100000000026401000000009004565b62000d2a731f603e000000000000000000000000000000000069d3c21bcecceda1000000635db8d244620016da640100000000026401000000009004565b62000d68735548f000000000000000000000000000000000006902ab1310b5b095920000635db8d244620016da640100000000026401000000009004565b62000da6735bb9ba00000000000000000000000000000000006934f086f3b33b68400000635db8d244620016da640100000000026401000000009004565b62000de4736dd10e41a7a84fe23ab35fefa2f46c9895f87a2d693c8c4bde2deef1680000635db8d244620016da640100000000026401000000009004565b62000e227316337db0000000000000000000000000000000006901c3c02f7b2019f50000635db8d244620016da640100000000026401000000009004565b62000e6073b999004b49c6b907d4278067da5c85195dcd7fc769081e0dd1d85030b50000635db8d244620016da640100000000026401000000009004565b62000e9e733dbb2290000000000000000000000000000000006934f086f3b33b68400000635db8d244620016da640100000000026401000000009004565b62000edc73559da540000000000000000000000000000000006934f086f3b33b68400000635db8d244620016da640100000000026401000000009004565b62000f1a733a9d83766c03c465851a38daa364ef7deccd1ece6934f086f3b33b68400000635db8d244620016da640100000000026401000000009004565b62000f5873b61c11b6e42d459efaee8995c44db08507e468e169477d5529f68a63000000635db8d244620016da640100000000026401000000009004565b62000f9673e803d7955a911106cb8fd79049a2374ff059000369038780827d32a3ab0000635db8d244620016da640100000000026401000000009004565b62000fd473509b057000000000000000000000000000000000691aaebeee26cab7360000635db8d244620016da640100000000026401000000009004565b620010127383980db85394d7c1610f37a90be744432368bad4692393a931b168245d0000635db8d244620016da640100000000026401000000009004565b6200105073db6cc57168c07b83a00f1f8871538446068824fc691a784379d99db4200000635db8d244620016da640100000000026401000000009004565b6200108e735035fba0000000000000000000000000000000006934f086f3b33b68400000635db8d244620016da640100000000026401000000009004565b620010cc73d96c8300000000000000000000000000000000006901c3c02f7b2019f50000635db8d244620016da640100000000026401000000009004565b6200110b7331178cd0000000000000000000000000000000006a042b4dd5360faca070000063608a9f84620016da640100000000026401000000009004565b62001149732f531158e2305ed4fb4144a2f4085e3d96e1982e6934f086f3b33b68400000635db8d244620016da640100000000026401000000009004565b62001188735d5da310000000000000000000000000000000006a017293b0a9e69fd9c00000635db8d244620016da640100000000026401000000009004565b620011c67318b9347000000000000000000000000000000000696abafbb89b2adcd80000635d408564620016da640100000000026401000000009004565b62001203722d4606b65c033769968bcdc63881b90b0853f5692648770b742bb90b0000635db8d244620016da640100000000026401000000009004565b62001241731faa8d10000000000000000000000000000000006969e10de76676d0800000635d408564620016da640100000000026401000000009004565b6200127f7333445720000000000000000000000000000000006902a5a058fc295ed00000635db8d244620016da640100000000026401000000009004565b620012bd730d1d4e623d10f9fba5db95830f7d3839406c6af26901c3c02f7b2019f50000635db8d244620016da640100000000026401000000009004565b620012fa72c2f65230815d30eaa1a4d057bcf0b72fe3cc4e6902a5a058fc295ed00000635db8d244620016da640100000000026401000000009004565b62001338739c3a5ec7bd63ecac1b92abe4b01b12ffd50bf3f26969e10de76676d0800000635d408564620016da640100000000026401000000009004565b620013767345635660000000000000000000000000000000006969e10de76676d0800000635d408564620016da640100000000026401000000009004565b620013b2739be61e41490f5227080fa1adbe3ec0a973d59732678ac7230489e80000635cc83884620016da640100000000026401000000009004565b620013f073572f91b0000000000000000000000000000000006934f086f3b33b68400000635db8d244620016da640100000000026401000000009004565b6200142e7339350e4a75d1e50a5072950325328884c11c12326901c761ff4c24e9210000635db8d244620016da640100000000026401000000009004565b6200146c733c96a530000000000000000000000000000000006969e10de76676d0800000635d408564620016da640100000000026401000000009004565b620014aa730ad7ba4af33b485e6f2505c417554631a3e5643f6902a5a058fc295ed00000635db8d244620016da640100000000026401000000009004565b620014e8735eea7250000000000000000000000000000000006901c3c02f7b2019f50000635db8d244620016da640100000000026401000000009004565b62001526733ab790e0000000000000000000000000000000006902a5a058fc295ed00000635db8d244620016da640100000000026401000000009004565b62001564734cf84620000000000000000000000000000000006902a5a058fc295ed00000635db8d244620016da640100000000026401000000009004565b620015a2735425f6f0000000000000000000000000000000006969e10de76676d0800000635d408564620016da640100000000026401000000009004565b620015e0736d516767e4068fc331bdb331fba7578bdb07a68c69234b04ae4f23156b0000635db8d244620016da640100000000026401000000009004565b6200161e73106a8ff0000000000000000000000000000000006902a5a058fc295ed00000635db8d244620016da640100000000026401000000009004565b6200165c73102fb9400000000000000000000000000000000069038780827d32a3ab0000635db8d244620016da640100000000026401000000009004565b6200169a737ed62cf71d519d3bf293ef90829508f92f4ccccb6902a5a058fc295ed00000635db8d244620016da640100000000026401000000009004565b620016d873199a8c5000000000000000000000000000000000691a784379d99db4200000635db8d244620016da640100000000026401000000009004565b565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816000015414801562001735575060008160010154145b6200178c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018062001b326029913960400191505060405180910390fd5b8260016000828254019250508190555082816000018190555081816001018190555050505050565b61034680620017c46000396000f3fe608060405234801561001057600080fd5b5060043610610069576000357c01000000000000000000000000000000000000000000000000000000009004806318a5bbdc1461006e578063192e7a7b146100cd57806330f0dbe0146101115780639976e12f1461012f575b600080fd5b6100b06004803603602081101561008457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061014d565b604051808381526020018281526020019250505060405180910390f35b61010f600480360360208110156100e357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610171565b005b610119610305565b6040518082815260200191505060405180910390f35b610137610314565b6040518082815260200191505060405180910390f35b60006020528060005260406000206000915090508060000154908060010154905082565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600081600001541161022d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f417661696c61626c6520616d6f756e742069732030000000000000000000000081525060200191505060405180910390fd5b806001015442116102a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f486f6c64696e6720706572696f64206973206e6f74206f76657200000000000081525060200191505060405180910390fd5b600081600001549050600082600001819055508273ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156102ff573d6000803e3d6000fd5b50505050565b6a21bd8334ca74c3834c000081565b6001548156fea165627a7a7230582078bf501dd1d053c49557b82491b940e47ebf94b95608375e22da53fcc7120a1a002954617267657420616d6f756e742073686f756c6420657175616c2061637475616c20616d6f756e74486f6c64696e6720666f72207468697320616464726573732077617320616c7265616479207365742e42616c616e63652073686f756c6420657175616c2074617267657420616d6f756e742e" + }, + "0x1204700000000000000000000000000000000006": { + "constructor": "0x6080604052670de0b6b3a76400006003553480156200001d57600080fd5b5060405160208062003e58833981018060405260208110156200003f57600080fd5b8101908080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a362000126816200012d640100000000026401000000009004565b506200028f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620001d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6577206f776e657220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b613bb9806200029f6000396000f3fe6080604052600436106101d4576000357c0100000000000000000000000000000000000000000000000000000000900480639269881411610109578063df57b742116100a7578063ef5454d611610081578063ef5454d614610d59578063f25eb5c114610e17578063f2fde38b14610e2e578063f6d339e414610e7f576101d4565b8063df57b74214610b62578063e30bd74014610bdd578063eadf976014610ca7576101d4565b8063ac72c120116100e3578063ac72c120146109c5578063c3a3582514610a18578063ddca3f4314610abc578063deb931a214610ae7576101d4565b806392698814146108855780639890220b146108d8578063ac4e73f914610907576101d4565b806369fe0e2d1161017657806379ce9fac1161015057806379ce9fac146106e85780638da5cb5b1461075b5780638f32d59b146107b257806390b97fc1146107e1576101d4565b806369fe0e2d146105b45780636a1acc3f14610607578063715018a6146106d1576101d4565b80633f3935d1116101b25780633f3935d1146103ad578063432ced041461044b5780634f39ca59146104915780636795dbcd146104e4576101d4565b806306b2ff47146101d957806319362a2814610242578063267b6922146102f4575b600080fd5b3480156101e557600080fd5b50610228600480360360208110156101fc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610f47565b604051808215151515815260200191505060405180910390f35b34801561024e57600080fd5b506102da6004803603606081101561026557600080fd5b81019080803590602001909291908035906020019064010000000081111561028c57600080fd5b82018360208201111561029e57600080fd5b803590602001918460018302840111640100000000831117156102c057600080fd5b909192939192939080359060200190929190505050610fa7565b604051808215151515815260200191505060405180910390f35b34801561030057600080fd5b5061032d6004803603602081101561031757600080fd5b81019080803590602001909291905050506111ff565b604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182151515158152602001935050505060405180910390f35b3480156103b957600080fd5b50610431600480360360208110156103d057600080fd5b81019080803590602001906401000000008111156103ed57600080fd5b8201836020820111156103ff57600080fd5b8035906020019184600183028401116401000000008311171561042157600080fd5b9091929391929390505050611276565b604051808215151515815260200191505060405180910390f35b6104776004803603602081101561046157600080fd5b8101908080359060200190929190505050611553565b604051808215151515815260200191505060405180910390f35b34801561049d57600080fd5b506104ca600480360360208110156104b457600080fd5b810190808035906020019092919050505061185c565b604051808215151515815260200191505060405180910390f35b3480156104f057600080fd5b506105726004803603604081101561050757600080fd5b81019080803590602001909291908035906020019064010000000081111561052e57600080fd5b82018360208201111561054057600080fd5b8035906020019184600183028401116401000000008311171561056257600080fd5b9091929391929390505050611acc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156105c057600080fd5b506105ed600480360360208110156105d757600080fd5b8101908080359060200190929190505050611bb0565b604051808215151515815260200191505060405180910390f35b34801561061357600080fd5b506106566004803603602081101561062a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611c73565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561069657808201518184015260208101905061067b565b50505050905090810190601f1680156106c35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156106dd57600080fd5b506106e6611d23565b005b3480156106f457600080fd5b506107416004803603604081101561070b57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611e5c565b604051808215151515815260200191505060405180910390f35b34801561076757600080fd5b5061077061208a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107be57600080fd5b506107c76120b3565b604051808215151515815260200191505060405180910390f35b3480156107ed57600080fd5b5061086f6004803603604081101561080457600080fd5b81019080803590602001909291908035906020019064010000000081111561082b57600080fd5b82018360208201111561083d57600080fd5b8035906020019184600183028401116401000000008311171561085f57600080fd5b909192939192939050505061210a565b6040518082815260200191505060405180910390f35b34801561089157600080fd5b506108be600480360360208110156108a857600080fd5b81019080803590602001909291905050506121ea565b604051808215151515815260200191505060405180910390f35b3480156108e457600080fd5b506108ed6122f3565b604051808215151515815260200191505060405180910390f35b34801561091357600080fd5b506109ab6004803603604081101561092a57600080fd5b810190808035906020019064010000000081111561094757600080fd5b82018360208201111561095957600080fd5b8035906020019184600183028401116401000000008311171561097b57600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612422565b604051808215151515815260200191505060405180910390f35b3480156109d157600080fd5b506109fe600480360360208110156109e857600080fd5b8101908080359060200190929190505050612982565b604051808215151515815260200191505060405180910390f35b348015610a2457600080fd5b50610aa660048036036040811015610a3b57600080fd5b810190808035906020019092919080359060200190640100000000811115610a6257600080fd5b820183602082011115610a7457600080fd5b80359060200191846001830284011164010000000083111715610a9657600080fd5b9091929391929390505050612a8b565b6040518082815260200191505060405180910390f35b348015610ac857600080fd5b50610ad1612b6f565b6040518082815260200191505060405180910390f35b348015610af357600080fd5b50610b2060048036036020811015610b0a57600080fd5b8101908080359060200190929190505050612b75565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610b6e57600080fd5b50610b9b60048036036020811015610b8557600080fd5b8101908080359060200190929190505050612c4e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610be957600080fd5b50610c2c60048036036020811015610c0057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612d27565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610c6c578082015181840152602081019050610c51565b50505050905090810190601f168015610c995780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b348015610cb357600080fd5b50610d3f60048036036060811015610cca57600080fd5b810190808035906020019092919080359060200190640100000000811115610cf157600080fd5b820183602082011115610d0357600080fd5b80359060200191846001830284011164010000000083111715610d2557600080fd5b909192939192939080359060200190929190505050612e08565b604051808215151515815260200191505060405180910390f35b348015610d6557600080fd5b50610dfd60048036036040811015610d7c57600080fd5b8101908080359060200190640100000000811115610d9957600080fd5b820183602082011115610dab57600080fd5b80359060200191846001830284011164010000000083111715610dcd57600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613063565b604051808215151515815260200191505060405180910390f35b348015610e2357600080fd5b50610e2c613297565b005b348015610e3a57600080fd5b50610e7d60048036036020811015610e5157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613648565b005b348015610e8b57600080fd5b50610f2d60048036036060811015610ea257600080fd5b810190808035906020019092919080359060200190640100000000811115610ec957600080fd5b820183602082011115610edb57600080fd5b80359060200191846001830284011164010000000083111715610efd57600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506136ce565b604051808215151515815260200191505060405180910390f35b600080600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080546001816001161561010002031660029004905014159050919050565b6000846001600082815260200190815260200160002060010160149054906101000a900460ff1615611041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b853373ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611119576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4572726f723a204f6e6c79206f776e6572206f6600000000000000000000000081525060200191505060405180910390fd5b83600160008981526020019081526020016000206002018787604051808383808284378083019250505092505050908152602001604051809103902081905550867fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea878789896040518080602001806020018381038352878782818152602001925080828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925080828437600081840152601f19601f820116905080830192505050965050505050505060405180910390a2600192505050949350505050565b60016020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160149054906101000a900460ff16905083565b600082828080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050600160008280519060200120815260200190815260200160002060010160149054906101000a900460ff161561135b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f4572726f723a204f6e6c79207768656e20656e7472790000000000000000000081525060200191505060405180910390fd5b83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050503373ffffffffffffffffffffffffffffffffffffffff16600160008380519060200120815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461147e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f4572726f723a204f6e6c79207768656e2070726f706f7365640000000000000081525060200191505060405180910390fd5b8484600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002091906114cc929190613aa0565b503373ffffffffffffffffffffffffffffffffffffffff167f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c91920868660405180806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050935050505060405180910390a260019250505092915050565b6000816001600082815260200190815260200160002060010160149054906101000a900460ff16156115ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b82600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146116c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f4572726f723a204f6e6c79207768656e20756e7265736572766564000000000081525060200191505060405180910390fd5b60035434101561173e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f4572726f723a206f6e6c79207768656e2066656520706169640000000000000081525060200191505060405180910390fd5b6117466120b3565b6117b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b336001600086815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16847f4963513eca575aba66fdcd25f267aae85958fe6fb97e75fa25d783f1a091a22160405160405180910390a3600192505050919050565b6000816001600082815260200190815260200160002060010160149054906101000a900460ff16156118f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b823373ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146119ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4572726f723a204f6e6c79206f776e6572206f6600000000000000000000000081525060200191505060405180910390fd5b600260006001600087815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000611a4f9190613b20565b600180600086815260200190815260200160002060010160146101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff16847fef1961b4d2909dc23643b309bfe5c3e5646842d98c3a58517037ef3871185af360405160405180910390a3600192505050919050565b6000836001600082815260200190815260200160002060010160149054906101000a900460ff1615611b66576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b600160008681526020019081526020016000206002018484604051808383808284378083019250505092505050908152602001604051809103902054600190049150509392505050565b6000611bba6120b3565b611c2c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b816003819055507f6bbc57480a46553fa4d156ce702beef5f3ad66303b0ed1a5d4cb44966c6584c3826040518082815260200191505060405180910390a160019050919050565b60026020528060005260406000206000915090508054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611d1b5780601f10611cf057610100808354040283529160200191611d1b565b820191906000526020600020905b815481529060010190602001808311611cfe57829003601f168201915b505050505081565b611d2b6120b3565b611d9d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000826001600082815260200190815260200160002060010160149054906101000a900460ff1615611ef6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b833373ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611fce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4572726f723a204f6e6c79206f776e6572206f6600000000000000000000000081525060200191505060405180910390fd5b836001600087815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16867f7b97c62130aa09acbbcbf7482630e756592496f1759eaf702f469cf64dfb779460405160405180910390a460019250505092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6000836001600082815260200190815260200160002060010160149054906101000a900460ff16156121a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b6001600086815260200190815260200160002060020184846040518083838082843780830192505050925050509081526020016040518091039020549150509392505050565b6000816001600082815260200190815260200160002060010160149054906101000a900460ff1615612284576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166001600085815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415915050919050565b60006122fd6120b3565b61236f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b7fdef931299fe61d176f949118058530c1f3f539dcb6950b4e372c9b835c33ca073073ffffffffffffffffffffffffffffffffffffffff16316040518082815260200191505060405180910390a13373ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f1935050505015801561241a573d6000803e3d6000fd5b506001905090565b600083838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050600160008280519060200120815260200190815260200160002060010160149054906101000a900460ff1615612507576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f4572726f723a204f6e6c79207768656e20656e7472790000000000000000000081525060200191505060405180910390fd5b848460405180838380828437808301925050509250505060405180910390203373ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146125fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4572726f723a204f6e6c79206f776e6572206f6600000000000000000000000081525060200191505060405180910390fd5b6000868660405180838380828437808301925050509250505060405180910390209050600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415801561276e575080600260006001600085815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020604051808280546001816001161561010002031660029004801561275f5780601f1061273d57610100808354040283529182019161275f565b820191906000526020600020905b81548152906001019060200180831161274b575b50509150506040518091039020145b156128a557600260006001600084815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006127f49190613b20565b6001600082815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd888860405180806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050935050505060405180910390a25b846001600083815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508473ffffffffffffffffffffffffffffffffffffffff167f728435a0031f6a04538fcdd24922a7e06bc7bc945db03e83d22122d1bc5f28df888860405180806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050935050505060405180910390a2600193505050509392505050565b6000816001600082815260200190815260200160002060010160149054906101000a900460ff1615612a1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166001600085815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415915050919050565b6000836001600082815260200190815260200160002060010160149054906101000a900460ff1615612b25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b600160008681526020019081526020016000206002018484604051808383808284378083019250505092505050908152602001604051809103902054600190049150509392505050565b60035481565b6000816001600082815260200190815260200160002060010160149054906101000a900460ff1615612c0f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b6001600084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b6000816001600082815260200190815260200160002060010160149054906101000a900460ff1615612ce8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b6001600084815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b6060600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015612dfc5780601f10612dd157610100808354040283529160200191612dfc565b820191906000526020600020905b815481529060010190602001808311612ddf57829003601f168201915b50505050509050919050565b6000846001600082815260200190815260200160002060010160149054906101000a900460ff1615612ea2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b853373ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612f7a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4572726f723a204f6e6c79206f776e6572206f6600000000000000000000000081525060200191505060405180910390fd5b83600102600160008981526020019081526020016000206002018787604051808383808284378083019250505092505050908152602001604051809103902081905550867fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea878789896040518080602001806020018381038352878782818152602001925080828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925080828437600081840152601f19601f820116905080830192505050965050505050505060405180910390a2600192505050949350505050565b600083838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050600160008280519060200120815260200190815260200160002060010160149054906101000a900460ff1615613148576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f4572726f723a204f6e6c79207768656e20656e7472790000000000000000000081525060200191505060405180910390fd5b6131506120b3565b6131c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b8484600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209190613210929190613aa0565b508273ffffffffffffffffffffffffffffffffffffffff167f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c91920868660405180806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050935050505060405180910390a260019150509392505050565b600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561336a5780601f1061333f5761010080835404028352916020019161336a565b820191906000526020600020905b81548152906001019060200180831161334d57829003601f168201915b5050505050600160008280519060200120815260200190815260200160002060010160149054906101000a900460ff161561340d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f4572726f723a204f6e6c79207768656e20656e7472790000000000000000000081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020604051808060200182810382528381815460018160011615610100020316600290048152602001915080546001816001161561010002031660029004801561350d5780601f106134e25761010080835404028352916020019161350d565b820191906000526020600020905b8154815290600101906020018083116134f057829003601f168201915b50509250505060405180910390a260016000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180828054600181600116156101000203166002900480156135b95780601f106135975761010080835404028352918201916135b9565b820191906000526020600020905b8154815290600101906020018083116135a5575b50509150506040518091039020815260200190815260200160002060010160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006136459190613b20565b50565b6136506120b3565b6136c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f53656e646572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b6136cb8161393f565b50565b6000846001600082815260200190815260200160002060010160149054906101000a900460ff1615613768576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4572726f723a204f6e6c79207768656e20656e7472792072617700000000000081525060200191505060405180910390fd5b853373ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614613840576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4572726f723a204f6e6c79206f776e6572206f6600000000000000000000000081525060200191505060405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff16600102600160008981526020019081526020016000206002018787604051808383808284378083019250505092505050908152602001604051809103902081905550867fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea878789896040518080602001806020018381038352878782818152602001925080828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925080828437600081840152601f19601f820116905080830192505050965050505050505060405180910390a2600192505050949350505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156139e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6577206f776e657220616464726573732063616e6e6f74206265203078300081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613ae157803560ff1916838001178555613b0f565b82800160010185558215613b0f579182015b82811115613b0e578235825591602001919060010190613af3565b5b509050613b1c9190613b68565b5090565b50805460018160011615610100020316600290046000825580601f10613b465750613b65565b601f016020900490600052602060002090810190613b649190613b68565b5b50565b613b8a91905b80821115613b86576000816000905550600101613b6e565b5090565b9056fea165627a7a723058201b0da92162b975c882f9c56423cbea6ec9afb46d8dccc92abe125e91c84d52de00290000000000000000000000001204700000000000000000000000000000000005" + }, + "0x1204700000000000000000000000000000000007": { + "constructor": "0x608060405234801561001057600080fd5b50604051604080610a5f833981018060405261002f919081019061028d565b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a381600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101448161014b640100000000026401000000009004565b505061036c565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156101bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101b290610309565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000610285825161033a565b905092915050565b600080604083850312156102a057600080fd5b60006102ae85828601610279565b92505060206102bf85828601610279565b9150509250929050565b60006102d6601f83610329565b91507f4e6577206f776e657220616464726573732063616e6e6f7420626520307830006000830152602082019050919050565b60006020820190508181036000830152610322816102c9565b9050919050565b600082825260208201905092915050565b60006103458261034c565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6106e48061037b6000396000f3fe608060405234801561001057600080fd5b506004361061007f576000357c0100000000000000000000000000000000000000000000000000000000900480636ddc4a0714610084578063715018a6146100a25780638da5cb5b146100ac5780638f32d59b146100ca578063f2fde38b146100e8578063fe64d6ff14610104575b600080fd5b61008c610120565b60405161009991906105b3565b60405180910390f35b6100aa610146565b005b6100b461024c565b6040516100c191906105b3565b60405180910390f35b6100d2610275565b6040516100df91906105ce565b60405180910390f35b61010260048036036100fd91908101906104ec565b6102cc565b005b61011e600480360361011991908101906104ec565b61031f565b005b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61014e610275565b61018d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161018490610609565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6102d4610275565b610313576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161030a90610609565b60405180910390fd5b61031c816103aa565b50565b610327610275565b610366576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161035d90610609565b60405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561041a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610411906105e9565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60006104e48235610678565b905092915050565b6000602082840312156104fe57600080fd5b600061050c848285016104d8565b91505092915050565b61051e8161063a565b82525050565b61052d8161064c565b82525050565b6000610540601f83610629565b91507f4e6577206f776e657220616464726573732063616e6e6f7420626520307830006000830152602082019050919050565b6000610580601383610629565b91507f53656e646572206973206e6f74206f776e6572000000000000000000000000006000830152602082019050919050565b60006020820190506105c86000830184610515565b92915050565b60006020820190506105e36000830184610524565b92915050565b6000602082019050818103600083015261060281610533565b9050919050565b6000602082019050818103600083015261062281610573565b9050919050565b600082825260208201905092915050565b600061064582610658565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006106838261068a565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff8216905091905056fea265627a7a723058207424d262effee3c4b2cfbe03927ef8931223cda85f89bf647b88b2f7e64cc5516c6578706572696d656e74616cf5003700000000000000000000000012047000000000000000000000000000000000090000000000000000000000001204700000000000000000000000000000000005" + }, + "0x1204700000000000000000000000000000000008": { + "constructor": "0x60806040523480156200001157600080fd5b5060405160408062002b838339810180604052620000339190810190620002af565b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a381600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506200014a8162000152640100000000026401000000009004565b5050620003ad565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620001c5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001bc9062000332565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600062000291825162000365565b905092915050565b6000620002a7825162000379565b905092915050565b60008060408385031215620002c357600080fd5b6000620002d38582860162000299565b9250506020620002e68582860162000283565b9150509250929050565b6000620002ff601f8362000354565b91507f4e6577206f776e657220616464726573732063616e6e6f7420626520307830006000830152602082019050919050565b600060208201905081810360008301526200034d81620002f0565b9050919050565b600082825260208201905092915050565b600062000372826200038d565b9050919050565b6000620003868262000365565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6127c680620003bd6000396000f3fe608060405234801561001057600080fd5b506004361061011d576000357c010000000000000000000000000000000000000000000000000000000090048063954029c9116100b4578063eab7ad9211610083578063eab7ad92146102e4578063ee7ee0fd14610300578063f2fde38b14610330578063fbd74f841461034c5761011d565b8063954029c91461024c578063a999809f14610268578063b71da0d114610298578063da5393d5146102c85761011d565b806370a05b18116100f057806370a05b18146101d6578063715018a6146102065780638da5cb5b146102105780638f32d59b1461022e5761011d565b80631bab58f5146101225780632c5653e21461015257806332d91c0e146101705780636a564261146101a0575b600080fd5b61013c60048036036101379190810190611f97565b61037c565b604051610149919061260c565b60405180910390f35b61015a6107b5565b604051610167919061254f565b60405180910390f35b61018a60048036036101859190810190611f97565b6107db565b604051610197919061256a565b60405180910390f35b6101ba60048036036101b59190810190611f97565b6109e8565b6040516101cd97969594939291906124c4565b60405180910390f35b6101f060048036036101eb9190810190611f97565b610c97565b6040516101fd91906124a2565b60405180910390f35b61020e610ea4565b005b610218610faa565b604051610225919061246c565b60405180910390f35b610236610fd3565b6040516102439190612487565b60405180910390f35b61026660048036036102619190810190611f97565b61102a565b005b610282600480360361027d9190810190611f97565b61119d565b60405161028f919061256a565b60405180910390f35b6102b260048036036102ad9190810190611f97565b6113aa565b6040516102bf9190612487565b60405180910390f35b6102e260048036036102dd9190810190611f97565b61143a565b005b6102fe60048036036102f99190810190611fe9565b611535565b005b61031a60048036036103159190810190611f97565b611853565b6040516103279190612487565b60405180910390f35b61034a60048036036103459190810190611f97565b6119d5565b005b61036660048036036103619190810190611f97565b611a28565b60405161037391906124a2565b60405180910390f35b610384611d63565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b15801561040857600080fd5b505afa15801561041c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506104409190810190611fc0565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104a49061258c565b60405180910390fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060e0016040529081600082018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105905780601f1061056557610100808354040283529160200191610590565b820191906000526020600020905b81548152906001019060200180831161057357829003601f168201915b50505050508152602001600182018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106325780601f1061060757610100808354040283529160200191610632565b820191906000526020600020905b81548152906001019060200180831161061557829003601f168201915b50505050508152602001600282018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106d45780601f106106a9576101008083540402835291602001916106d4565b820191906000526020600020905b8154815290600101906020018083116106b757829003601f168201915b50505050508152602001600382018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107765780601f1061074b57610100808354040283529160200191610776565b820191906000526020600020905b81548152906001019060200180831161075957829003601f168201915b505050505081526020016004820160009054906101000a900460ff16151515158152602001600582015481526020016006820154815250509050919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b15801561086157600080fd5b505afa158015610875573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108999190810190611fc0565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610906576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108fd9061258c565b60405180910390fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206003018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109dc5780601f106109b1576101008083540402835291602001916109dc565b820191906000526020600020905b8154815290600101906020018083116109bf57829003601f168201915b50505050509050919050565b6001602052806000526040600020600091509050806000018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a945780601f10610a6957610100808354040283529160200191610a94565b820191906000526020600020905b815481529060010190602001808311610a7757829003601f168201915b505050505090806001018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b325780601f10610b0757610100808354040283529160200191610b32565b820191906000526020600020905b815481529060010190602001808311610b1557829003601f168201915b505050505090806002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610bd05780601f10610ba557610100808354040283529160200191610bd0565b820191906000526020600020905b815481529060010190602001808311610bb357829003601f168201915b505050505090806003018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c6e5780601f10610c4357610100808354040283529160200191610c6e565b820191906000526020600020905b815481529060010190602001808311610c5157829003601f168201915b5050505050908060040160009054906101000a900460ff16908060050154908060060154905087565b6060600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b158015610d1d57600080fd5b505afa158015610d31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610d559190810190611fc0565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610dc2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610db99061258c565b60405180910390fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e985780601f10610e6d57610100808354040283529160200191610e98565b820191906000526020600020905b815481529060010190602001808311610e7b57829003601f168201915b50505050509050919050565b610eac610fd3565b610eeb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ee2906125ec565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b1580156110ae57600080fd5b505afa1580156110c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506110e69190810190611fc0565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611153576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114a9061258c565b60405180910390fd5b43600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206006018190555050565b6060600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b15801561122357600080fd5b505afa158015611237573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061125b9190810190611fc0565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146112c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112bf9061258c565b60405180910390fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561139e5780601f106113735761010080835404028352916020019161139e565b820191906000526020600020905b81548152906001019060200180831161138157829003601f168201915b50505050509050919050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060154600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050154109050919050565b611442610fd3565b611481576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611478906125ec565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156114f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e8906125ac565b60405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b1580156115b957600080fd5b505afa1580156115cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115f19190810190611fc0565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461165e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116559061258c565b60405180910390fd5b8888600160008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000191906116af929190611da2565b508686600160008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001019190611701929190611e22565b508484600160008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002019190611753929190611da2565b508282600160008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030191906117a5929190611e22565b5080600160008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160006101000a81548160ff02191690831515021790555043600160008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005018190555050505050505050505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b1580156118d957600080fd5b505afa1580156118ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506119119190810190611fc0565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461197e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119759061258c565b60405180910390fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900460ff169050919050565b6119dd610fd3565b611a1c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a13906125ec565b60405180910390fd5b611a2581611c35565b50565b6060600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636ddc4a076040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b158015611aae57600080fd5b505afa158015611ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611ae69190810190611fc0565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b53576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b4a9061258c565b60405180910390fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611c295780601f10611bfe57610100808354040283529160200191611c29565b820191906000526020600020905b815481529060010190602001808311611c0c57829003601f168201915b50505050509050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611ca5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c9c906125cc565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6040518060e001604052806060815260200160608152602001606081526020016060815260200160001515815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611de357803560ff1916838001178555611e11565b82800160010185558215611e11579182015b82811115611e10578235825591602001919060010190611df5565b5b509050611e1e9190611ea2565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611e6357803560ff1916838001178555611e91565b82800160010185558215611e91579182015b82811115611e90578235825591602001919060010190611e75565b5b509050611e9e9190611ea2565b5090565b611ec491905b80821115611ec0576000816000905550600101611ea8565b5090565b90565b6000611ed382356126e6565b905092915050565b6000611ee782516126e6565b905092915050565b6000611efb82356126f8565b905092915050565b60008083601f840112611f1557600080fd5b8235905067ffffffffffffffff811115611f2e57600080fd5b602083019150836001820283011115611f4657600080fd5b9250929050565b60008083601f840112611f5f57600080fd5b8235905067ffffffffffffffff811115611f7857600080fd5b602083019150836001820283011115611f9057600080fd5b9250929050565b600060208284031215611fa957600080fd5b6000611fb784828501611ec7565b91505092915050565b600060208284031215611fd257600080fd5b6000611fe084828501611edb565b91505092915050565b60008060008060008060008060008060c08b8d03121561200857600080fd5b60006120168d828e01611ec7565b9a505060208b013567ffffffffffffffff81111561203357600080fd5b61203f8d828e01611f03565b995099505060408b013567ffffffffffffffff81111561205e57600080fd5b61206a8d828e01611f4d565b975097505060608b013567ffffffffffffffff81111561208957600080fd5b6120958d828e01611f03565b955095505060808b013567ffffffffffffffff8111156120b457600080fd5b6120c08d828e01611f4d565b935093505060a06120d38d828e01611eef565b9150509295989b9194979a5092959850565b6120ee8161269e565b82525050565b6120fd816126b0565b82525050565b61210c816126b0565b82525050565b600061211d82612639565b612127818561266b565b9350612137818560208601612748565b6121408161277b565b840191505092915050565b60006121568261262e565b612160818561265a565b9350612170818560208601612748565b6121798161277b565b840191505092915050565b600061218f8261262e565b612199818561266b565b93506121a9818560208601612748565b6121b28161277b565b840191505092915050565b6121c681612724565b82525050565b60006121d78261264f565b6121e1818561268d565b93506121f1818560208601612748565b6121fa8161277b565b840191505092915050565b600061221082612644565b61221a818561267c565b935061222a818560208601612748565b6122338161277b565b840191505092915050565b600061224982612644565b612253818561268d565b9350612263818560208601612748565b61226c8161277b565b840191505092915050565b600061228460138361268d565b91507f4572726f723a206f6e6c794c6f676963204462000000000000000000000000006000830152602082019050919050565b60006122c460298361268d565b91507f4572726f723a206e65774c6f6f6b5570206973206e6f7420616c6c6f7765642060008301527f746f2062652030783000000000000000000000000000000000000000000000006020830152604082019050919050565b600061232a601f8361268d565b91507f4e6577206f776e657220616464726573732063616e6e6f7420626520307830006000830152602082019050919050565b600061236a60138361268d565b91507f53656e646572206973206e6f74206f776e6572000000000000000000000000006000830152602082019050919050565b600060e08301600083015184820360008601526123ba828261214b565b915050602083015184820360208601526123d48282612205565b915050604083015184820360408601526123ee828261214b565b915050606083015184820360608601526124088282612205565b915050608083015161241d60808601826120f4565b5060a083015161243060a086018261244e565b5060c083015161244360c086018261244e565b508091505092915050565b612457816126dc565b82525050565b612466816126dc565b82525050565b600060208201905061248160008301846120e5565b92915050565b600060208201905061249c6000830184612103565b92915050565b600060208201905081810360008301526124bc8184612112565b905092915050565b600060e08201905081810360008301526124de818a612184565b905081810360208301526124f2818961223e565b905081810360408301526125068188612184565b9050818103606083015261251a818761223e565b90506125296080830186612103565b61253660a083018561245d565b61254360c083018461245d565b98975050505050505050565b600060208201905061256460008301846121bd565b92915050565b6000602082019050818103600083015261258481846121cc565b905092915050565b600060208201905081810360008301526125a581612277565b9050919050565b600060208201905081810360008301526125c5816122b7565b9050919050565b600060208201905081810360008301526125e58161231d565b9050919050565b600060208201905081810360008301526126058161235d565b9050919050565b60006020820190508181036000830152612626818461239d565b905092915050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b60006126a9826126bc565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006126f182612704565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061272f82612736565b9050919050565b6000612741826126bc565b9050919050565b60005b8381101561276657808201518184015260208101905061274b565b83811115612775576000848401525b50505050565b6000601f19601f830116905091905056fea265627a7a723058207e60ec05ac38073f6d98c9cff2cce094d00db0238d6d4b0c183253539a43fe2b6c6578706572696d656e74616cf5003700000000000000000000000012047000000000000000000000000000000000070000000000000000000000001204700000000000000000000000000000000005" + }, + "0x1204700000000000000000000000000000000009": { + "constructor": "0x60806040523480156200001157600080fd5b50604051604080620021cc8339810180604052620000339190810190620002af565b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a381600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506200014a8162000152640100000000026401000000009004565b5050620003ad565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620001c5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001bc9062000332565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600062000291825162000365565b905092915050565b6000620002a7825162000379565b905092915050565b60008060408385031215620002c357600080fd5b6000620002d38582860162000299565b9250506020620002e68582860162000283565b9150509250929050565b6000620002ff601f8362000354565b91507f4e6577206f776e657220616464726573732063616e6e6f7420626520307830006000830152602082019050919050565b600060208201905081810360008301526200034d81620002f0565b9050919050565b600082825260208201905092915050565b600062000372826200038d565b9050919050565b6000620003868262000365565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b611e0f80620003bd6000396000f3fe608060405234801561001057600080fd5b50600436106100b0576000357c0100000000000000000000000000000000000000000000000000000000900480638da5cb5b116100835780638da5cb5b146101155780638f32d59b14610133578063b71da0d114610151578063ec26261114610181578063f2fde38b1461019f576100b0565b806312127ed7146100b55780633f67c333146100d1578063715018a6146100db57806389c3ce1e146100e5575b600080fd5b6100cf60048036036100ca9190810190611450565b6101bb565b005b6100d96109dd565b005b6100e3610b98565b005b6100ff60048036036100fa9190810190611427565b610c9e565b60405161010c9190611b14565b60405180910390f35b61011d610d85565b60405161012a91906119ab565b60405180910390f35b61013b610dae565b6040516101489190611a5e565b60405180910390f35b61016b60048036036101669190810190611427565b610e05565b6040516101789190611a5e565b60405180910390f35b610189610ed5565b6040516101969190611a79565b60405180910390f35b6101b960048036036101b49190810190611427565b610efb565b005b6101c3610dae565b610202576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101f990611ab4565b60405180910390fd5b6002856040516102129190611994565b602060405180830381855afa15801561022f573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506102529190810190611562565b6002600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fbd74f84896040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016102cb91906119ab565b60006040518083038186803b1580156102e357600080fd5b505afa1580156102f7573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250610320919081019061158b565b60405161032d9190611994565b602060405180830381855afa15801561034a573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525061036d9190810190611562565b1480156104e257506002846040516103859190611994565b602060405180830381855afa1580156103a2573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506103c59190810190611562565b6002600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a999809f896040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040161043e91906119ab565b60006040518083038186803b15801561045657600080fd5b505afa15801561046a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525061049391908101906115cc565b6040516104a09190611994565b602060405180830381855afa1580156104bd573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506104e09190810190611562565b145b801561065657506002836040516104f99190611994565b602060405180830381855afa158015610516573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506105399190810190611562565b6002600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a05b18896040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016105b291906119ab565b60006040518083038186803b1580156105ca57600080fd5b505afa1580156105de573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250610607919081019061158b565b6040516106149190611994565b602060405180830381855afa158015610631573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506106549190810190611562565b145b80156107ca575060028260405161066d9190611994565b602060405180830381855afa15801561068a573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506106ad9190810190611562565b6002600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166332d91c0e896040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040161072691906119ab565b60006040518083038186803b15801561073e57600080fd5b505afa158015610752573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525061077b91908101906115cc565b6040516107889190611994565b602060405180830381855afa1580156107a5573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506107c89190810190611562565b145b801561089f5750801515600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ee7ee0fd886040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040161084b91906119ab565b60206040518083038186803b15801561086357600080fd5b505afa158015610877573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061089b9190810190611539565b1515145b156108df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d690611ad4565b60405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663eab7ad928787878787876040518763ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401610960969594939291906119e1565b600060405180830381600087803b15801561097a57600080fd5b505af115801561098e573d6000803e3d6000fd5b505050508573ffffffffffffffffffffffffffffffffffffffff167fc9e49a024d50440c73d2d12d0ae05064094dca76b46dc95e99ea6848eb8f27e960405160405180910390a2505050505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fbd74f84336040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401610a5691906119c6565b60006040518083038186803b158015610a6e57600080fd5b505afa158015610a82573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250610aab919081019061158b565b511415610aed576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ae490611af4565b60405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663954029c9336040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401610b6491906119c6565b600060405180830381600087803b158015610b7e57600080fd5b505af1158015610b92573d6000803e3d6000fd5b50505050565b610ba0610dae565b610bdf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bd690611ab4565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b610ca661107c565b610cae61107c565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631bab58f5846040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401610d2591906119ab565b60006040518083038186803b158015610d3d57600080fd5b505afa158015610d51573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250610d7a919081019061160d565b905080915050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b71da0d1836040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401610e7e91906119ab565b60206040518083038186803b158015610e9657600080fd5b505afa158015610eaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ece9190810190611539565b9050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610f03610dae565b610f42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f3990611ab4565b60405180910390fd5b610f4b81610f4e565b50565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610fbe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fb590611a94565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6040518060e001604052806060815260200160608152602001606081526020016060815260200160001515815260200160008152602001600081525090565b60006110c78235611cd6565b905092915050565b60006110db8235611ce8565b905092915050565b60006110ef8251611ce8565b905092915050565b60006111038251611cf4565b905092915050565b600082601f83011261111c57600080fd5b815161112f61112a82611b63565b611b36565b9150808252602083016020830185838301111561114b57600080fd5b611156838284611d91565b50505092915050565b600082601f83011261117057600080fd5b813561118361117e82611b8f565b611b36565b9150808252602083016020830185838301111561119f57600080fd5b6111aa838284611d82565b50505092915050565b600082601f8301126111c457600080fd5b81516111d76111d282611b8f565b611b36565b915080825260208301602083018583830111156111f357600080fd5b6111fe838284611d91565b50505092915050565b600082601f83011261121857600080fd5b815161122b61122682611bbb565b611b36565b9150808252602083016020830185838301111561124757600080fd5b611252838284611d91565b50505092915050565b600082601f83011261126c57600080fd5b813561127f61127a82611be7565b611b36565b9150808252602083016020830185838301111561129b57600080fd5b6112a6838284611d82565b50505092915050565b600082601f8301126112c057600080fd5b81516112d36112ce82611be7565b611b36565b915080825260208301602083018583830111156112ef57600080fd5b6112fa838284611d91565b50505092915050565b600060e0828403121561131557600080fd5b61131f60e0611b36565b9050600082015167ffffffffffffffff81111561133b57600080fd5b6113478482850161110b565b600083015250602082015167ffffffffffffffff81111561136757600080fd5b61137384828501611207565b602083015250604082015167ffffffffffffffff81111561139357600080fd5b61139f8482850161110b565b604083015250606082015167ffffffffffffffff8111156113bf57600080fd5b6113cb84828501611207565b60608301525060806113df848285016110e3565b60808301525060a06113f384828501611413565b60a08301525060c061140784828501611413565b60c08301525092915050565b600061141f8251611d1e565b905092915050565b60006020828403121561143957600080fd5b6000611447848285016110bb565b91505092915050565b60008060008060008060c0878903121561146957600080fd5b600061147789828a016110bb565b965050602087013567ffffffffffffffff81111561149457600080fd5b6114a089828a0161115f565b955050604087013567ffffffffffffffff8111156114bd57600080fd5b6114c989828a0161125b565b945050606087013567ffffffffffffffff8111156114e657600080fd5b6114f289828a0161115f565b935050608087013567ffffffffffffffff81111561150f57600080fd5b61151b89828a0161125b565b92505060a061152c89828a016110cf565b9150509295509295509295565b60006020828403121561154b57600080fd5b6000611559848285016110e3565b91505092915050565b60006020828403121561157457600080fd5b6000611582848285016110f7565b91505092915050565b60006020828403121561159d57600080fd5b600082015167ffffffffffffffff8111156115b757600080fd5b6115c3848285016111b3565b91505092915050565b6000602082840312156115de57600080fd5b600082015167ffffffffffffffff8111156115f857600080fd5b611604848285016112af565b91505092915050565b60006020828403121561161f57600080fd5b600082015167ffffffffffffffff81111561163957600080fd5b61164584828501611303565b91505092915050565b61165781611d28565b82525050565b61166681611c8e565b82525050565b61167581611ca0565b82525050565b61168481611ca0565b82525050565b600061169582611c1e565b61169f8185611c50565b93506116af818560208601611d91565b6116b881611dc4565b840191505092915050565b60006116ce82611c1e565b6116d88185611c61565b93506116e8818560208601611d91565b80840191505092915050565b60006116ff82611c13565b6117098185611c3f565b9350611719818560208601611d91565b61172281611dc4565b840191505092915050565b61173681611d3a565b82525050565b600061174782611c34565b6117518185611c7d565b9350611761818560208601611d91565b61176a81611dc4565b840191505092915050565b600061178082611c29565b61178a8185611c6c565b935061179a818560208601611d91565b6117a381611dc4565b840191505092915050565b60006117bb601f83611c7d565b91507f4e6577206f776e657220616464726573732063616e6e6f7420626520307830006000830152602082019050919050565b60006117fb601383611c7d565b91507f53656e646572206973206e6f74206f776e6572000000000000000000000000006000830152602082019050919050565b600061183b602583611c7d565b91507f4572726f723a204e6f206368616e67657320696e20746865207061737365642060008301527f53746174650000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006118a1601f83611c7d565b91507f4572726f723a20596f7520617265206e6f7420612076616c696461746f7221006000830152602082019050919050565b600060e08301600083015184820360008601526118f182826116f4565b9150506020830151848203602086015261190b8282611775565b9150506040830151848203604086015261192582826116f4565b9150506060830151848203606086015261193f8282611775565b9150506080830151611954608086018261166c565b5060a083015161196760a0860182611985565b5060c083015161197a60c0860182611985565b508091505092915050565b61198e81611ccc565b82525050565b60006119a082846116c3565b915081905092915050565b60006020820190506119c0600083018461165d565b92915050565b60006020820190506119db600083018461164e565b92915050565b600060c0820190506119f6600083018961165d565b8181036020830152611a08818861168a565b90508181036040830152611a1c818761173c565b90508181036060830152611a30818661168a565b90508181036080830152611a44818561173c565b9050611a5360a083018461167b565b979650505050505050565b6000602082019050611a73600083018461167b565b92915050565b6000602082019050611a8e600083018461172d565b92915050565b60006020820190508181036000830152611aad816117ae565b9050919050565b60006020820190508181036000830152611acd816117ee565b9050919050565b60006020820190508181036000830152611aed8161182e565b9050919050565b60006020820190508181036000830152611b0d81611894565b9050919050565b60006020820190508181036000830152611b2e81846118d4565b905092915050565b6000604051905081810181811067ffffffffffffffff82111715611b5957600080fd5b8060405250919050565b600067ffffffffffffffff821115611b7a57600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff821115611ba657600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff821115611bd257600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff821115611bfe57600080fd5b601f19601f8301169050602081019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b6000611c9982611cac565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000611ce182611cfe565b9050919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000611d3382611d5e565b9050919050565b6000611d4582611d4c565b9050919050565b6000611d5782611cac565b9050919050565b6000611d6982611d70565b9050919050565b6000611d7b82611cac565b9050919050565b82818337600083830152505050565b60005b83811015611daf578082015181840152602081019050611d94565b83811115611dbe576000848401525b50505050565b6000601f19601f830116905091905056fea265627a7a723058204ed2d756516ea8df8dbc4fbf2bd76bb43e93ab01c8c274fc9169dfd0be6254d06c6578706572696d656e74616cf5003700000000000000000000000012047000000000000000000000000000000000080000000000000000000000001204700000000000000000000000000000000005" + } + }, + "nodes": [ + "enode://59c9250cb805409e84c9cd0038e97d8e5e4605b928663675869ebdfd4c251d80ccad76267a5eb2f4362ddceb5ec671f7595463adfc0a12e9f68dbf233072db41@54.70.158.106:30303", + "enode://e487ebacbdad3418905d2ed7f009fa5dbd17d73880854884acc604c0afc1a60a396aa90cb2741278c555a4e30ffc6ffc1c29e83840aa22009ec92fe53f81ec04@99.81.92.124:30303", + "enode://563f12602a117201b39ebeea108185abb15d9286830c074640c9fccbaaaabcc7fe2c95682cc43f95b95059f6d0dc4c9becbc1b2bd78e0c5ef5fddff07d85ba0e@54.201.62.74:30303", + "enode://5903b3acebdc4a34800f6923e5f3aec3ca7e5d1285bec4adb9f20ebb0f87a3bebdd748b1849ca1108a9f1e37ff9ced0b475292b8effc29e95d49ec438f244b02@3.121.165.10:30303", + "enode://8f8e35a6dcacfee946f46447b4703c84f4e485e478143997f86b1834e1b0bb78dab363d700dff3147442b9d3e2a1c521f79340c436eb7245a97c7fe385b89a5d@54.93.159.98:30303", + "enode://bd228aa03cf4a88491c81c5f3ab4a1437df3b463081cc93943c4d3ab37f1e4f8081c6995eca076f717d4fdf9a277c750bd0289477ac151f1e2b024747dcd1747@52.31.129.130:30303" + ] +} diff --git a/ethcore/res/ethereum/xdai.json b/ethcore/res/ethereum/xdai.json new file mode 100644 index 0000000000..ac2a40e148 --- /dev/null +++ b/ethcore/res/ethereum/xdai.json @@ -0,0 +1,157 @@ +{ + "name": "xDai Chain", + "dataDir": "xdai", + "engine": { + "authorityRound": { + "params": { + "stepDuration": 5, + "blockReward": "0x0", + "maximumUncleCountTransition": 0, + "maximumUncleCount": 0, + "validators": { + "multi": { + "0": { + "list": ["0xcace5b3c29211740e595850e80478416ee77ca21"] + }, + "1300": { + "safeContract": "0x22e1229a2c5b95a60983b5577f745a603284f535" + } + } + }, + "blockRewardContractAddress": "0x867305d19606aadba405ce534e303d0e225f9556", + "blockRewardContractTransition": 1310 + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x400", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID": "100", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0", + "eip145Transition": 1604400, + "eip1014Transition": 1604400, + "eip1052Transition": 1604400, + "eip1283Transition": 1604400, + "eip1283DisableTransition": 2508800, + "registrar": "0x1ec97dc137f5168af053c24460a1200502e1a9d2" + }, + "genesis": { + "seal": { + "authorityRound": { + "step": "0x0", + "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x20000", + "gasLimit": "0x989680" + }, + "accounts": { + "0000000000000000000000000000000000000005": { + "builtin": { + "name": "modexp", + "activate_at": "0x0", + "pricing": { + "modexp": { + "divisor": 20 + } + } + } + }, + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x0", + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, + "0x0000000000000000000000000000000000000001": { + "balance": "1", + "builtin": { + "name": "ecrecover", + "pricing": { + "linear": { + "base": 3000, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000002": { + "balance": "1", + "builtin": { + "name": "sha256", + "pricing": { + "linear": { + "base": 60, + "word": 12 + } + } + } + }, + "0x0000000000000000000000000000000000000003": { + "balance": "1", + "builtin": { + "name": "ripemd160", + "pricing": { + "linear": { + "base": 600, + "word": 120 + } + } + } + }, + "0x0000000000000000000000000000000000000004": { + "balance": "1", + "builtin": { + "name": "identity", + "pricing": { + "linear": { + "base": 15, + "word": 3 + } + } + } + } + }, + "nodes": [ + "enode://66786c15390cb4fef3743571e12ec54ca343e7f119018136d68b670edd93604eedf74e5013dc5c2439f89e0e05593e29c409a97e155ea4165c6b832de131ef1e@3.214.113.185:30303" + ] +} diff --git a/ethcore/res/instant_seal.json b/ethcore/res/instant_seal.json index 3ec998f0e5..baafeb5bdf 100644 --- a/ethcore/res/instant_seal.json +++ b/ethcore/res/instant_seal.json @@ -43,9 +43,50 @@ "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, + "0000000000000000000000000000000000000006": { + "balance": "1", + "builtin": { + "name": "alt_bn128_add", + "activate_at": 0, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "balance": "1", + "builtin": { + "name": "alt_bn128_mul", + "activate_at": 0, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "balance": "1", + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": 0, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, "0000000000000000000000000000000000001337": { "balance": "1", "constructor": "0x606060405233600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550670de0b6b3a764000060035534610000575b612904806100666000396000f3006060604052361561013c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306b2ff471461014157806313af40351461018c57806319362a28146101bf5780633f3935d114610248578063432ced04146102b75780634f39ca59146102eb5780636795dbcd1461032457806369fe0e2d146103c857806379ce9fac146103fd5780638da5cb5b1461045557806390b97fc1146104a457806392698814146105245780639890220b1461055d578063ac4e73f914610584578063ac72c12014610612578063c3a358251461064b578063ddca3f43146106c3578063deb931a2146106e6578063df57b74214610747578063e30bd740146107a8578063eadf976014610862578063ef5454d6146108e7578063f25eb5c114610975578063f6d339e414610984575b610000565b3461000057610172600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a1f565b604051808215151515815260200191505060405180910390f35b34610000576101bd600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a81565b005b346100005761022e60048080356000191690602001909190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803560001916906020019091905050610ba2565b604051808215151515815260200191505060405180910390f35b346100005761029d600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050610dc9565b604051808215151515815260200191505060405180910390f35b6102d1600480803560001916906020019091905050611035565b604051808215151515815260200191505060405180910390f35b346100005761030a60048080356000191690602001909190505061115f565b604051808215151515815260200191505060405180910390f35b346100005761038660048080356000191690602001909190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050611378565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34610000576103e3600480803590602001909190505061140d565b604051808215151515815260200191505060405180910390f35b346100005761043b60048080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506114b4565b604051808215151515815260200191505060405180910390f35b34610000576104626115fb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b346100005761050660048080356000191690602001909190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050611621565b60405180826000191660001916815260200191505060405180910390f35b34610000576105436004808035600019169060200190919050506116b2565b604051808215151515815260200191505060405180910390f35b346100005761056a611715565b604051808215151515815260200191505060405180910390f35b34610000576105f8600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611824565b604051808215151515815260200191505060405180910390f35b3461000057610631600480803560001916906020019091905050611d8b565b604051808215151515815260200191505060405180910390f35b34610000576106ad60048080356000191690602001909190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050611dee565b6040518082815260200191505060405180910390f35b34610000576106d0611e83565b6040518082815260200191505060405180910390f35b3461000057610705600480803560001916906020019091905050611e89565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3461000057610766600480803560001916906020019091905050611ed2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34610000576107d9600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611f1b565b6040518080602001828103825283818151815260200191508051906020019080838360008314610828575b80518252602083111561082857602082019150602081019050602083039250610804565b505050905090810190601f1680156108545780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576108cd60048080356000191690602001909190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803590602001909190505061200c565b604051808215151515815260200191505060405180910390f35b346100005761095b600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612236565b604051808215151515815260200191505060405180910390f35b3461000057610982612425565b005b3461000057610a0560048080356000191690602001909190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612698565b604051808215151515815260200191505060405180910390f35b60006000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805460018160011615610100020316600290049050141590505b919050565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610add57610b9f565b8073ffffffffffffffffffffffffffffffffffffffff16600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236460405180905060405180910390a380600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5b50565b6000833373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515610c1d57610dc1565b82600160008760001916600019168152602001908152602001600020600201856040518082805190602001908083835b60208310610c705780518252602082019150602081019050602083039250610c4d565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390208160001916905550836040518082805190602001908083835b60208310610cdf5780518252602082019150602081019050602083039250610cbc565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902085600019167fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea866040518080602001828103825283818151815260200191508051906020019080838360008314610d82575b805182526020831115610d8257602082019150602081019050602083039250610d5e565b505050905090810190601f168015610dae5780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b509392505050565b6000813373ffffffffffffffffffffffffffffffffffffffff1660016000836040518082805190602001908083835b60208310610e1b5780518252602082019150602081019050602083039250610df8565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515610ea45761102f565b82600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610f2d57805160ff1916838001178555610f5b565b82800160010185558215610f5b579182015b82811115610f5a578251825591602001919060010190610f3f565b5b509050610f8091905b80821115610f7c576000816000905550600101610f64565b5090565b50503373ffffffffffffffffffffffffffffffffffffffff16836040518082805190602001908083835b60208310610fcd5780518252602082019150602081019050602083039250610faa565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c9192060405180905060405180910390a3600191505b5b50919050565b600081600060016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561109b57611159565b6003543410156110aa57611158565b3360016000856000191660001916815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff1683600019167f4963513eca575aba66fdcd25f267aae85958fe6fb97e75fa25d783f1a091a22160405180905060405180910390a3600191505b5b5b50919050565b6000813373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415156111da57611372565b6002600060016000866000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805460018160011615610100020316600290046000825580601f1061127c57506112b3565b601f0160209004906000526020600020908101906112b291905b808211156112ae576000816000905550600101611296565b5090565b5b5060016000846000191660001916815260200190815260200160002060006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550503373ffffffffffffffffffffffffffffffffffffffff1683600019167fef1961b4d2909dc23643b309bfe5c3e5646842d98c3a58517037ef3871185af360405180905060405180910390a3600191505b5b50919050565b6000600160008460001916600019168152602001908152602001600020600201826040518082805190602001908083835b602083106113cc57805182526020820191506020810190506020830392506113a9565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020546001900490505b92915050565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561146b576114af565b816003819055507f6bbc57480a46553fa4d156ce702beef5f3ad66303b0ed1a5d4cb44966c6584c3826040518082815260200191505060405180910390a1600190505b5b919050565b6000823373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561152f576115f4565b8260016000866000191660001916815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1685600019167f7b97c62130aa09acbbcbf7482630e756592496f1759eaf702f469cf64dfb779460405180905060405180910390a4600191505b5b5092915050565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600160008460001916600019168152602001908152602001600020600201826040518082805190602001908083835b602083106116755780518252602082019150602081019050602083039250611652565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390205490505b92915050565b6000600060016000846000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141590505b919050565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561177357611821565b7fdef931299fe61d176f949118058530c1f3f539dcb6950b4e372c9b835c33ca073073ffffffffffffffffffffffffffffffffffffffff16316040518082815260200191505060405180910390a13373ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051809050600060405180830381858888f19350505050151561181b57610000565b600190505b5b90565b60006000836040518082805190602001908083835b6020831061185c5780518252602082019150602081019050602083039250611839565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390203373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561190157611d83565b846040518082805190602001908083835b602083106119355780518252602082019150602081019050602083039250611912565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209150600060016000846000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614158015611ab4575081600019166002600060016000866000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518082805460018160011615610100020316600290048015611aa15780601f10611a7f576101008083540402835291820191611aa1565b820191906000526020600020905b815481529060010190602001808311611a8d575b5050915050604051809103902060001916145b15611c79576002600060016000856000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805460018160011615610100020316600290046000825580601f10611b5b5750611b92565b601f016020900490600052602060002090810190611b9191905b80821115611b8d576000816000905550600101611b75565b5090565b5b5060016000836000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16856040518082805190602001908083835b60208310611c1c5780518252602082019150602081019050602083039250611bf9565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd60405180905060405180910390a35b8360016000846000191660001916815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508373ffffffffffffffffffffffffffffffffffffffff16856040518082805190602001908083835b60208310611d215780518252602082019150602081019050602083039250611cfe565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f728435a0031f6a04538fcdd24922a7e06bc7bc945db03e83d22122d1bc5f28df60405180905060405180910390a3600192505b5b505092915050565b6000600060016000846000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141590505b919050565b6000600160008460001916600019168152602001908152602001600020600201826040518082805190602001908083835b60208310611e425780518252602082019150602081019050602083039250611e1f565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020546001900490505b92915050565b60035481565b600060016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b919050565b600060016000836000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b919050565b6020604051908101604052806000815250600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611fff5780601f10611fd457610100808354040283529160200191611fff565b820191906000526020600020905b815481529060010190602001808311611fe257829003601f168201915b505050505090505b919050565b6000833373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415156120875761222e565b82600102600160008760001916600019168152602001908152602001600020600201856040518082805190602001908083835b602083106120dd57805182526020820191506020810190506020830392506120ba565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390208160001916905550836040518082805190602001908083835b6020831061214c5780518252602082019150602081019050602083039250612129565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902085600019167fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea8660405180806020018281038252838181518152602001915080519060200190808383600083146121ef575b8051825260208311156121ef576020820191506020810190506020830392506121cb565b505050905090810190601f16801561221b5780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b509392505050565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156122945761241f565b82600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061231d57805160ff191683800117855561234b565b8280016001018555821561234b579182015b8281111561234a57825182559160200191906001019061232f565b5b50905061237091905b8082111561236c576000816000905550600101612354565b5090565b50508173ffffffffffffffffffffffffffffffffffffffff16836040518082805190602001908083835b602083106123bd578051825260208201915060208101905060208303925061239a565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c9192060405180905060405180910390a3600190505b5b92915050565b3373ffffffffffffffffffffffffffffffffffffffff16600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180828054600181600116156101000203166002900480156124d65780601f106124b45761010080835404028352918201916124d6565b820191906000526020600020905b8154815290600101906020018083116124c2575b505091505060405180910390207f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd60405180905060405180910390a360016000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180828054600181600116156101000203166002900480156125b05780601f1061258e5761010080835404028352918201916125b0565b820191906000526020600020905b81548152906001019060200180831161259c575b505091505060405180910390206000191660001916815260200190815260200160002060010160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805460018160011615610100020316600290046000825580601f1061265d5750612694565b601f01602090049060005260206000209081019061269391905b8082111561268f576000816000905550600101612677565b5090565b5b505b565b6000833373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515612713576128d0565b8273ffffffffffffffffffffffffffffffffffffffff16600102600160008760001916600019168152602001908152602001600020600201856040518082805190602001908083835b6020831061277f578051825260208201915060208101905060208303925061275c565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390208160001916905550836040518082805190602001908083835b602083106127ee57805182526020820191506020810190506020830392506127cb565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902085600019167fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea866040518080602001828103825283818151815260200191508051906020019080838360008314612891575b8051825260208311156128915760208201915060208101905060208303925061286d565b505050905090810190601f1680156128bd5780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b5093925050505600a165627a7a7230582066b2da4773a0f1d81efe071c66b51c46868a871661efd18c0f629353ff4c1f9b0029" }, "00a329c0648769a73afac7f9381e08fb43dbea72": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } } diff --git a/ethcore/res/null.json b/ethcore/res/null.json index 7fa41a8def..5128f26c59 100644 --- a/ethcore/res/null.json +++ b/ethcore/res/null.json @@ -36,9 +36,50 @@ "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "0", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "0", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, + "0000000000000000000000000000000000000006": { + "balance": "1", + "builtin": { + "name": "alt_bn128_add", + "activate_at": 0, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "balance": "1", + "builtin": { + "name": "alt_bn128_mul", + "activate_at": 0, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "balance": "1", + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": 0, + "eip1108_transition": "0x7fffffffffffff", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, "9cce34f7ab185c7aba1b7c8140d620b4bda941d6": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "0" } } } diff --git a/ethcore/service/Cargo.toml b/ethcore/service/Cargo.toml index 7db0ad2770..c0be41038b 100644 --- a/ethcore/service/Cargo.toml +++ b/ethcore/service/Cargo.toml @@ -1,4 +1,5 @@ [package] +description = "Parity Ethereum (EthCore) Client & Network Service Creation & Registration with the I/O Subsystem" name = "ethcore-service" version = "0.1.0" authors = ["Parity Technologies "] diff --git a/ethcore/service/src/error.rs b/ethcore/service/src/error.rs index 483409535a..c73cb0dfc1 100644 --- a/ethcore/service/src/error.rs +++ b/ethcore/service/src/error.rs @@ -14,17 +14,18 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +// Silence: `use of deprecated item 'std::error::Error::cause': replaced by Error::source, which can support downcasting` +// https://github.com/paritytech/parity-ethereum/issues/10302 +#![allow(deprecated)] + use ethcore; use io; use ethcore_private_tx; error_chain! { - links { - PrivateTransactions(ethcore_private_tx::Error, ethcore_private_tx::ErrorKind); - } - foreign_links { Ethcore(ethcore::error::Error); IoError(io::IoError); + PrivateTransactions(ethcore_private_tx::Error); } } diff --git a/ethcore/service/src/service.rs b/ethcore/service/src/service.rs index 831d1f0e45..0953970376 100644 --- a/ethcore/service/src/service.rs +++ b/ethcore/service/src/service.rs @@ -30,11 +30,12 @@ use blockchain::{BlockChainDB, BlockChainDBHandler}; use ethcore::client::{Client, ClientConfig, ChainNotify, ClientIoMessage}; use ethcore::miner::Miner; use ethcore::snapshot::service::{Service as SnapshotService, ServiceParams as SnapServiceParams}; -use ethcore::snapshot::{SnapshotService as _SnapshotService, RestorationStatus}; +use ethcore::snapshot::{SnapshotService as _SnapshotService, RestorationStatus, Error as SnapshotError}; use ethcore::spec::Spec; -use ethcore::account_provider::AccountProvider; +use ethcore::error::{Error as EthcoreError, ErrorKind}; -use ethcore_private_tx::{self, Importer}; + +use ethcore_private_tx::{self, Importer, Signer}; use Error; pub struct PrivateTxService { @@ -96,9 +97,10 @@ impl ClientService { restoration_db_handler: Box, _ipc_path: &Path, miner: Arc, - account_provider: Arc, + signer: Arc, encryptor: Box, private_tx_conf: ethcore_private_tx::ProviderConfig, + private_encryptor_conf: ethcore_private_tx::EncryptorConfig, ) -> Result { let io_service = IoService::::start()?; @@ -127,13 +129,18 @@ impl ClientService { }; let snapshot = Arc::new(SnapshotService::new(snapshot_params)?); + let private_keys = Arc::new(ethcore_private_tx::SecretStoreKeys::new( + client.clone(), + private_encryptor_conf.key_server_account, + )); let provider = Arc::new(ethcore_private_tx::Provider::new( - client.clone(), - miner, - account_provider, - encryptor, - private_tx_conf, - io_service.channel(), + client.clone(), + miner, + signer, + encryptor, + private_tx_conf, + io_service.channel(), + private_keys, )); let private_tx = Arc::new(PrivateTxService::new(provider)); @@ -192,6 +199,7 @@ impl ClientService { /// Shutdown the Client Service pub fn shutdown(&self) { + trace!(target: "shutdown", "Shutting down Client Service"); self.snapshot.shutdown(); } } @@ -252,7 +260,11 @@ impl IoHandler for ClientIoHandler { let res = thread::Builder::new().name("Periodic Snapshot".into()).spawn(move || { if let Err(e) = snapshot.take_snapshot(&*client, num) { - warn!("Failed to take snapshot at block #{}: {}", num, e); + match e { + EthcoreError(ErrorKind::Snapshot(SnapshotError::SnapshotAborted), _) => info!("Snapshot aborted"), + _ => warn!("Failed to take snapshot at block #{}: {}", num, e), + } + } }); @@ -276,7 +288,6 @@ mod tests { use tempdir::TempDir; use ethcore_db::NUM_COLUMNS; - use ethcore::account_provider::AccountProvider; use ethcore::client::ClientConfig; use ethcore::miner::Miner; use ethcore::spec::Spec; @@ -311,9 +322,10 @@ mod tests { restoration_db_handler, tempdir.path(), Arc::new(Miner::new_for_tests(&spec, None)), - Arc::new(AccountProvider::transient_provider()), + Arc::new(ethcore_private_tx::DummySigner), Box::new(ethcore_private_tx::NoopEncryptor), Default::default(), + Default::default(), ); assert!(service.is_ok()); drop(service.unwrap()); diff --git a/ethcore/src/account_db.rs b/ethcore/src/account_db.rs index 5b7bd52753..a389c009bf 100644 --- a/ethcore/src/account_db.rs +++ b/ethcore/src/account_db.rs @@ -17,11 +17,10 @@ //! DB backend wrapper for Account trie use ethereum_types::H256; use hash::{KECCAK_NULL_RLP, keccak}; -use hashdb::{HashDB, AsHashDB}; +use hash_db::{HashDB, AsHashDB}; use keccak_hasher::KeccakHasher; use kvdb::DBValue; use rlp::NULL_RLP; -use std::collections::HashMap; #[cfg(test)] use ethereum_types::Address; @@ -99,15 +98,11 @@ impl<'db> AccountDB<'db> { } impl<'db> AsHashDB for AccountDB<'db> { - fn as_hashdb(&self) -> &HashDB { self } - fn as_hashdb_mut(&mut self) -> &mut HashDB { self } + fn as_hash_db(&self) -> &HashDB { self } + fn as_hash_db_mut(&mut self) -> &mut HashDB { self } } impl<'db> HashDB for AccountDB<'db> { - fn keys(&self) -> HashMap { - unimplemented!() - } - fn get(&self, key: &H256) -> Option { if key == &KECCAK_NULL_RLP { return Some(DBValue::from_slice(&NULL_RLP)); @@ -163,10 +158,6 @@ impl<'db> AccountDBMut<'db> { } impl<'db> HashDB for AccountDBMut<'db>{ - fn keys(&self) -> HashMap { - unimplemented!() - } - fn get(&self, key: &H256) -> Option { if key == &KECCAK_NULL_RLP { return Some(DBValue::from_slice(&NULL_RLP)); @@ -209,22 +200,18 @@ impl<'db> HashDB for AccountDBMut<'db>{ } impl<'db> AsHashDB for AccountDBMut<'db> { - fn as_hashdb(&self) -> &HashDB { self } - fn as_hashdb_mut(&mut self) -> &mut HashDB { self } + fn as_hash_db(&self) -> &HashDB { self } + fn as_hash_db_mut(&mut self) -> &mut HashDB { self } } struct Wrapping<'db>(&'db HashDB); impl<'db> AsHashDB for Wrapping<'db> { - fn as_hashdb(&self) -> &HashDB { self } - fn as_hashdb_mut(&mut self) -> &mut HashDB { self } + fn as_hash_db(&self) -> &HashDB { self } + fn as_hash_db_mut(&mut self) -> &mut HashDB { self } } impl<'db> HashDB for Wrapping<'db> { - fn keys(&self) -> HashMap { - unimplemented!() - } - fn get(&self, key: &H256) -> Option { if key == &KECCAK_NULL_RLP { return Some(DBValue::from_slice(&NULL_RLP)); @@ -254,15 +241,11 @@ impl<'db> HashDB for Wrapping<'db> { struct WrappingMut<'db>(&'db mut HashDB); impl<'db> AsHashDB for WrappingMut<'db> { - fn as_hashdb(&self) -> &HashDB { self } - fn as_hashdb_mut(&mut self) -> &mut HashDB { self } + fn as_hash_db(&self) -> &HashDB { self } + fn as_hash_db_mut(&mut self) -> &mut HashDB { self } } impl<'db> HashDB for WrappingMut<'db>{ - fn keys(&self) -> HashMap { - unimplemented!() - } - fn get(&self, key: &H256) -> Option { if key == &KECCAK_NULL_RLP { return Some(DBValue::from_slice(&NULL_RLP)); diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index e5fcb45161..56cfc1c4c1 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -31,7 +31,7 @@ //! `ExecutedBlock` is an underlaying data structure used by all structs above to store block //! related info. -use std::cmp; +use std::{cmp, ops}; use std::collections::HashSet; use std::sync::Arc; @@ -52,7 +52,6 @@ use vm::{EnvInfo, LastHashes}; use hash::keccak; use rlp::{RlpStream, Encodable, encode_list}; use types::transaction::{SignedTransaction, Error as TransactionError}; -use types::block::Block; use types::header::{Header, ExtendedHeader}; use types::receipt::{Receipt, TransactionOutcome}; @@ -155,69 +154,15 @@ impl ExecutedBlock { } } -/// Trait for a object that is a `ExecutedBlock`. -pub trait IsBlock { - /// Get the `ExecutedBlock` associated with this object. - fn block(&self) -> &ExecutedBlock; - - /// Get the base `Block` object associated with this. - fn to_base(&self) -> Block { - Block { - header: self.header().clone(), - transactions: self.transactions().iter().cloned().map(Into::into).collect(), - uncles: self.uncles().to_vec(), - } - } - - /// Get the header associated with this object's block. - fn header(&self) -> &Header { &self.block().header } - - /// Get the final state associated with this object's block. - fn state(&self) -> &State { &self.block().state } - - /// Get all information on transactions in this block. - fn transactions(&self) -> &[SignedTransaction] { &self.block().transactions } - - /// Get all information on receipts in this block. - fn receipts(&self) -> &[Receipt] { &self.block().receipts } - - /// Get all uncles in this block. - fn uncles(&self) -> &[Header] { &self.block().uncles } -} - /// Trait for an object that owns an `ExecutedBlock` pub trait Drain { /// Returns `ExecutedBlock` fn drain(self) -> ExecutedBlock; } -impl IsBlock for ExecutedBlock { - fn block(&self) -> &ExecutedBlock { self } -} - -impl ::parity_machine::LiveBlock for ExecutedBlock { - type Header = Header; - - fn header(&self) -> &Header { - &self.header - } - - fn uncles(&self) -> &[Header] { - &self.uncles - } -} - -impl ::parity_machine::Transactions for ExecutedBlock { - type Transaction = SignedTransaction; - - fn transactions(&self) -> &[SignedTransaction] { - &self.transactions - } -} - impl<'x> OpenBlock<'x> { /// Create a new `OpenBlock` ready for transaction pushing. - pub fn new<'a>( + pub fn new<'a, I: IntoIterator>( engine: &'x EthEngine, factories: Factories, tracing: bool, @@ -228,7 +173,7 @@ impl<'x> OpenBlock<'x> { gas_range_target: (U256, U256), extra_data: Bytes, is_epoch_begin: bool, - ancestry: &mut Iterator, + ancestry: I, ) -> Result { let number = parent.number() + 1; let state = State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce(number), factories)?; @@ -250,7 +195,7 @@ impl<'x> OpenBlock<'x> { engine.populate_from_parent(&mut r.block.header, parent); engine.machine().on_new_block(&mut r.block)?; - engine.on_new_block(&mut r.block, is_epoch_begin, ancestry)?; + engine.on_new_block(&mut r.block, is_epoch_begin, &mut ancestry.into_iter())?; Ok(r) } @@ -270,7 +215,7 @@ impl<'x> OpenBlock<'x> { /// NOTE Will check chain constraints and the uncle number but will NOT check /// that the header itself is actually valid. pub fn push_uncle(&mut self, valid_uncle_header: Header) -> Result<(), BlockError> { - let max_uncles = self.engine.maximum_uncle_count(self.block.header().number()); + let max_uncles = self.engine.maximum_uncle_count(self.block.header.number()); if self.block.uncles.len() + 1 > max_uncles { return Err(BlockError::TooManyUncles(OutOfBounds{ min: None, @@ -284,11 +229,6 @@ impl<'x> OpenBlock<'x> { Ok(()) } - /// Get the environment info concerning this block. - pub fn env_info(&self) -> EnvInfo { - self.block.env_info() - } - /// Push a transaction into the block. /// /// If valid, it will be executed, and archived together with the receipt. @@ -297,7 +237,7 @@ impl<'x> OpenBlock<'x> { return Err(TransactionError::AlreadyImported.into()); } - let env_info = self.env_info(); + let env_info = self.block.env_info(); let outcome = self.block.state.apply(&env_info, self.engine.machine(), &t, self.block.traces.is_enabled())?; self.block.transactions_set.insert(h.unwrap_or_else(||t.hash())); @@ -344,7 +284,6 @@ impl<'x> OpenBlock<'x> { self.block.header.set_difficulty(*header.difficulty()); self.block.header.set_gas_limit(*header.gas_limit()); self.block.header.set_timestamp(header.timestamp()); - self.block.header.set_author(*header.author()); self.block.header.set_uncles_hash(*header.uncles_hash()); self.block.header.set_transactions_root(*header.transactions_root()); // TODO: that's horrible. set only for backwards compatibility @@ -394,22 +333,39 @@ impl<'x> OpenBlock<'x> { pub fn block_mut(&mut self) -> &mut ExecutedBlock { &mut self.block } } -impl<'x> IsBlock for OpenBlock<'x> { - fn block(&self) -> &ExecutedBlock { &self.block } +impl<'a> ops::Deref for OpenBlock<'a> { + type Target = ExecutedBlock; + + fn deref(&self) -> &Self::Target { + &self.block + } } -impl IsBlock for ClosedBlock { - fn block(&self) -> &ExecutedBlock { &self.block } +impl ops::Deref for ClosedBlock { + type Target = ExecutedBlock; + + fn deref(&self) -> &Self::Target { + &self.block + } } -impl IsBlock for LockedBlock { - fn block(&self) -> &ExecutedBlock { &self.block } +impl ops::Deref for LockedBlock { + type Target = ExecutedBlock; + + fn deref(&self) -> &Self::Target { + &self.block + } } -impl ClosedBlock { - /// Get the hash of the header without seal arguments. - pub fn hash(&self) -> H256 { self.header().bare_hash() } +impl ops::Deref for SealedBlock { + type Target = ExecutedBlock; + + fn deref(&self) -> &Self::Target { + &self.block + } +} +impl ClosedBlock { /// Turn this into a `LockedBlock`, unable to be reopened again. pub fn lock(self) -> LockedBlock { LockedBlock { @@ -443,25 +399,25 @@ impl LockedBlock { self.block.header.set_receipts_root( ordered_trie_root(self.block.receipts.iter().map(|r| r.rlp_bytes())) ); - // compute hash and cache it. - self.block.header.compute_hash(); } - /// Get the hash of the header without seal arguments. - pub fn hash(&self) -> H256 { self.header().bare_hash() } - /// Provide a valid seal in order to turn this into a `SealedBlock`. /// /// NOTE: This does not check the validity of `seal` with the engine. - pub fn seal(self, engine: &EthEngine, seal: Vec) -> Result { - let expected_seal_fields = engine.seal_fields(self.header()); + pub fn seal(self, engine: &EthEngine, seal: Vec) -> Result { + let expected_seal_fields = engine.seal_fields(&self.header); let mut s = self; if seal.len() != expected_seal_fields { - return Err(BlockError::InvalidSealArity( - Mismatch { expected: expected_seal_fields, found: seal.len() })); + Err(BlockError::InvalidSealArity(Mismatch { + expected: expected_seal_fields, + found: seal.len() + }))?; } + s.block.header.set_seal(seal); + engine.on_seal_block(&mut s.block)?; s.block.header.compute_hash(); + Ok(SealedBlock { block: s.block }) @@ -470,6 +426,7 @@ impl LockedBlock { /// Provide a valid seal in order to turn this into a `SealedBlock`. /// This does check the validity of `seal` with the engine. /// Returns the `ClosedBlock` back again if the seal is no good. + /// TODO(https://github.com/paritytech/parity-ethereum/issues/10407): This is currently only used in POW chain call paths, we should really merge it with seal() above. pub fn try_seal( self, engine: &EthEngine, @@ -510,12 +467,8 @@ impl Drain for SealedBlock { } } -impl IsBlock for SealedBlock { - fn block(&self) -> &ExecutedBlock { &self.block } -} - /// Enact the block given by block header, transactions and uncles -fn enact( +pub(crate) fn enact( header: Header, transactions: Vec, uncles: Vec
, @@ -528,13 +481,12 @@ fn enact( is_epoch_begin: bool, ancestry: &mut Iterator, ) -> Result { - { - if ::log::max_level() >= ::log::Level::Trace { - let s = State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce(parent.number() + 1), factories.clone())?; - trace!(target: "enact", "num={}, root={}, author={}, author_balance={}\n", - header.number(), s.root(), header.author(), s.balance(&header.author())?); - } - } + // For trace log + let trace_state = if log_enabled!(target: "enact", ::log::Level::Trace) { + Some(State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce(parent.number() + 1), factories.clone())?) + } else { + None + }; let mut b = OpenBlock::new( engine, @@ -543,13 +495,23 @@ fn enact( db, parent, last_hashes, - Address::new(), + // Engine such as Clique will calculate author from extra_data. + // this is only important for executing contracts as the 'executive_author'. + engine.executive_author(&header)?, (3141562.into(), 31415620.into()), vec![], is_epoch_begin, ancestry, )?; + if let Some(ref s) = trace_state { + let env = b.env_info(); + let root = s.root(); + let author_balance = s.balance(&env.author)?; + trace!(target: "enact", "num={}, root={}, author={}, author_balance={}\n", + b.block.header.number(), root, env.author, author_balance); + } + b.populate_from(&header); b.push_transactions(transactions)?; @@ -615,6 +577,7 @@ mod tests { last_hashes: Arc, factories: Factories, ) -> Result { + let block = Unverified::from_rlp(block_bytes)?; let header = block.header; let transactions: Result, Error> = block @@ -644,7 +607,7 @@ mod tests { (3141562.into(), 31415620.into()), vec![], false, - &mut Vec::new().into_iter(), + None, )?; b.populate_from(&header); @@ -669,7 +632,7 @@ mod tests { ) -> Result { let header = Unverified::from_rlp(block_bytes.clone())?.header; Ok(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, factories)? - .seal(engine, header.seal().to_vec())?) + .seal(engine, header.seal().to_vec())?) } #[test] @@ -679,7 +642,7 @@ mod tests { let genesis_header = spec.genesis_header(); let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let b = b.close_and_lock().unwrap(); let _ = b.seal(&*spec.engine, vec![]); } @@ -693,7 +656,7 @@ mod tests { let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap() + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap() .close_and_lock().unwrap().seal(engine, vec![]).unwrap(); let orig_bytes = b.rlp_bytes(); let orig_db = b.drain().state.drop().1; @@ -717,7 +680,7 @@ mod tests { let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let mut uncle1_header = Header::new(); uncle1_header.set_extra_data(b"uncle1".to_vec()); let mut uncle2_header = Header::new(); diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index 499e3c8f6c..bca2aeeaac 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -16,21 +16,26 @@ //! Standard built-in contracts. -use std::cmp::{max, min}; -use std::io::{self, Read}; - -use byteorder::{ByteOrder, BigEndian}; -use parity_crypto::digest; -use num::{BigUint, Zero, One}; - -use hash::keccak; +use std::{ + cmp::{max, min}, + io::{self, Read, Cursor}, + mem::size_of, +}; + +use bn; +use byteorder::{BigEndian, LittleEndian, ByteOrder, ReadBytesExt}; use ethereum_types::{H256, U256}; -use bytes::BytesRef; -use ethkey::{Signature, recover as ec_recover}; use ethjson; +use ethkey::{Signature, recover as ec_recover}; +use hash::keccak; +use log::{warn, trace}; +use num::{BigUint, Zero, One}; +use bytes::BytesRef; +use parity_crypto::digest; +use eip_152::compress; /// Execution error. -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub struct Error(pub &'static str); impl From<&'static str> for Error { @@ -52,9 +57,27 @@ pub trait Impl: Send + Sync { } /// A gas pricing scheme for built-in contracts. -pub trait Pricer: Send + Sync { - /// The gas cost of running this built-in for the given input data. - fn cost(&self, input: &[u8]) -> U256; +// TODO: refactor this trait, see https://github.com/paritytech/parity-ethereum/issues/11014 +trait Pricer: Send + Sync { + /// The gas cost of running this built-in for the given input data at block number `at` + fn cost(&self, input: &[u8], at: u64) -> U256; +} + +/// Pricing for the Blake2 compression function (aka "F"). +/// Computes the price as a fixed cost per round where the number of rounds is part of the input +/// byte slice. +pub type Blake2FPricer = u64; + +impl Pricer for Blake2FPricer { + fn cost(&self, input: &[u8], _at: u64) -> U256 { + use std::convert::TryInto; + let (rounds_bytes, _) = input.split_at(std::mem::size_of::()); + // Returning zero if the conversion fails is fine because `execute()` will check the length + // and bail with the appropriate error. + let rounds = u32::from_be_bytes(rounds_bytes.try_into().unwrap_or([0u8; 4])); +// U256::from(*self as u128 * rounds as u128) + U256::from(*self as u64 * rounds as u64) + } } /// A linear pricing model. This computes a price using a base cost and a cost per-word. @@ -69,26 +92,56 @@ struct ModexpPricer { } impl Pricer for Linear { - fn cost(&self, input: &[u8]) -> U256 { + fn cost(&self, input: &[u8], _at: u64) -> U256 { U256::from(self.base) + U256::from(self.word) * U256::from((input.len() + 31) / 32) } } -/// A alt_bn128_parinig pricing model. This computes a price using a base cost and a cost per pair. -struct AltBn128PairingPricer { +/// alt_bn128 constant operations (add and mul) pricing model. +struct AltBn128ConstOperations { + price: usize, + eip1108_transition_at: u64, + eip1108_transition_price: usize, +} + +impl Pricer for AltBn128ConstOperations { + fn cost(&self, _input: &[u8], at: u64) -> U256 { + if at >= self.eip1108_transition_at { + self.eip1108_transition_price.into() + } else { + self.price.into() + } + } +} + +/// alt_bn128 pairing price +#[derive(Debug, Copy, Clone)] +struct AltBn128PairingPrice { base: usize, pair: usize, } +/// alt_bn128_pairing pricing model. This computes a price using a base cost and a cost per pair. +struct AltBn128PairingPricer { + price: AltBn128PairingPrice, + eip1108_transition_at: u64, + eip1108_transition_price: AltBn128PairingPrice, +} + impl Pricer for AltBn128PairingPricer { - fn cost(&self, input: &[u8]) -> U256 { - let cost = U256::from(self.base) + U256::from(self.pair) * U256::from(input.len() / 192); - cost + fn cost(&self, input: &[u8], at: u64) -> U256 { + let price = if at >= self.eip1108_transition_at { + self.eip1108_transition_price + } else { + self.price + }; + + U256::from(price.base) + U256::from(price.pair) * U256::from(input.len() / 192) } } impl Pricer for ModexpPricer { - fn cost(&self, input: &[u8]) -> U256 { + fn cost(&self, input: &[u8], _at: u64) -> U256 { let mut reader = input.chain(io::repeat(0)); let mut buf = [0; 32]; @@ -157,14 +210,16 @@ impl ModexpPricer { /// /// Unless `is_active` is true, pub struct Builtin { - pricer: Box, - native: Box, + pricer: Box, + native: Box, activate_at: u64, } impl Builtin { /// Simple forwarder for cost. - pub fn cost(&self, input: &[u8]) -> U256 { self.pricer.cost(input) } + pub fn cost(&self, input: &[u8], at: u64) -> U256 { + self.pricer.cost(input, at) + } /// Simple forwarder for execute. pub fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { @@ -172,12 +227,17 @@ impl Builtin { } /// Whether the builtin is activated at the given block number. - pub fn is_active(&self, at: u64) -> bool { at >= self.activate_at } + pub fn is_active(&self, at: u64) -> bool { + at >= self.activate_at + } } impl From for Builtin { fn from(b: ethjson::spec::Builtin) -> Self { - let pricer: Box = match b.pricing { + let pricer: Box = match b.pricing { + ethjson::spec::Pricing::Blake2F { gas_per_round } => { + Box::new(gas_per_round) + }, ethjson::spec::Pricing::Linear(linear) => { Box::new(Linear { base: linear.base, @@ -187,7 +247,7 @@ impl From for Builtin { ethjson::spec::Pricing::Modexp(exp) => { Box::new(ModexpPricer { divisor: if exp.divisor == 0 { - warn!("Zero modexp divisor specified. Falling back to default."); + warn!(target: "builtin", "Zero modexp divisor specified. Falling back to default."); 10 } else { exp.divisor @@ -196,31 +256,46 @@ impl From for Builtin { } ethjson::spec::Pricing::AltBn128Pairing(pricer) => { Box::new(AltBn128PairingPricer { - base: pricer.base, - pair: pricer.pair, + price: AltBn128PairingPrice { + base: pricer.base, + pair: pricer.pair, + }, + eip1108_transition_at: b.eip1108_transition.map_or(u64::max_value(), Into::into), + eip1108_transition_price: AltBn128PairingPrice { + base: pricer.eip1108_transition_base, + pair: pricer.eip1108_transition_pair, + }, + }) + } + ethjson::spec::Pricing::AltBn128ConstOperations(pricer) => { + Box::new(AltBn128ConstOperations { + price: pricer.price, + eip1108_transition_price: pricer.eip1108_transition_price, + eip1108_transition_at: b.eip1108_transition.map_or(u64::max_value(), Into::into) }) } }; Builtin { - pricer: pricer, + pricer, native: ethereum_builtin(&b.name), - activate_at: b.activate_at.map(Into::into).unwrap_or(0), + activate_at: b.activate_at.map_or(0, Into::into), } } } /// Ethereum built-in factory. -pub fn ethereum_builtin(name: &str) -> Box { +pub fn ethereum_builtin(name: &str) -> Box { match name { - "identity" => Box::new(Identity) as Box, - "ecrecover" => Box::new(EcRecover) as Box, - "sha256" => Box::new(Sha256) as Box, - "ripemd160" => Box::new(Ripemd160) as Box, - "modexp" => Box::new(ModexpImpl) as Box, - "alt_bn128_add" => Box::new(Bn128AddImpl) as Box, - "alt_bn128_mul" => Box::new(Bn128MulImpl) as Box, - "alt_bn128_pairing" => Box::new(Bn128PairingImpl) as Box, + "identity" => Box::new(Identity) as Box, + "ecrecover" => Box::new(EcRecover) as Box, + "sha256" => Box::new(Sha256) as Box, + "ripemd160" => Box::new(Ripemd160) as Box, + "modexp" => Box::new(ModexpImpl) as Box, + "alt_bn128_add" => Box::new(Bn128AddImpl) as Box, + "alt_bn128_mul" => Box::new(Bn128MulImpl) as Box, + "alt_bn128_pairing" => Box::new(Bn128PairingImpl) as Box, + "blake2_f" => Box::new(Blake2F) as Box, _ => panic!("invalid builtin name: {}", name), } } @@ -232,6 +307,10 @@ pub fn ethereum_builtin(name: &str) -> Box { // - sha256 // - ripemd160 // - modexp (EIP198) +// - alt_bn128_add +// - alt_bn128_mul +// - alt_bn128_pairing +// - blake2_f (The Blake2 compression function F, EIP-152) #[derive(Debug)] struct Identity; @@ -257,8 +336,11 @@ struct Bn128MulImpl; #[derive(Debug)] struct Bn128PairingImpl; +#[derive(Debug)] +struct Blake2F; + impl Impl for Identity { - fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { +fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { output.write(0, input); Ok(()) } @@ -302,6 +384,60 @@ impl Impl for Sha256 { } } +impl Impl for Blake2F { + /// Format of `input`: + /// [4 bytes for rounds][64 bytes for h][128 bytes for m][8 bytes for t_0][8 bytes for t_1][1 byte for f] + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { + const BLAKE2_F_ARG_LEN: usize = 213; + const PROOF: &str = "Checked the length of the input above; qed"; + + if input.len() != BLAKE2_F_ARG_LEN { + trace!(target: "builtin", "input length for Blake2 F precompile should be exactly 213 bytes, was {}", input.len()); + return Err("input length for Blake2 F precompile should be exactly 213 bytes".into()) + } + + let mut cursor = Cursor::new(input); + let rounds = cursor.read_u32::().expect(PROOF); + + // state vector, h + let mut h = [0u64; 8]; + for state_word in h.iter_mut() { + *state_word = cursor.read_u64::().expect(PROOF); + } + + // message block vector, m + let mut m = [0u64; 16]; + for msg_word in m.iter_mut() { + *msg_word = cursor.read_u64::().expect(PROOF); + } + + // 2w-bit offset counter, t + let t = [ + cursor.read_u64::().expect(PROOF), + cursor.read_u64::().expect(PROOF), + ]; + + // final block indicator flag, "f" + let f = match input.last() { + Some(1) => true, + Some(0) => false, + _ => { + trace!(target: "builtin", "incorrect final block indicator flag, was: {:?}", input.last()); + return Err("incorrect final block indicator flag".into()) + } + }; + + compress(&mut h, m, t, f, rounds as usize); + + let mut output_buf = [0u8; 8 * size_of::()]; + for (i, state_word) in h.iter().enumerate() { + output_buf[i*8..(i+1)*8].copy_from_slice(&state_word.to_le_bytes()); + } + output.write(0, &output_buf[..]); + Ok(()) + } +} + impl Impl for Ripemd160 { fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { let hash = digest::ripemd160(input); @@ -450,7 +586,7 @@ impl Impl for Bn128AddImpl { if let Some(sum) = AffineG1::from_jacobian(p1 + p2) { // point not at infinity sum.x().to_big_endian(&mut write_buf[0..32]).expect("Cannot fail since 0..32 is 32-byte length"); - sum.y().to_big_endian(&mut write_buf[32..64]).expect("Cannot fail since 32..64 is 32-byte length");; + sum.y().to_big_endian(&mut write_buf[32..64]).expect("Cannot fail since 32..64 is 32-byte length"); } output.write(0, &write_buf); @@ -471,7 +607,7 @@ impl Impl for Bn128MulImpl { if let Some(sum) = AffineG1::from_jacobian(p * fr) { // point not at infinity sum.x().to_big_endian(&mut write_buf[0..32]).expect("Cannot fail since 0..32 is 32-byte length"); - sum.y().to_big_endian(&mut write_buf[32..64]).expect("Cannot fail since 32..64 is 32-byte length");; + sum.y().to_big_endian(&mut write_buf[32..64]).expect("Cannot fail since 32..64 is 32-byte length"); } output.write(0, &write_buf); Ok(()) @@ -489,7 +625,7 @@ impl Impl for Bn128PairingImpl { } if let Err(err) = self.execute_with_error(input, output) { - trace!("Pairining error: {:?}", err); + trace!(target: "builtin", "Pairing error: {:?}", err); return Err(err) } Ok(()) @@ -558,12 +694,120 @@ impl Bn128PairingImpl { #[cfg(test)] mod tests { - use super::{Builtin, Linear, ethereum_builtin, Pricer, ModexpPricer, modexp as me}; - use ethjson; use ethereum_types::U256; - use bytes::BytesRef; - use rustc_hex::FromHex; + use ethjson::uint::Uint; use num::{BigUint, Zero, One}; + use bytes::BytesRef; +use hex_literal::hex; + use super::{Builtin, Linear, ethereum_builtin, Pricer, ModexpPricer, modexp as me}; + + #[test] + fn blake2f_cost() { + let f = Builtin { + pricer: Box::new(123), + native: ethereum_builtin("blake2_f"), + activate_at: 0, + }; + // 5 rounds + let input = hex!("0000000548c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001"); + let mut output = [0u8; 64]; + f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).unwrap(); + + assert_eq!(f.cost(&input[..], 0), U256::from(123*5)); + } + + #[test] + fn blake2_f_is_err_on_invalid_length() { + let blake2 = ethereum_builtin("blake2_f"); + // Test vector 1 and expected output from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-152.md#test-vector-1 + let input = hex!("00000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001"); + let mut out = [0u8; 64]; + + let result = blake2.execute(&input[..], &mut BytesRef::Fixed(&mut out[..])); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), "input length for Blake2 F precompile should be exactly 213 bytes".into()); + } + + #[test] + fn blake2_f_is_err_on_invalid_length_2() { + let blake2 = ethereum_builtin("blake2_f"); + // Test vector 2 and expected output from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-152.md#test-vector-2 + let input = hex!("000000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001"); + let mut out = [0u8; 64]; + + let result = blake2.execute(&input[..], &mut BytesRef::Fixed(&mut out[..])); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), "input length for Blake2 F precompile should be exactly 213 bytes".into()); + } + + #[test] + fn blake2_f_is_err_on_bad_finalization_flag() { + let blake2 = ethereum_builtin("blake2_f"); + // Test vector 3 and expected output from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-152.md#test-vector-3 + let input = hex!("0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000002"); + let mut out = [0u8; 64]; + + let result = blake2.execute(&input[..], &mut BytesRef::Fixed(&mut out[..])); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), "incorrect final block indicator flag".into()); + } + + #[test] + fn blake2_f_zero_rounds_is_ok_test_vector_4() { + let blake2 = ethereum_builtin("blake2_f"); + // Test vector 4 and expected output from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-152.md#test-vector-4 + let input = hex!("0000000048c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001"); + let expected = hex!("08c9bcf367e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d282e6ad7f520e511f6c3e2b8c68059b9442be0454267ce079217e1319cde05b"); + let mut output = [0u8; 64]; + blake2.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).unwrap(); + assert_eq!(&output[..], &expected[..]); + } + + #[test] + fn blake2_f_test_vector_5() { + let blake2 = ethereum_builtin("blake2_f"); + // Test vector 5 and expected output from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-152.md#test-vector-5 + let input = hex!("0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001"); + let expected = hex!("ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"); + let mut out = [0u8; 64]; + blake2.execute(&input[..], &mut BytesRef::Fixed(&mut out[..])).unwrap(); + assert_eq!(&out[..], &expected[..]); + } + + #[test] + fn blake2_f_test_vector_6() { + let blake2 = ethereum_builtin("blake2_f"); + // Test vector 6 and expected output from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-152.md#test-vector-6 + let input = hex!("0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000"); + let expected = hex!("75ab69d3190a562c51aef8d88f1c2775876944407270c42c9844252c26d2875298743e7f6d5ea2f2d3e8d226039cd31b4e426ac4f2d3d666a610c2116fde4735"); + let mut out = [0u8; 64]; + blake2.execute(&input[..], &mut BytesRef::Fixed(&mut out[..])).unwrap(); + assert_eq!(&out[..], &expected[..]); + } + + #[test] + fn blake2_f_test_vector_7() { + let blake2 = ethereum_builtin("blake2_f"); + // Test vector 7 and expected output from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-152.md#test-vector-7 + let input = hex!("0000000148c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001"); + let expected = hex!("b63a380cb2897d521994a85234ee2c181b5f844d2c624c002677e9703449d2fba551b3a8333bcdf5f2f7e08993d53923de3d64fcc68c034e717b9293fed7a421"); + let mut out = [0u8; 64]; + blake2.execute(&input[..], &mut BytesRef::Fixed(&mut out[..])).unwrap(); + assert_eq!(&out[..], &expected[..]); + } + + #[ignore] + #[test] + fn blake2_f_test_vector_8() { + let blake2 = ethereum_builtin("blake2_f"); + // Test vector 8 and expected output from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-152.md#test-vector-8 + // Note this test is slow, 4294967295/0xffffffff rounds take a while. + let input = hex!("ffffffff48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001"); + let expected = hex!("fc59093aafa9ab43daae0e914c57635c5402d8e3d2130eb9b3cc181de7f0ecf9b22bf99a7815ce16419e200e01846e6b5df8cc7703041bbceb571de6631d2615"); + let mut out = [0u8; 64]; + blake2.execute(&input[..], &mut BytesRef::Fixed(&mut out[..])).unwrap(); + assert_eq!(&out[..], &expected[..]); + } #[test] fn modexp_func() { @@ -626,19 +870,19 @@ mod tests { let mut o = [255u8; 32]; f.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); - assert_eq!(&o[..], &(FromHex::from_hex("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855").unwrap())[..]); + assert_eq!(&o[..], hex!("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")); let mut o8 = [255u8; 8]; f.execute(&i[..], &mut BytesRef::Fixed(&mut o8[..])).expect("Builtin should not fail"); - assert_eq!(&o8[..], &(FromHex::from_hex("e3b0c44298fc1c14").unwrap())[..]); + assert_eq!(&o8[..], hex!("e3b0c44298fc1c14")); let mut o34 = [255u8; 34]; f.execute(&i[..], &mut BytesRef::Fixed(&mut o34[..])).expect("Builtin should not fail"); - assert_eq!(&o34[..], &(FromHex::from_hex("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855ffff").unwrap())[..]); + assert_eq!(&o34[..], &hex!("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855ffff")[..]); let mut ov = vec![]; f.execute(&i[..], &mut BytesRef::Flexible(&mut ov)).expect("Builtin should not fail"); - assert_eq!(&ov[..], &(FromHex::from_hex("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855").unwrap())[..]); + assert_eq!(&ov[..], &hex!("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")[..]); } #[test] @@ -649,59 +893,59 @@ mod tests { let mut o = [255u8; 32]; f.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); - assert_eq!(&o[..], &(FromHex::from_hex("0000000000000000000000009c1185a5c5e9fc54612808977ee8f548b2258d31").unwrap())[..]); + assert_eq!(&o[..], &hex!("0000000000000000000000009c1185a5c5e9fc54612808977ee8f548b2258d31")[..]); let mut o8 = [255u8; 8]; f.execute(&i[..], &mut BytesRef::Fixed(&mut o8[..])).expect("Builtin should not fail"); - assert_eq!(&o8[..], &(FromHex::from_hex("0000000000000000").unwrap())[..]); + assert_eq!(&o8[..], &hex!("0000000000000000")[..]); let mut o34 = [255u8; 34]; f.execute(&i[..], &mut BytesRef::Fixed(&mut o34[..])).expect("Builtin should not fail"); - assert_eq!(&o34[..], &(FromHex::from_hex("0000000000000000000000009c1185a5c5e9fc54612808977ee8f548b2258d31ffff").unwrap())[..]); + assert_eq!(&o34[..], &hex!("0000000000000000000000009c1185a5c5e9fc54612808977ee8f548b2258d31ffff")[..]); } #[test] fn ecrecover() { let f = ethereum_builtin("ecrecover"); - let i = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap(); + let i = hex!("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03"); let mut o = [255u8; 32]; f.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); - assert_eq!(&o[..], &(FromHex::from_hex("000000000000000000000000c08b5542d177ac6686946920409741463a15dddb").unwrap())[..]); + assert_eq!(&o[..], &hex!("000000000000000000000000c08b5542d177ac6686946920409741463a15dddb")[..]); let mut o8 = [255u8; 8]; f.execute(&i[..], &mut BytesRef::Fixed(&mut o8[..])).expect("Builtin should not fail"); - assert_eq!(&o8[..], &(FromHex::from_hex("0000000000000000").unwrap())[..]); + assert_eq!(&o8[..], &hex!("0000000000000000")[..]); let mut o34 = [255u8; 34]; f.execute(&i[..], &mut BytesRef::Fixed(&mut o34[..])).expect("Builtin should not fail"); - assert_eq!(&o34[..], &(FromHex::from_hex("000000000000000000000000c08b5542d177ac6686946920409741463a15dddbffff").unwrap())[..]); + assert_eq!(&o34[..], &hex!("000000000000000000000000c08b5542d177ac6686946920409741463a15dddbffff")[..]); - let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001a650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap(); + let i_bad = hex!("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001a650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03"); let mut o = [255u8; 32]; f.execute(&i_bad[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); - assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); + assert_eq!(&o[..], &hex!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[..]); - let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b0000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let i_bad = hex!("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b0000000000000000000000000000000000000000000000000000000000000000"); let mut o = [255u8; 32]; f.execute(&i_bad[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); - assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); + assert_eq!(&o[..], &hex!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[..]); - let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b").unwrap(); + let i_bad = hex!("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b"); let mut o = [255u8; 32]; f.execute(&i_bad[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); - assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); + assert_eq!(&o[..], &hex!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[..]); - let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000001b").unwrap(); + let i_bad = hex!("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000001b"); let mut o = [255u8; 32]; f.execute(&i_bad[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); - assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); + assert_eq!(&o[..], &hex!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[..]); - let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(); + let i_bad = hex!("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); let mut o = [255u8; 32]; f.execute(&i_bad[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); - assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); + assert_eq!(&o[..], &hex!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[..]); // TODO: Should this (corrupted version of the above) fail rather than returning some address? /* let i_bad = FromHex::from_hex("48173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap(); @@ -721,103 +965,103 @@ mod tests { // test for potential gas cost multiplication overflow { - let input = FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000003b27bafd00000000000000000000000000000000000000000000000000000000503c8ac3").unwrap(); + let input = hex!("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000003b27bafd00000000000000000000000000000000000000000000000000000000503c8ac3"); let expected_cost = U256::max_value(); - assert_eq!(f.cost(&input[..]), expected_cost.into()); + assert_eq!(f.cost(&input[..], 0), expected_cost.into()); } // test for potential exp len overflow { - let input = FromHex::from_hex("\ - 00000000000000000000000000000000000000000000000000000000000000ff\ - 2a1e530000000000000000000000000000000000000000000000000000000000\ + let input = hex!(" + 00000000000000000000000000000000000000000000000000000000000000ff + 2a1e530000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000" - ).unwrap(); + ); let mut output = vec![0u8; 32]; - let expected = FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let expected = hex!("0000000000000000000000000000000000000000000000000000000000000000"); let expected_cost = U256::max_value(); f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should fail"); assert_eq!(output, expected); - assert_eq!(f.cost(&input[..]), expected_cost.into()); + assert_eq!(f.cost(&input[..], 0), expected_cost.into()); } // fermat's little theorem example. { - let input = FromHex::from_hex("\ - 0000000000000000000000000000000000000000000000000000000000000001\ - 0000000000000000000000000000000000000000000000000000000000000020\ - 0000000000000000000000000000000000000000000000000000000000000020\ - 03\ - fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e\ + let input = hex!(" + 0000000000000000000000000000000000000000000000000000000000000001 + 0000000000000000000000000000000000000000000000000000000000000020 + 0000000000000000000000000000000000000000000000000000000000000020 + 03 + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" - ).unwrap(); + ); let mut output = vec![0u8; 32]; - let expected = FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000001").unwrap(); + let expected = hex!("0000000000000000000000000000000000000000000000000000000000000001"); let expected_cost = 13056; f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); assert_eq!(output, expected); - assert_eq!(f.cost(&input[..]), expected_cost.into()); + assert_eq!(f.cost(&input[..], 0), expected_cost.into()); } // second example from EIP: zero base. { - let input = FromHex::from_hex("\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000020\ - 0000000000000000000000000000000000000000000000000000000000000020\ - fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e\ + let input = hex!(" + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000020 + 0000000000000000000000000000000000000000000000000000000000000020 + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" - ).unwrap(); + ); let mut output = vec![0u8; 32]; - let expected = FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let expected = hex!("0000000000000000000000000000000000000000000000000000000000000000"); let expected_cost = 13056; f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); assert_eq!(output, expected); - assert_eq!(f.cost(&input[..]), expected_cost.into()); + assert_eq!(f.cost(&input[..], 0), expected_cost.into()); } // another example from EIP: zero-padding { - let input = FromHex::from_hex("\ - 0000000000000000000000000000000000000000000000000000000000000001\ - 0000000000000000000000000000000000000000000000000000000000000002\ - 0000000000000000000000000000000000000000000000000000000000000020\ - 03\ - ffff\ + let input = hex!(" + 0000000000000000000000000000000000000000000000000000000000000001 + 0000000000000000000000000000000000000000000000000000000000000002 + 0000000000000000000000000000000000000000000000000000000000000020 + 03 + ffff 80" - ).unwrap(); + ); let mut output = vec![0u8; 32]; - let expected = FromHex::from_hex("3b01b01ac41f2d6e917c6d6a221ce793802469026d9ab7578fa2e79e4da6aaab").unwrap(); + let expected = hex!("3b01b01ac41f2d6e917c6d6a221ce793802469026d9ab7578fa2e79e4da6aaab"); let expected_cost = 768; f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); assert_eq!(output, expected); - assert_eq!(f.cost(&input[..]), expected_cost.into()); + assert_eq!(f.cost(&input[..], 0), expected_cost.into()); } // zero-length modulus. { - let input = FromHex::from_hex("\ - 0000000000000000000000000000000000000000000000000000000000000001\ - 0000000000000000000000000000000000000000000000000000000000000002\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 03\ + let input = hex!(" + 0000000000000000000000000000000000000000000000000000000000000001 + 0000000000000000000000000000000000000000000000000000000000000002 + 0000000000000000000000000000000000000000000000000000000000000000 + 03 ffff" - ).unwrap(); + ); let mut output = vec![]; let expected_cost = 0; f.execute(&input[..], &mut BytesRef::Flexible(&mut output)).expect("Builtin should not fail"); assert_eq!(output.len(), 0); // shouldn't have written any output. - assert_eq!(f.cost(&input[..]), expected_cost.into()); + assert_eq!(f.cost(&input[..], 0), expected_cost.into()); } } @@ -832,21 +1076,21 @@ mod tests { // zero-points additions { - let input = FromHex::from_hex("\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ + let input = hex!(" + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000" - ).unwrap(); + ); let mut output = vec![0u8; 64]; - let expected = FromHex::from_hex("\ - 0000000000000000000000000000000000000000000000000000000000000000\ + let expected = hex!(" + 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000" - ).unwrap(); + ); f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); - assert_eq!(output, expected); + assert_eq!(output, &expected[..]); } // no input, should not fail @@ -855,23 +1099,23 @@ mod tests { let input = BytesRef::Fixed(&mut empty); let mut output = vec![0u8; 64]; - let expected = FromHex::from_hex("\ - 0000000000000000000000000000000000000000000000000000000000000000\ + let expected = hex!(" + 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000" - ).unwrap(); + ); f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); - assert_eq!(output, expected); + assert_eq!(output, &expected[..]); } // should fail - point not on curve { - let input = FromHex::from_hex("\ - 1111111111111111111111111111111111111111111111111111111111111111\ - 1111111111111111111111111111111111111111111111111111111111111111\ - 1111111111111111111111111111111111111111111111111111111111111111\ + let input = hex!(" + 1111111111111111111111111111111111111111111111111111111111111111 + 1111111111111111111111111111111111111111111111111111111111111111 + 1111111111111111111111111111111111111111111111111111111111111111 1111111111111111111111111111111111111111111111111111111111111111" - ).unwrap(); + ); let mut output = vec![0u8; 64]; @@ -891,29 +1135,29 @@ mod tests { // zero-point multiplication { - let input = FromHex::from_hex("\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ + let input = hex!(" + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 0200000000000000000000000000000000000000000000000000000000000000" - ).unwrap(); + ); let mut output = vec![0u8; 64]; - let expected = FromHex::from_hex("\ - 0000000000000000000000000000000000000000000000000000000000000000\ + let expected = hex!(" + 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000" - ).unwrap(); + ); f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); - assert_eq!(output, expected); + assert_eq!(output, &expected[..]); } // should fail - point not on curve { - let input = FromHex::from_hex("\ - 1111111111111111111111111111111111111111111111111111111111111111\ - 1111111111111111111111111111111111111111111111111111111111111111\ + let input = hex!(" + 1111111111111111111111111111111111111111111111111111111111111111 + 1111111111111111111111111111111111111111111111111111111111111111 0f00000000000000000000000000000000000000000000000000000000000000" - ).unwrap(); + ); let mut output = vec![0u8; 64]; @@ -954,16 +1198,12 @@ mod tests { } } - fn bytes(s: &'static str) -> Vec { - FromHex::from_hex(s).expect("static str should contain valid hex bytes") - } - #[test] fn bn128_pairing_empty() { // should not fail, because empty input is a valid input of 0 elements empty_test( builtin_pairing(), - bytes("0000000000000000000000000000000000000000000000000000000000000001"), + hex!("0000000000000000000000000000000000000000000000000000000000000001").to_vec(), ); } @@ -972,12 +1212,12 @@ mod tests { // should fail - point not on curve error_test( builtin_pairing(), - &bytes("\ - 1111111111111111111111111111111111111111111111111111111111111111\ - 1111111111111111111111111111111111111111111111111111111111111111\ - 1111111111111111111111111111111111111111111111111111111111111111\ - 1111111111111111111111111111111111111111111111111111111111111111\ - 1111111111111111111111111111111111111111111111111111111111111111\ + &hex!(" + 1111111111111111111111111111111111111111111111111111111111111111 + 1111111111111111111111111111111111111111111111111111111111111111 + 1111111111111111111111111111111111111111111111111111111111111111 + 1111111111111111111111111111111111111111111111111111111111111111 + 1111111111111111111111111111111111111111111111111111111111111111 1111111111111111111111111111111111111111111111111111111111111111" ), Some("not on curve"), @@ -989,9 +1229,9 @@ mod tests { // should fail - input length is invalid error_test( builtin_pairing(), - &bytes("\ - 1111111111111111111111111111111111111111111111111111111111111111\ - 1111111111111111111111111111111111111111111111111111111111111111\ + &hex!(" + 1111111111111111111111111111111111111111111111111111111111111111 + 1111111111111111111111111111111111111111111111111111111111111111 111111111111111111111111111111" ), Some("Invalid input length"), @@ -1008,7 +1248,7 @@ mod tests { fn is_active() { let pricer = Box::new(Linear { base: 10, word: 20} ); let b = Builtin { - pricer: pricer as Box, + pricer: pricer as Box, native: ethereum_builtin("identity"), activate_at: 100_000, }; @@ -1022,15 +1262,15 @@ mod tests { fn from_named_linear() { let pricer = Box::new(Linear { base: 10, word: 20 }); let b = Builtin { - pricer: pricer as Box, + pricer: pricer as Box, native: ethereum_builtin("identity"), activate_at: 1, }; - assert_eq!(b.cost(&[0; 0]), U256::from(10)); - assert_eq!(b.cost(&[0; 1]), U256::from(30)); - assert_eq!(b.cost(&[0; 32]), U256::from(30)); - assert_eq!(b.cost(&[0; 33]), U256::from(50)); + assert_eq!(b.cost(&[0; 0], 0), U256::from(10)); + assert_eq!(b.cost(&[0; 1], 0), U256::from(30)); + assert_eq!(b.cost(&[0; 32], 0), U256::from(30)); + assert_eq!(b.cost(&[0; 33], 0), U256::from(50)); let i = [0u8, 1, 2, 3]; let mut o = [255u8; 4]; @@ -1047,16 +1287,67 @@ mod tests { word: 20, }), activate_at: None, + eip1108_transition: None, }); - assert_eq!(b.cost(&[0; 0]), U256::from(10)); - assert_eq!(b.cost(&[0; 1]), U256::from(30)); - assert_eq!(b.cost(&[0; 32]), U256::from(30)); - assert_eq!(b.cost(&[0; 33]), U256::from(50)); + assert_eq!(b.cost(&[0; 0], 0), U256::from(10)); + assert_eq!(b.cost(&[0; 1], 0), U256::from(30)); + assert_eq!(b.cost(&[0; 32], 0), U256::from(30)); + assert_eq!(b.cost(&[0; 33], 0), U256::from(50)); let i = [0u8, 1, 2, 3]; let mut o = [255u8; 4]; b.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); assert_eq!(i, o); } + + #[test] + fn bn128_pairing_eip1108_transition() { + let b = Builtin::from(ethjson::spec::Builtin { + name: "alt_bn128_pairing".to_owned(), + pricing: ethjson::spec::Pricing::AltBn128Pairing(ethjson::spec::builtin::AltBn128Pairing { + base: 100_000, + pair: 80_000, + eip1108_transition_base: 45_000, + eip1108_transition_pair: 34_000, + }), + activate_at: Some(Uint(U256::from(10))), + eip1108_transition: Some(Uint(U256::from(20))), + }); + + assert_eq!(b.cost(&[0; 192 * 3], 10), U256::from(340_000), "80 000 * 3 + 100 000 == 340 000"); + assert_eq!(b.cost(&[0; 192 * 7], 20), U256::from(283_000), "34 000 * 7 + 45 000 == 283 000"); + } + + #[test] + fn bn128_add_eip1108_transition() { + let b = Builtin::from(ethjson::spec::Builtin { + name: "alt_bn128_add".to_owned(), + pricing: ethjson::spec::Pricing::AltBn128ConstOperations(ethjson::spec::builtin::AltBn128ConstOperations { + price: 500, + eip1108_transition_price: 150, + }), + activate_at: Some(Uint(U256::from(10))), + eip1108_transition: Some(Uint(U256::from(20))), + }); + + assert_eq!(b.cost(&[0; 192], 10), U256::from(500)); + assert_eq!(b.cost(&[0; 10], 20), U256::from(150), "after istanbul hardfork gas cost for add should be 150"); + } + + #[test] + fn bn128_mul_eip1108_transition() { + let b = Builtin::from(ethjson::spec::Builtin { + name: "alt_bn128_mul".to_owned(), + pricing: ethjson::spec::Pricing::AltBn128ConstOperations(ethjson::spec::builtin::AltBn128ConstOperations { + price: 40_000, + eip1108_transition_price: 6000, + }), + activate_at: Some(Uint(U256::from(10))), + eip1108_transition: Some(Uint(U256::from(20))), + }); + + assert_eq!(b.cost(&[0; 192], 10), U256::from(40_000)); + assert_eq!(b.cost(&[0; 10], 20), U256::from(6_000), "after istanbul hardfork gas cost for mul should be 6 000"); + } } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index bcac9bbad3..12372b83ee 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -21,11 +21,11 @@ use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; use std::sync::{Arc, Weak}; use std::time::{Instant, Duration}; -use blockchain::{BlockReceipts, BlockChain, BlockChainDB, BlockProvider, TreeRoute, ImportRoute, TransactionAddress, ExtrasInsert}; +use blockchain::{BlockReceipts, BlockChain, BlockChainDB, BlockProvider, TreeRoute, ImportRoute, TransactionAddress, ExtrasInsert, BlockNumberKey}; use bytes::Bytes; use call_contract::{CallContract, RegistryInfo}; use ethcore_miner::pool::VerifiedTransaction; -use ethereum_types::{H256, Address, U256}; +use ethereum_types::{H256, H264, Address, U256}; use evm::Schedule; use hash::keccak; use io::IoChannel; @@ -44,14 +44,14 @@ use types::receipt::{Receipt, LocalizedReceipt}; use types::{BlockNumber, header::{Header, ExtendedHeader}}; use vm::{EnvInfo, LastHashes}; -use block::{IsBlock, LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock}; +use block::{LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock}; use client::ancient_import::AncientVerifier; use client::{ Nonce, Balance, ChainInfo, BlockInfo, TransactionInfo, ReopenBlock, PrepareOpenBlock, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock, StateOrBlock, StateInfo, StateClient, Call, AccountData, BlockChain as BlockChainTrait, BlockProducer, SealedBlockImporter, - ClientIoMessage, + ClientIoMessage, BlockChainReset }; use client::{ BlockId, TransactionId, UncleId, TraceId, ClientConfig, BlockChainClient, @@ -60,7 +60,7 @@ use client::{ IoClient, BadBlocks, }; use client::bad_blocks; -use engines::{EthEngine, EpochTransition, ForkChoice, EngineError}; +use engines::{MAX_UNCLE_AGE, EthEngine, EpochTransition, ForkChoice, EngineError}; use engines::epoch::PendingTransition; use error::{ ImportErrorKind, ExecutionError, CallError, BlockError, @@ -79,12 +79,14 @@ use verification::queue::kind::BlockLike; use verification::queue::kind::blocks::Unverified; use verification::{PreverifiedBlock, Verifier, BlockQueue}; use verification; +use ansi_term::Colour; // re-export pub use types::blockchain_info::BlockChainInfo; pub use types::block_status::BlockStatus; pub use blockchain::CacheSize as BlockChainCacheSize; pub use verification::QueueInfo as BlockQueueInfo; +use db::{Writable, Readable, keys::BlockDetails}; use_contract!(registry, "res/contracts/registrar.json"); @@ -295,19 +297,11 @@ impl Importer { match self.check_and_lock_block(&bytes, block, client) { Ok((closed_block, pending)) => { - if self.engine.is_proposal(&header) { - self.block_queue.mark_as_good(&[hash]); - proposed_blocks.push(bytes); - } else { - imported_blocks.push(hash); - - let transactions_len = closed_block.transactions().len(); - - let route = self.commit_block(closed_block, &header, encoded::Block::new(bytes), pending, client); - import_results.push(route); - - client.report.write().accrue_block(&header, transactions_len); - } + imported_blocks.push(hash); + let transactions_len = closed_block.transactions.len(); + let route = self.commit_block(closed_block, &header, encoded::Block::new(bytes), pending, client); + import_results.push(route); + client.report.write().accrue_block(&header, transactions_len); }, Err(err) => { self.bad_blocks.report(bytes, format!("{:?}", err)); @@ -404,6 +398,7 @@ impl Importer { let db = client.state_db.read().boxed_clone_canon(header.parent_hash()); let is_epoch_begin = chain.epoch_transition(parent.number(), *header.parent_hash()).is_some(); + let enact_result = enact_verified( block, engine, @@ -428,13 +423,13 @@ impl Importer { // if the expected receipts root header does not match. // (i.e. allow inconsistency in receipts outcome before the transition block) if header.number() < engine.params().validate_receipts_transition - && header.receipts_root() != locked_block.block().header().receipts_root() + && header.receipts_root() != locked_block.header.receipts_root() { locked_block.strip_receipts_outcomes(); } // Final Verification - if let Err(e) = self.verifier.verify_block_final(&header, locked_block.block().header()) { + if let Err(e) = self.verifier.verify_block_final(&header, &locked_block.header) { warn!(target: "client", "Stage 5 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); bail!(e); } @@ -442,8 +437,8 @@ impl Importer { let pending = self.check_epoch_end_signal( &header, bytes, - locked_block.receipts(), - locked_block.state().db(), + &locked_block.receipts, + locked_block.state.db(), client )?; @@ -621,7 +616,7 @@ impl Importer { let call = move |addr, data| { let mut state_db = state_db.boxed_clone(); - let backend = ::state::backend::Proving::new(state_db.as_hashdb_mut()); + let backend = ::state::backend::Proving::new(state_db.as_hash_db_mut()); let transaction = client.contract_call_tx(BlockId::Hash(*header.parent_hash()), addr, data); @@ -769,8 +764,8 @@ impl Client { liveness: AtomicBool::new(awake), mode: Mutex::new(config.mode.clone()), chain: RwLock::new(chain), - tracedb: tracedb, - engine: engine, + tracedb, + engine, pruning: config.pruning.clone(), db: RwLock::new(db.clone()), state_db: RwLock::new(state_db), @@ -783,8 +778,8 @@ impl Client { ancient_blocks_import_lock: Default::default(), queue_consensus_message: IoChannelQueue::new(usize::max_value()), last_hashes: RwLock::new(VecDeque::new()), - factories: factories, - history: history, + factories, + history, on_user_defaults_change: Mutex::new(None), registrar_address, exit_handler: Mutex::new(None), @@ -1114,7 +1109,7 @@ impl Client { let mut ss = self.sleep_state.lock(); if let Some(t) = ss.last_activity { if Instant::now() > t + timeout { - self.sleep(); + self.sleep(false); ss.last_activity = None; } } @@ -1124,7 +1119,7 @@ impl Client { let now = Instant::now(); if let Some(t) = ss.last_activity { if now > t + timeout { - self.sleep(); + self.sleep(false); ss.last_activity = None; ss.last_autosleep = Some(now); } @@ -1143,10 +1138,15 @@ impl Client { /// Take a snapshot at the given block. /// If the ID given is "latest", this will default to 1000 blocks behind. - pub fn take_snapshot(&self, writer: W, at: BlockId, p: &snapshot::Progress) -> Result<(), EthcoreError> { + pub fn take_snapshot( + &self, + writer: W, + at: BlockId, + p: &snapshot::Progress, + ) -> Result<(), EthcoreError> { let db = self.state_db.read().journal_db().boxed_clone(); let best_block_number = self.chain_info().best_block_number; - let block_number = self.block_number(at).ok_or(snapshot::Error::InvalidStartingBlock(at))?; + let block_number = self.block_number(at).ok_or_else(|| snapshot::Error::InvalidStartingBlock(at))?; if db.is_pruned() && self.pruning_info().earliest_state > block_number { return Err(snapshot::Error::OldBlockPrunedDB.into()); @@ -1173,8 +1173,16 @@ impl Client { }; let processing_threads = self.config.snapshot.processing_threads; - snapshot::take_snapshot(&*self.engine, &self.chain.read(), start_hash, db.as_hashdb(), writer, p, processing_threads)?; - + let chunker = self.engine.snapshot_components().ok_or(snapshot::Error::SnapshotsUnsupported)?; + snapshot::take_snapshot( + chunker, + &self.chain.read(), + start_hash, + db.as_hash_db(), + writer, + p, + processing_threads, + )?; Ok(()) } @@ -1210,10 +1218,10 @@ impl Client { } } - fn sleep(&self) { + fn sleep(&self, force: bool) { if self.liveness.load(AtomicOrdering::Relaxed) { // only sleep if the import queue is mostly empty. - if self.queue_info().total_queue_size() <= MAX_QUEUE_SIZE_TO_SLEEP_ON { + if force || (self.queue_info().total_queue_size() <= MAX_QUEUE_SIZE_TO_SLEEP_ON) { self.liveness.store(false, AtomicOrdering::Relaxed); self.notify(|n| n.stop()); info!(target: "mode", "sleep: Sleeping."); @@ -1328,6 +1336,71 @@ impl snapshot::DatabaseRestore for Client { } } +impl BlockChainReset for Client { + fn reset(&self, num: u32) -> Result<(), String> { + if num as u64 > self.pruning_history() { + return Err("Attempting to reset to block with pruned state".into()) + } else if num == 0 { + return Err("invalid number of blocks to reset".into()) + } + + let mut blocks_to_delete = Vec::with_capacity(num as usize); + let mut best_block_hash = self.chain.read().best_block_hash(); + let mut batch = DBTransaction::with_capacity(blocks_to_delete.len()); + + for _ in 0..num { + let current_header = self.chain.read().block_header_data(&best_block_hash) + .expect("best_block_hash was fetched from db; block_header_data should exist in db; qed"); + best_block_hash = current_header.parent_hash(); + + let (number, hash) = (current_header.number(), current_header.hash()); + batch.delete(::db::COL_HEADERS, &hash); + batch.delete(::db::COL_BODIES, &hash); + Writable::delete:: + (&mut batch, ::db::COL_EXTRA, &hash); + Writable::delete:: + (&mut batch, ::db::COL_EXTRA, &number); + + blocks_to_delete.push((number, hash)); + } + + let hashes = blocks_to_delete.iter().map(|(_, hash)| hash).collect::>(); + info!("Deleting block hashes {}", + Colour::Red + .bold() + .paint(format!("{:#?}", hashes)) + ); + + let mut best_block_details = Readable::read::( + &**self.db.read().key_value(), + ::db::COL_EXTRA, + &best_block_hash + ).expect("block was previously imported; best_block_details should exist; qed"); + + let (_, last_hash) = blocks_to_delete.last() + .expect("num is > 0; blocks_to_delete can't be empty; qed"); + // remove the last block as a child so that it can be re-imported + // ethcore/blockchain/src/blockchain.rs/Blockchain::is_known_child() + best_block_details.children.retain(|h| *h != *last_hash); + batch.write( + ::db::COL_EXTRA, + &best_block_hash, + &best_block_details + ); + // update the new best block hash + batch.put(::db::COL_EXTRA, b"best", &best_block_hash); + + self.db.read() + .key_value() + .write(batch) + .map_err(|err| format!("could not delete blocks; io error occurred: {}", err))?; + + info!("New best block hash {}", Colour::Green.bold().paint(format!("{:?}", best_block_hash))); + + Ok(()) + } +} + impl Nonce for Client { fn nonce(&self, address: &Address, id: BlockId) -> Option { self.state_at(id).and_then(|s| s.nonce(address).ok()) @@ -1533,22 +1606,27 @@ impl Call for Client { let schedule = machine.schedule(env_info.number); Executive::new(&mut clone, &env_info, &machine, &schedule) .transact_virtual(&tx, options()) - .ok() - .map(|r| r.exception.is_none()) }; - let cond = |gas| exec(gas).unwrap_or(false); + let cond = |gas| { + exec(gas) + .ok() + .map_or(false, |r| r.exception.is_none()) + }; if !cond(upper) { upper = max_upper; match exec(upper) { - Some(false) => return Err(CallError::Exceptional), - None => { + Ok(v) => { + if let Some(exception) = v.exception { + return Err(CallError::Exceptional(exception)) + } + }, + Err(_e) => { trace!(target: "estimate_gas", "estimate_gas failed with {}", upper); let err = ExecutionError::Internal(format!("Requires higher than upper limit of {}", upper)); return Err(err.into()) - }, - _ => {}, + } } } let lower = t.gas_required(&self.engine.schedule(env_info.number)).into(); @@ -1652,7 +1730,7 @@ impl BlockChainClient for Client { } match new_mode { Mode::Active => self.wake_up(), - Mode::Off => self.sleep(), + Mode::Off => self.sleep(true), _ => {(*self.sleep_state.lock()).last_activity = Some(Instant::now()); } } } @@ -1661,15 +1739,17 @@ impl BlockChainClient for Client { self.config.spec_name.clone() } - fn set_spec_name(&self, new_spec_name: String) { + fn set_spec_name(&self, new_spec_name: String) -> Result<(), ()> { trace!(target: "mode", "Client::set_spec_name({:?})", new_spec_name); if !self.enabled.load(AtomicOrdering::Relaxed) { - return; + return Err(()); } if let Some(ref h) = *self.exit_handler.lock() { (*h)(new_spec_name); + Ok(()) } else { warn!("Not hypervised; cannot change chain."); + Err(()) } } @@ -1736,7 +1816,8 @@ impl BlockChainClient for Client { }; let (root, db) = state.drop(); - let trie = match self.factories.trie.readonly(db.as_hashdb(), &root) { + let db = &db.as_hash_db(); + let trie = match self.factories.trie.readonly(db, &root) { Ok(trie) => trie, _ => { trace!(target: "fatdb", "list_accounts: Couldn't open the DB"); @@ -1782,8 +1863,9 @@ impl BlockChainClient for Client { }; let (_, db) = state.drop(); - let account_db = self.factories.accountdb.readonly(db.as_hashdb(), keccak(account)); - let trie = match self.factories.trie.readonly(account_db.as_hashdb(), &root) { + let account_db = &self.factories.accountdb.readonly(db.as_hash_db(), keccak(account)); + let account_db = &account_db.as_hash_db(); + let trie = match self.factories.trie.readonly(account_db, &root) { Ok(trie) => trie, _ => { trace!(target: "fatdb", "list_storage: Couldn't open the DB"); @@ -1877,7 +1959,7 @@ impl BlockChainClient for Client { } fn find_uncles(&self, hash: &H256) -> Option> { - self.chain.read().find_uncle_hashes(hash, self.engine.maximum_uncle_age()) + self.chain.read().find_uncle_hashes(hash, MAX_UNCLE_AGE) } fn state_data(&self, hash: &H256) -> Option { @@ -2110,11 +2192,20 @@ impl BlockChainClient for Client { fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error> { let authoring_params = self.importer.miner.authoring_params(); + let service_transaction_checker = self.importer.miner.service_transaction_checker(); + let gas_price = if let Some(checker) = service_transaction_checker { + match checker.check_address(self, authoring_params.author) { + Ok(true) => U256::zero(), + _ => self.importer.miner.sensible_gas_price(), + } + } else { + self.importer.miner.sensible_gas_price() + }; let transaction = transaction::Transaction { nonce: self.latest_nonce(&authoring_params.author), action: Action::Call(address), gas: self.importer.miner.sensible_gas_limit(), - gas_price: self.importer.miner.sensible_gas_price(), + gas_price, value: U256::zero(), data: data, }; @@ -2230,24 +2321,24 @@ impl ReopenBlock for Client { fn reopen_block(&self, block: ClosedBlock) -> OpenBlock { let engine = &*self.engine; let mut block = block.reopen(engine); - let max_uncles = engine.maximum_uncle_count(block.header().number()); - if block.uncles().len() < max_uncles { + let max_uncles = engine.maximum_uncle_count(block.header.number()); + if block.uncles.len() < max_uncles { let chain = self.chain.read(); let h = chain.best_block_hash(); // Add new uncles let uncles = chain - .find_uncle_hashes(&h, engine.maximum_uncle_age()) + .find_uncle_hashes(&h, MAX_UNCLE_AGE) .unwrap_or_else(Vec::new); for h in uncles { - if !block.uncles().iter().any(|header| header.hash() == h) { + if !block.uncles.iter().any(|header| header.hash() == h) { let uncle = chain.block_header_data(&h).expect("find_uncle_hashes only returns hashes for existing headers; qed"); let uncle = uncle.decode().expect("decoding failure"); block.push_uncle(uncle).expect("pushing up to maximum_uncle_count; push_uncle is not ok only if more than maximum_uncle_count is pushed; so all push_uncle are Ok; qed"); - if block.uncles().len() >= max_uncles { break } + if block.uncles.len() >= max_uncles { break } } } @@ -2275,15 +2366,15 @@ impl PrepareOpenBlock for Client { gas_range_target, extra_data, is_epoch_begin, - &mut chain.ancestry_with_metadata_iter(best_header.hash()), + chain.ancestry_with_metadata_iter(best_header.hash()), )?; // Add uncles chain - .find_uncle_headers(&h, engine.maximum_uncle_age()) + .find_uncle_headers(&h, MAX_UNCLE_AGE) .unwrap_or_else(Vec::new) .into_iter() - .take(engine.maximum_uncle_count(open_block.header().number())) + .take(engine.maximum_uncle_count(open_block.header.number())) .foreach(|h| { open_block.push_uncle(h.decode().expect("decoding failure")).expect("pushing maximum_uncle_count; open_block was just created; @@ -2308,7 +2399,7 @@ impl ImportSealedBlock for Client { fn import_sealed_block(&self, block: SealedBlock) -> EthcoreResult { let start = Instant::now(); let raw = block.rlp_bytes(); - let header = block.header().clone(); + let header = block.header.clone(); let hash = header.hash(); self.notify(|n| n.block_pre_import(&raw, &hash, header.difficulty())); @@ -2331,8 +2422,8 @@ impl ImportSealedBlock for Client { let pending = self.importer.check_epoch_end_signal( &header, &block_data, - block.receipts(), - block.state().db(), + &block.receipts, + block.state.db(), self )?; let route = self.importer.commit_block( @@ -2449,7 +2540,7 @@ impl ProvingBlockChainClient for Client { let mut jdb = self.state_db.read().journal_db().boxed_clone(); state::prove_transaction_virtual( - jdb.as_hashdb_mut(), + jdb.as_hash_db_mut(), header.state_root().clone(), &transaction, self.engine.machine(), @@ -2469,7 +2560,11 @@ impl SnapshotClient for Client {} impl Drop for Client { fn drop(&mut self) { - self.engine.stop(); + if let Some(c) = Arc::get_mut(&mut self.engine) { + c.stop() + } else { + warn!(target: "shutdown", "unable to get mut ref for engine for shutdown."); + } } } diff --git a/ethcore/src/client/evm_test_client.rs b/ethcore/src/client/evm_test_client.rs index a65e2b313e..d65e20691e 100644 --- a/ethcore/src/client/evm_test_client.rs +++ b/ethcore/src/client/evm_test_client.rs @@ -94,6 +94,7 @@ impl<'a> EvmTestClient<'a> { ForkSpec::Byzantium => Some(ethereum::new_byzantium_test()), ForkSpec::Constantinople => Some(ethereum::new_constantinople_test()), ForkSpec::ConstantinopleFix => Some(ethereum::new_constantinople_fix_test()), + ForkSpec::Istanbul => Some(ethereum::new_istanbul_test()), ForkSpec::EIP158ToByzantiumAt5 => Some(ethereum::new_transition_test()), ForkSpec::FrontierToHomesteadAt5 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 => None, } @@ -241,16 +242,17 @@ impl<'a> EvmTestClient<'a> { transaction: transaction::SignedTransaction, tracer: T, vm_tracer: V, - ) -> TransactResult { + ) -> std::result::Result, TransactErr> { let initial_gas = transaction.gas; // Verify transaction let is_ok = transaction.verify_basic(true, None, false); if let Err(error) = is_ok { - return TransactResult::Err { - state_root: *self.state.root(), - error: error.into(), - end_state: (self.dump_state)(&self.state), - }; + return Err( + TransactErr{ + state_root: *self.state.root(), + error: error.into(), + end_state: (self.dump_state)(&self.state), + }); } // Apply transaction @@ -283,7 +285,7 @@ impl<'a> EvmTestClient<'a> { match result { Ok(result) => { - TransactResult::Ok { + Ok(TransactSuccess { state_root, gas_left: initial_gas - result.receipt.gas_used, outcome: result.receipt.outcome, @@ -298,47 +300,48 @@ impl<'a> EvmTestClient<'a> { }, end_state, } - }, - Err(error) => TransactResult::Err { + )}, + Err(error) => Err(TransactErr { state_root, error, end_state, - }, + }), } } } -/// A result of applying transaction to the state. -#[derive(Debug)] -pub enum TransactResult { - /// Successful execution - Ok { - /// State root - state_root: H256, - /// Amount of gas left - gas_left: U256, - /// Output - output: Vec, - /// Traces - trace: Vec, - /// VM Traces - vm_trace: Option, - /// Created contract address (if any) - contract_address: Option, - /// Generated logs - logs: Vec, - /// outcome - outcome: receipt::TransactionOutcome, - /// end state if needed - end_state: Option, - }, - /// Transaction failed to run - Err { - /// State root - state_root: H256, - /// Execution error - error: ::error::Error, - /// end state if needed - end_state: Option, - }, +/// To be returned inside a std::result::Result::Ok after a successful +/// transaction completed. +#[allow(dead_code)] +pub struct TransactSuccess { + /// State root + pub state_root: H256, + /// Amount of gas left + pub gas_left: U256, + /// Output + pub output: Vec, + /// Traces + pub trace: Vec, + /// VM Traces + pub vm_trace: Option, + /// Created contract address (if any) + pub contract_address: Option, + /// Generated logs + pub logs: Vec, + /// outcome + pub outcome: receipt::TransactionOutcome, + /// end state if needed + pub end_state: Option, +} + +/// To be returned inside a std::result::Result::Err after a failed +/// transaction. +#[allow(dead_code)] +pub struct TransactErr { + /// State root + pub state_root: H256, + /// Execution error + pub error: ::error::Error, + /// end state if needed + pub end_state: Option, } diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 7d9053ca60..d710a6b4dd 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -30,7 +30,7 @@ mod trace; pub use self::client::*; pub use self::config::{Mode, ClientConfig, DatabaseCompactionProfile, BlockChainConfig, VMType}; #[cfg(any(test, feature = "test-helpers"))] -pub use self::evm_test_client::{EvmTestClient, EvmTestError, TransactResult}; +pub use self::evm_test_client::{EvmTestClient, EvmTestError, TransactErr, TransactSuccess}; pub use self::io_message::ClientIoMessage; #[cfg(any(test, feature = "test-helpers"))] pub use self::test_client::{TestBlockChainClient, EachBlockWith}; @@ -38,6 +38,7 @@ pub use self::chain_notify::{ChainNotify, NewBlocks, ChainRoute, ChainRouteType, pub use self::traits::{ Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, PrepareOpenBlock, TransactionInfo, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock, StateOrBlock, StateClient, Call, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter, BadBlocks, + BlockChainReset }; pub use state::StateInfo; pub use self::traits::{BlockChainClient, EngineClient, ProvingBlockChainClient, IoClient}; @@ -53,7 +54,7 @@ pub use vm::{LastHashes, EnvInfo}; pub use error::TransactionImportError; pub use verification::VerifierType; -mod traits; +pub mod traits; mod chain_notify; mod private_notify; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 5236f7cd40..502a9ee72b 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -416,7 +416,7 @@ impl PrepareOpenBlock for TestBlockChainClient { gas_range_target, extra_data, false, - &mut Vec::new().into_iter(), + None, )?; // TODO [todr] Override timestamp for predictability open_block.set_timestamp(*self.latest_block_timestamp.read()); @@ -863,7 +863,7 @@ impl BlockChainClient for TestBlockChainClient { fn spec_name(&self) -> String { "foundation".into() } - fn set_spec_name(&self, _: String) { unimplemented!(); } + fn set_spec_name(&self, _: String) -> Result<(), ()> { unimplemented!(); } fn disable(&self) { self.disabled.store(true, AtomicOrder::Relaxed); } diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index b273bd3dcb..8e4abc01cd 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -360,7 +360,7 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra fn spec_name(&self) -> String; /// Set the chain via a spec name. - fn set_spec_name(&self, spec_name: String); + fn set_spec_name(&self, spec_name: String) -> Result<(), ()>; /// Disable the client from importing blocks. This cannot be undone in this session and indicates /// that a subsystem has reason to believe this executable incapable of syncing the chain. @@ -471,3 +471,9 @@ pub trait ProvingBlockChainClient: BlockChainClient { /// Get an epoch change signal by block hash. fn epoch_signal(&self, hash: H256) -> Option>; } + +/// resets the blockchain +pub trait BlockChainReset { + /// reset to best_block - n + fn reset(&self, num: u32) -> Result<(), String>; +} diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 1404e58fef..312b58e61c 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -22,9 +22,8 @@ use std::iter::FromIterator; use std::ops::Deref; use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; use std::sync::{Weak, Arc}; -use std::time::{UNIX_EPOCH, SystemTime, Duration}; +use std::time::{UNIX_EPOCH, Duration}; -use account_provider::AccountProvider; use block::*; use client::EngineClient; use engines::{Engine, Seal, EngineError, ConstructedVerifier}; @@ -37,12 +36,13 @@ use hash::keccak; use super::signer::EngineSigner; use super::validator_set::{ValidatorSet, SimpleList, new_validator_set}; use self::finality::RollingFinality; -use ethkey::{self, Password, Signature}; +use ethkey::{self, Signature}; use io::{IoContext, IoHandler, TimerToken, IoService}; use itertools::{self, Itertools}; use rlp::{encode, Decodable, DecoderError, Encodable, RlpStream, Rlp}; use ethereum_types::{H256, H520, Address, U128, U256}; use parking_lot::{Mutex, RwLock}; +use time_utils::CheckedSystemTime; use types::BlockNumber; use types::header::{Header, ExtendedHeader}; use types::ancestry_action::AncestryAction; @@ -412,7 +412,7 @@ pub struct AuthorityRound { transition_service: IoService<()>, step: Arc, client: Arc>>>, - signer: RwLock, + signer: RwLock>>, validators: Box, validate_score_transition: u64, validate_step_transition: u64, @@ -513,15 +513,19 @@ fn header_expected_seal_fields(header: &Header, empty_steps_transition: u64) -> } fn header_step(header: &Header, empty_steps_transition: u64) -> Result { - let expected_seal_fields = header_expected_seal_fields(header, empty_steps_transition); - Rlp::new(&header.seal().get(0).expect( - &format!("was either checked with verify_block_basic or is genesis; has {} fields; qed (Make sure the spec file has a correct genesis seal)", expected_seal_fields))).as_val() + Rlp::new(&header.seal().get(0).unwrap_or_else(|| + panic!("was either checked with verify_block_basic or is genesis; has {} fields; qed (Make sure the spec + file has a correct genesis seal)", header_expected_seal_fields(header, empty_steps_transition)) + )) + .as_val() } fn header_signature(header: &Header, empty_steps_transition: u64) -> Result { - let expected_seal_fields = header_expected_seal_fields(header, empty_steps_transition); - Rlp::new(&header.seal().get(1).expect( - &format!("was checked with verify_block_basic; has {} fields; qed", expected_seal_fields))).as_val::().map(Into::into) + Rlp::new(&header.seal().get(1).unwrap_or_else(|| + panic!("was checked with verify_block_basic; has {} fields; qed", + header_expected_seal_fields(header, empty_steps_transition)) + )) + .as_val::().map(Into::into) } // extracts the raw empty steps vec from the header seal. should only be called when there are 3 fields in the seal @@ -571,8 +575,15 @@ fn verify_timestamp(step: &Step, header_step: u64) -> Result<(), BlockError> { // NOTE This error might be returned only in early stage of verification (Stage 1). // Returning it further won't recover the sync process. trace!(target: "engine", "verify_timestamp: block too early"); - let oob = oob.map(|n| SystemTime::now() + Duration::from_secs(n)); - Err(BlockError::TemporarilyInvalid(oob).into()) + + let found = CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::from_secs(oob.found)) + .ok_or(BlockError::TimestampOverflow)?; + let max = oob.max.and_then(|m| CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::from_secs(m))); + let min = oob.min.and_then(|m| CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::from_secs(m))); + + let new_oob = OutOfBounds { min, max, found }; + + Err(BlockError::TemporarilyInvalid(new_oob).into()) }, Ok(_) => Ok(()), } @@ -608,6 +619,7 @@ fn combine_proofs(signal_number: BlockNumber, set_proof: &[u8], finality_proof: stream.out() } + fn destructure_proofs(combined: &[u8]) -> Result<(BlockNumber, &[u8], &[u8]), Error> { let rlp = Rlp::new(combined); Ok(( @@ -623,7 +635,7 @@ trait AsMillis { impl AsMillis for Duration { fn as_millis(&self) -> u64 { - self.as_secs()*1_000 + (self.subsec_nanos()/1_000_000) as u64 + self.as_secs() * 1_000 + (self.subsec_nanos() / 1_000_000) as u64 } } @@ -665,7 +677,7 @@ impl AuthorityRound { can_propose: AtomicBool::new(true), }), client: Arc::new(RwLock::new(None)), - signer: Default::default(), + signer: RwLock::new(None), validators: our_params.validators, validate_score_transition: our_params.validate_score_transition, validate_step_transition: our_params.validate_step_transition, @@ -788,7 +800,7 @@ impl AuthorityRound { return; } - if let (true, Some(me)) = (current_step > parent_step + 1, self.signer.read().address()) { + if let (true, Some(me)) = (current_step > parent_step + 1, self.signer.read().as_ref().map(|s| s.address())) { debug!(target: "engine", "Author {} built block with step gap. current step: {}, parent step: {}", header.author(), current_step, parent_step); let mut reported = HashSet::new(); @@ -935,8 +947,12 @@ impl Engine for AuthorityRound { return BTreeMap::default(); } - let step = header_step(header, self.empty_steps_transition).as_ref().map(ToString::to_string).unwrap_or("".into()); - let signature = header_signature(header, self.empty_steps_transition).as_ref().map(ToString::to_string).unwrap_or("".into()); + let step = header_step(header, self.empty_steps_transition).as_ref() + .map(ToString::to_string) + .unwrap_or_default(); + let signature = header_signature(header, self.empty_steps_transition).as_ref() + .map(ToString::to_string) + .unwrap_or_default(); let mut info = map![ "step".into() => step, @@ -1023,7 +1039,7 @@ impl Engine for AuthorityRound { return Seal::None; } - let header = block.header(); + let header = &block.header; let parent_step = header_step(parent, self.empty_steps_transition) .expect("Header has been verified; qed"); @@ -1069,7 +1085,7 @@ impl Engine for AuthorityRound { // `EmptyStep(step, parent_hash)` message. If we exceed the maximum amount of `empty_step` rounds we proceed // with the seal. if header.number() >= self.empty_steps_transition && - block.transactions().is_empty() && + block.transactions.is_empty() && empty_steps.len() < self.maximum_empty_steps { if self.step.can_propose.compare_and_swap(true, false, AtomicOrdering::SeqCst) { @@ -1139,7 +1155,7 @@ impl Engine for AuthorityRound { if self.immediate_transitions || !epoch_begin { return Ok(()) } // genesis is never a new block, but might as well check. - let header = block.header().clone(); + let header = block.header.clone(); let first = header.number() == 0; let mut call = |to, data| { @@ -1159,8 +1175,8 @@ impl Engine for AuthorityRound { /// Apply the block reward on finalisation of the block. fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { let mut beneficiaries = Vec::new(); - if block.header().number() >= self.empty_steps_transition { - let empty_steps = if block.header().seal().is_empty() { + if block.header.number() >= self.empty_steps_transition { + let empty_steps = if block.header.seal().is_empty() { // this is a new block, calculate rewards based on the empty steps messages we have accumulated let client = match self.client.read().as_ref().and_then(|weak| weak.upgrade()) { Some(client) => client, @@ -1170,7 +1186,7 @@ impl Engine for AuthorityRound { }, }; - let parent = client.block_header(::client::BlockId::Hash(*block.header().parent_hash())) + let parent = client.block_header(::client::BlockId::Hash(*block.header.parent_hash())) .expect("hash is from parent; parent header must exist; qed") .decode()?; @@ -1179,7 +1195,7 @@ impl Engine for AuthorityRound { self.empty_steps(parent_step.into(), current_step.into(), parent.hash()) } else { // we're verifying a block, extract empty steps from the seal - header_empty_steps(block.header())? + header_empty_steps(&block.header)? }; for empty_step in empty_steps { @@ -1188,11 +1204,11 @@ impl Engine for AuthorityRound { } } - let author = *block.header().author(); + let author = *block.header.author(); beneficiaries.push((author, RewardKind::Author)); let rewards: Vec<_> = match self.block_reward_contract { - Some(ref c) if block.header().number() >= self.block_reward_contract_transition => { + Some(ref c) if block.header.number() >= self.block_reward_contract_transition => { let mut call = super::default_system_or_code_call(&self.machine, block); let rewards = c.reward(&beneficiaries, &mut call)?; @@ -1406,8 +1422,10 @@ impl Engine for AuthorityRound { let first = chain_head.number() == 0; - // apply immediate transitions. + // Apply transitions that don't require finality and should be enacted immediately (e.g from chain spec) if let Some(change) = self.validators.is_epoch_end(first, chain_head) { + info!(target: "engine", "Immediately applying validator set change signalled at block {}", chain_head.number()); + self.epoch_manager.lock().note_new_epoch(); let change = combine_proofs(chain_head.number(), &change, &[]); return Some(change) } @@ -1492,12 +1510,16 @@ impl Engine for AuthorityRound { self.validators.register_client(client); } - fn set_signer(&self, ap: Arc, address: Address, password: Password) { - self.signer.write().set(ap, address, password); + fn set_signer(&self, signer: Box) { + *self.signer.write() = Some(signer); } fn sign(&self, hash: H256) -> Result { - Ok(self.signer.read().sign(hash)?) + Ok(self.signer.read() + .as_ref() + .ok_or(ethkey::Error::InvalidAddress)? + .sign(hash)? + ) } fn snapshot_components(&self) -> Option> { @@ -1532,16 +1554,16 @@ mod tests { use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; use hash::keccak; + use accounts::AccountProvider; use ethereum_types::{Address, H520, H256, U256}; use ethkey::Signature; use types::header::Header; use rlp::encode; use block::*; use test_helpers::{ - generate_dummy_client_with_spec_and_accounts, get_temp_state_db, + generate_dummy_client_with_spec, get_temp_state_db, TestNotify }; - use account_provider::AccountProvider; use spec::Spec; use types::transaction::{Action, Transaction}; use engines::{Seal, Engine, EngineError, EthEngine}; @@ -1615,23 +1637,23 @@ mod tests { let db1 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let db2 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let b1 = b1.close_and_lock().unwrap(); - let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let b2 = b2.close_and_lock().unwrap(); - engine.set_signer(tap.clone(), addr1, "1".into()); - if let Seal::Regular(seal) = engine.generate_seal(b1.block(), &genesis_header) { + engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + if let Seal::Regular(seal) = engine.generate_seal(&b1, &genesis_header) { assert!(b1.clone().try_seal(engine, seal).is_ok()); // Second proposal is forbidden. - assert!(engine.generate_seal(b1.block(), &genesis_header) == Seal::None); + assert!(engine.generate_seal(&b1, &genesis_header) == Seal::None); } - engine.set_signer(tap, addr2, "2".into()); - if let Seal::Regular(seal) = engine.generate_seal(b2.block(), &genesis_header) { + engine.set_signer(Box::new((tap, addr2, "2".into()))); + if let Seal::Regular(seal) = engine.generate_seal(&b2, &genesis_header) { assert!(b2.clone().try_seal(engine, seal).is_ok()); // Second proposal is forbidden. - assert!(engine.generate_seal(b2.block(), &genesis_header) == Seal::None); + assert!(engine.generate_seal(&b2, &genesis_header) == Seal::None); } } @@ -1649,19 +1671,19 @@ mod tests { let db2 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let b1 = b1.close_and_lock().unwrap(); - let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let b2 = b2.close_and_lock().unwrap(); - engine.set_signer(tap.clone(), addr1, "1".into()); - match engine.generate_seal(b1.block(), &genesis_header) { + engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + match engine.generate_seal(&b1, &genesis_header) { Seal::None | Seal::Proposal(_) => panic!("wrong seal"), Seal::Regular(_) => { engine.step(); - engine.set_signer(tap.clone(), addr2, "0".into()); - match engine.generate_seal(b2.block(), &genesis_header) { + engine.set_signer(Box::new((tap.clone(), addr2, "0".into()))); + match engine.generate_seal(&b2, &genesis_header) { Seal::Regular(_) | Seal::Proposal(_) => panic!("sealed despite wrong difficulty"), Seal::None => {} } @@ -1768,7 +1790,7 @@ mod tests { assert!(aura.verify_block_family(&header, &parent_header).is_ok()); assert_eq!(last_benign.load(AtomicOrdering::SeqCst), 0); - aura.set_signer(Arc::new(AccountProvider::transient_provider()), Default::default(), "".into()); + aura.set_signer(Box::new((Arc::new(AccountProvider::transient_provider()), Default::default(), "".into()))); // Do not report on steps skipped between genesis and first block. header.set_number(1); @@ -1878,18 +1900,18 @@ mod tests { let last_hashes = Arc::new(vec![genesis_header.hash()]); - let client = generate_dummy_client_with_spec_and_accounts(Spec::new_test_round_empty_steps, None); + let client = generate_dummy_client_with_spec(Spec::new_test_round_empty_steps); let notify = Arc::new(TestNotify::default()); client.add_notify(notify.clone()); engine.register_client(Arc::downgrade(&client) as _); - engine.set_signer(tap.clone(), addr1, "1".into()); + engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let b1 = b1.close_and_lock().unwrap(); // the block is empty so we don't seal and instead broadcast an empty step message - assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); // spec starts with step 2 let empty_step_rlp = encode(&empty_step(engine, 2, &genesis_header.hash())); @@ -1899,7 +1921,7 @@ mod tests { let len = notify.messages.read().len(); // make sure that we don't generate empty step for the second time - assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); assert_eq!(len, notify.messages.read().len()); } @@ -1917,22 +1939,22 @@ mod tests { let last_hashes = Arc::new(vec![genesis_header.hash()]); - let client = generate_dummy_client_with_spec_and_accounts(Spec::new_test_round_empty_steps, None); + let client = generate_dummy_client_with_spec(Spec::new_test_round_empty_steps); let notify = Arc::new(TestNotify::default()); client.add_notify(notify.clone()); engine.register_client(Arc::downgrade(&client) as _); // step 2 - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let b1 = b1.close_and_lock().unwrap(); // since the block is empty it isn't sealed and we generate empty steps - engine.set_signer(tap.clone(), addr1, "1".into()); - assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); engine.step(); // step 3 - let mut b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let mut b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); b2.push_transaction(Transaction { action: Action::Create, nonce: U256::from(0), @@ -1944,9 +1966,9 @@ mod tests { let b2 = b2.close_and_lock().unwrap(); // we will now seal a block with 1tx and include the accumulated empty step message - engine.set_signer(tap.clone(), addr2, "0".into()); - if let Seal::Regular(seal) = engine.generate_seal(b2.block(), &genesis_header) { - engine.set_signer(tap.clone(), addr1, "1".into()); + engine.set_signer(Box::new((tap.clone(), addr2, "0".into()))); + if let Seal::Regular(seal) = engine.generate_seal(&b2, &genesis_header) { + engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash()); let empty_steps = ::rlp::encode_list(&vec![empty_step2]); @@ -1970,36 +1992,36 @@ mod tests { let last_hashes = Arc::new(vec![genesis_header.hash()]); - let client = generate_dummy_client_with_spec_and_accounts(Spec::new_test_round_empty_steps, None); + let client = generate_dummy_client_with_spec(Spec::new_test_round_empty_steps); let notify = Arc::new(TestNotify::default()); client.add_notify(notify.clone()); engine.register_client(Arc::downgrade(&client) as _); // step 2 - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let b1 = b1.close_and_lock().unwrap(); // since the block is empty it isn't sealed and we generate empty steps - engine.set_signer(tap.clone(), addr1, "1".into()); - assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); engine.step(); // step 3 - let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let b2 = b2.close_and_lock().unwrap(); - engine.set_signer(tap.clone(), addr2, "0".into()); - assert_eq!(engine.generate_seal(b2.block(), &genesis_header), Seal::None); + engine.set_signer(Box::new((tap.clone(), addr2, "0".into()))); + assert_eq!(engine.generate_seal(&b2, &genesis_header), Seal::None); engine.step(); // step 4 // the spec sets the maximum_empty_steps to 2 so we will now seal an empty block and include the empty step messages - let b3 = OpenBlock::new(engine, Default::default(), false, db3, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let b3 = OpenBlock::new(engine, Default::default(), false, db3, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let b3 = b3.close_and_lock().unwrap(); - engine.set_signer(tap.clone(), addr1, "1".into()); - if let Seal::Regular(seal) = engine.generate_seal(b3.block(), &genesis_header) { + engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + if let Seal::Regular(seal) = engine.generate_seal(&b3, &genesis_header) { let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash()); - engine.set_signer(tap.clone(), addr2, "0".into()); + engine.set_signer(Box::new((tap.clone(), addr2, "0".into()))); let empty_step3 = sealed_empty_step(engine, 3, &genesis_header.hash()); let empty_steps = ::rlp::encode_list(&vec![empty_step2, empty_step3]); @@ -2022,28 +2044,28 @@ mod tests { let last_hashes = Arc::new(vec![genesis_header.hash()]); - let client = generate_dummy_client_with_spec_and_accounts(Spec::new_test_round_empty_steps, None); + let client = generate_dummy_client_with_spec(Spec::new_test_round_empty_steps); engine.register_client(Arc::downgrade(&client) as _); // step 2 - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let b1 = b1.close_and_lock().unwrap(); // since the block is empty it isn't sealed and we generate empty steps - engine.set_signer(tap.clone(), addr1, "1".into()); - assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); engine.step(); // step 3 // the signer of the accumulated empty step message should be rewarded - let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); - let addr1_balance = b2.block().state().balance(&addr1).unwrap(); + let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); + let addr1_balance = b2.state.balance(&addr1).unwrap(); // after closing the block `addr1` should be reward twice, one for the included empty step message and another for block creation let b2 = b2.close_and_lock().unwrap(); // the spec sets the block reward to 10 - assert_eq!(b2.block().state().balance(&addr1).unwrap(), addr1_balance + (10 * 2)) + assert_eq!(b2.state.balance(&addr1).unwrap(), addr1_balance + (10 * 2)) } #[test] @@ -2084,7 +2106,7 @@ mod tests { ); // empty step with valid signature from incorrect proposer for step - engine.set_signer(tap.clone(), addr1, "1".into()); + engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); let empty_steps = vec![sealed_empty_step(engine, 1, &parent_header.hash())]; set_empty_steps_seal(&mut header, 2, &signature, &empty_steps); @@ -2094,9 +2116,9 @@ mod tests { ); // valid empty steps - engine.set_signer(tap.clone(), addr1, "1".into()); + engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); let empty_step2 = sealed_empty_step(engine, 2, &parent_header.hash()); - engine.set_signer(tap.clone(), addr2, "0".into()); + engine.set_signer(Box::new((tap.clone(), addr2, "0".into()))); let empty_step3 = sealed_empty_step(engine, 3, &parent_header.hash()); let empty_steps = vec![empty_step2, empty_step3]; @@ -2121,10 +2143,7 @@ mod tests { let last_hashes = Arc::new(vec![genesis_header.hash()]); - let client = generate_dummy_client_with_spec_and_accounts( - Spec::new_test_round_block_reward_contract, - None, - ); + let client = generate_dummy_client_with_spec(Spec::new_test_round_block_reward_contract); engine.register_client(Arc::downgrade(&client) as _); // step 2 @@ -2139,13 +2158,13 @@ mod tests { (3141562.into(), 31415620.into()), vec![], false, - &mut Vec::new().into_iter(), + None, ).unwrap(); let b1 = b1.close_and_lock().unwrap(); // since the block is empty it isn't sealed and we generate empty steps - engine.set_signer(tap.clone(), addr1, "1".into()); - assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); engine.step(); // step 3 @@ -2161,9 +2180,9 @@ mod tests { (3141562.into(), 31415620.into()), vec![], false, - &mut Vec::new().into_iter(), + None, ).unwrap(); - let addr1_balance = b2.block().state().balance(&addr1).unwrap(); + let addr1_balance = b2.state.balance(&addr1).unwrap(); // after closing the block `addr1` should be reward twice, one for the included empty step // message and another for block creation @@ -2171,7 +2190,7 @@ mod tests { // the contract rewards (1000 + kind) for each benefactor/reward kind assert_eq!( - b2.block().state().balance(&addr1).unwrap(), + b2.state.balance(&addr1).unwrap(), addr1_balance + (1000 + 0) + (1000 + 2), ) } @@ -2182,7 +2201,7 @@ mod tests { let engine = &*spec.engine; let addr1 = accounts[0]; - engine.set_signer(tap.clone(), addr1, "1".into()); + engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); let mut header: Header = Header::default(); let empty_step = empty_step(engine, 1, &header.parent_hash()); @@ -2263,7 +2282,7 @@ mod tests { header.set_author(accounts[0]); // when - engine.set_signer(tap.clone(), accounts[1], "0".into()); + engine.set_signer(Box::new((tap.clone(), accounts[1], "0".into()))); let empty_steps = vec![ sealed_empty_step(&*engine, 1, &parent.hash()), sealed_empty_step(&*engine, 1, &parent.hash()), @@ -2300,9 +2319,9 @@ mod tests { header.set_author(accounts[0]); // when - engine.set_signer(tap.clone(), accounts[1], "0".into()); + engine.set_signer(Box::new((tap.clone(), accounts[1], "0".into()))); let es1 = sealed_empty_step(&*engine, 1, &parent.hash()); - engine.set_signer(tap.clone(), accounts[0], "1".into()); + engine.set_signer(Box::new((tap.clone(), accounts[0], "1".into()))); let es2 = sealed_empty_step(&*engine, 2, &parent.hash()); let mut empty_steps = vec![es2, es1]; diff --git a/ethcore/src/engines/basic_authority.rs b/ethcore/src/engines/basic_authority.rs index 4a57544adf..69b8d07c52 100644 --- a/ethcore/src/engines/basic_authority.rs +++ b/ethcore/src/engines/basic_authority.rs @@ -16,19 +16,18 @@ //! A blockchain engine that supports a basic, non-BFT proof-of-authority. -use std::sync::{Weak, Arc}; -use ethereum_types::{H256, H520, Address}; +use std::sync::Weak; +use ethereum_types::{H256, H520}; use parking_lot::RwLock; -use ethkey::{self, Password, Signature}; -use account_provider::AccountProvider; +use ethkey::{self, Signature}; use block::*; use engines::{Engine, Seal, ConstructedVerifier, EngineError}; +use engines::signer::EngineSigner; use error::{BlockError, Error}; use ethjson; use client::EngineClient; use machine::{AuxiliaryData, Call, EthereumMachine}; use types::header::{Header, ExtendedHeader}; -use super::signer::EngineSigner; use super::validator_set::{ValidatorSet, SimpleList, new_validator_set}; /// `BasicAuthority` params. @@ -76,7 +75,7 @@ fn verify_external(header: &Header, validators: &ValidatorSet) -> Result<(), Err /// Engine using `BasicAuthority`, trivial proof-of-authority consensus. pub struct BasicAuthority { machine: EthereumMachine, - signer: RwLock, + signer: RwLock>>, validators: Box, } @@ -85,7 +84,7 @@ impl BasicAuthority { pub fn new(our_params: BasicAuthorityParams, machine: EthereumMachine) -> Self { BasicAuthority { machine: machine, - signer: Default::default(), + signer: RwLock::new(None), validators: new_validator_set(our_params.validators), } } @@ -105,7 +104,7 @@ impl Engine for BasicAuthority { /// Attempt to seal the block internally. fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal { - let header = block.header(); + let header = &block.header; let author = header.author(); if self.validators.contains(header.parent_hash(), author) { // account should be pernamently unlocked, otherwise sealing will fail @@ -190,12 +189,16 @@ impl Engine for BasicAuthority { self.validators.register_client(client); } - fn set_signer(&self, ap: Arc, address: Address, password: Password) { - self.signer.write().set(ap, address, password); + fn set_signer(&self, signer: Box) { + *self.signer.write() = Some(signer); } fn sign(&self, hash: H256) -> Result { - Ok(self.signer.read().sign(hash)?) + Ok(self.signer.read() + .as_ref() + .ok_or_else(|| ethkey::Error::InvalidAddress)? + .sign(hash)? + ) } fn snapshot_components(&self) -> Option> { @@ -214,7 +217,7 @@ mod tests { use ethereum_types::H520; use block::*; use test_helpers::get_temp_state_db; - use account_provider::AccountProvider; + use accounts::AccountProvider; use types::header::Header; use spec::Spec; use engines::Seal; @@ -257,13 +260,13 @@ mod tests { let spec = new_test_authority(); let engine = &*spec.engine; - engine.set_signer(Arc::new(tap), addr, "".into()); + engine.set_signer(Box::new((Arc::new(tap), addr, "".into()))); let genesis_header = spec.genesis_header(); let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let b = b.close_and_lock().unwrap(); - if let Seal::Regular(seal) = engine.generate_seal(b.block(), &genesis_header) { + if let Seal::Regular(seal) = engine.generate_seal(&b, &genesis_header) { assert!(b.try_seal(engine, seal).is_ok()); } } @@ -275,7 +278,7 @@ mod tests { let engine = new_test_authority().engine; assert!(!engine.seals_internally().unwrap()); - engine.set_signer(Arc::new(tap), authority, "".into()); + engine.set_signer(Box::new((Arc::new(tap), authority, "".into()))); assert!(engine.seals_internally().unwrap()); } } diff --git a/ethcore/src/engines/block_reward.rs b/ethcore/src/engines/block_reward.rs index 39d1afa7dc..58b55408eb 100644 --- a/ethcore/src/engines/block_reward.rs +++ b/ethcore/src/engines/block_reward.rs @@ -24,11 +24,12 @@ use ethereum_types::{H160, Address, U256}; use std::sync::Arc; use hash::keccak; use error::Error; -use machine::WithRewards; -use parity_machine::{Machine, WithBalances}; +use machine::Machine; use trace; use types::BlockNumber; use super::{SystemOrCodeCall, SystemOrCodeCallKind}; +use trace::{Tracer, ExecutiveTracer, Tracing}; +use block::ExecutedBlock; use_contract!(block_reward_contract, "res/contracts/block_reward.json"); @@ -152,17 +153,26 @@ impl BlockRewardContract { /// Applies the given block rewards, i.e. adds the given balance to each beneficiary' address. /// If tracing is enabled the operations are recorded. -pub fn apply_block_rewards( +pub fn apply_block_rewards( rewards: &[(Address, RewardKind, U256)], - block: &mut M::LiveBlock, + block: &mut ExecutedBlock, machine: &M, ) -> Result<(), M::Error> { for &(ref author, _, ref block_reward) in rewards { machine.add_balance(block, author, block_reward)?; } - let rewards: Vec<_> = rewards.into_iter().map(|&(a, k, r)| (a, k.into(), r)).collect(); - machine.note_rewards(block, &rewards) + if let Tracing::Enabled(ref mut traces) = *block.traces_mut() { + let mut tracer = ExecutiveTracer::default(); + + for &(address, reward_kind, amount) in rewards { + tracer.trace_reward(address, amount, reward_kind.into()); + } + + traces.push(tracer.drain().into()); + } + + Ok(()) } #[cfg(test)] @@ -170,17 +180,14 @@ mod test { use client::PrepareOpenBlock; use ethereum_types::U256; use spec::Spec; - use test_helpers::generate_dummy_client_with_spec_and_accounts; + use test_helpers::generate_dummy_client_with_spec; use engines::SystemOrCodeCallKind; use super::{BlockRewardContract, RewardKind}; #[test] fn block_reward_contract() { - let client = generate_dummy_client_with_spec_and_accounts( - Spec::new_test_round_block_reward_contract, - None, - ); + let client = generate_dummy_client_with_spec(Spec::new_test_round_block_reward_contract); let machine = Spec::new_test_machine(); diff --git a/ethcore/src/engines/clique/block_state.rs b/ethcore/src/engines/clique/block_state.rs new file mode 100644 index 0000000000..6518d8ac24 --- /dev/null +++ b/ethcore/src/engines/clique/block_state.rs @@ -0,0 +1,367 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +use std::collections::{HashMap, BTreeSet, VecDeque}; +use std::fmt; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +use engines::EngineError; +use engines::clique::util::{extract_signers, recover_creator}; +use engines::clique::{VoteType, DIFF_INTURN, DIFF_NOTURN, NULL_AUTHOR, SIGNING_DELAY_NOTURN_MS}; +use error::{Error, BlockError}; +use ethereum_types::{Address, H64}; +use rand::Rng; +use time_utils::CheckedSystemTime; +use types::BlockNumber; +use types::header::Header; +use unexpected::Mismatch; + +/// Type that keeps track of the state for a given vote +// Votes that go against the proposal aren't counted since it's equivalent to not voting +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)] +pub struct VoteState { + kind: VoteType, + votes: u64, +} + +/// Type that represent a vote +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)] +pub struct Vote { + block_number: BlockNumber, + beneficiary: Address, + kind: VoteType, + signer: Address, + reverted: bool, +} + +/// Type that represent a pending vote +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd)] +pub struct PendingVote { + signer: Address, + beneficiary: Address, +} + +/// Clique state for each block. +#[cfg(not(test))] +#[derive(Clone, Debug, Default)] +pub struct CliqueBlockState { + /// Current votes for a beneficiary + votes: HashMap, + /// A list of all votes for the given epoch + votes_history: Vec, + /// a list of all valid signer, sorted by ascending order. + signers: BTreeSet
, + /// a deque of recent signer, new entry should be pushed front, apply() modifies this. + recent_signers: VecDeque
, + /// inturn signing should wait until this time + pub next_timestamp_inturn: Option, + /// noturn signing should wait until this time + pub next_timestamp_noturn: Option, +} + +#[cfg(test)] +#[derive(Clone, Debug, Default)] +pub struct CliqueBlockState { + /// All recorded votes for a given signer, `Vec` is a stack of votes + pub votes: HashMap, + /// A list of all votes for the given epoch + pub votes_history: Vec, + /// a list of all valid signer, sorted by ascending order. + pub signers: BTreeSet
, + /// a deque of recent signer, new entry should be pushed front, apply() modifies this. + pub recent_signers: VecDeque
, + /// inturn signing should wait until this time + pub next_timestamp_inturn: Option, + /// noturn signing should wait until this time + pub next_timestamp_noturn: Option, +} + +impl fmt::Display for CliqueBlockState { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let signers: Vec = self.signers.iter() + .map(|s| + format!("{} {:?}", + s, + self.votes.iter().map(|(v, s)| format!("[beneficiary {}, votes: {}]", v.beneficiary, s.votes)) + .collect::>() + ) + ) + .collect(); + + let recent_signers: Vec = self.recent_signers.iter().map(|s| format!("{}", s)).collect(); + let num_votes = self.votes_history.len(); + let add_votes = self.votes_history.iter().filter(|v| v.kind == VoteType::Add).count(); + let rm_votes = self.votes_history.iter().filter(|v| v.kind == VoteType::Remove).count(); + let reverted_votes = self.votes_history.iter().filter(|v| v.reverted).count(); + + write!(f, + "Votes {{ \n signers: {:?} \n recent_signers: {:?} \n number of votes: {} \n number of add votes {} + \r number of remove votes {} \n number of reverted votes: {}}}", + signers, recent_signers, num_votes, add_votes, rm_votes, reverted_votes) + } +} + +impl CliqueBlockState { + /// Create new state with given information, this is used creating new state from Checkpoint block. + pub fn new(signers: BTreeSet
) -> Self { + CliqueBlockState { + signers, + ..Default::default() + } + } + + // see https://github.com/ethereum/go-ethereum/blob/master/consensus/clique/clique.go#L474 + fn verify(&self, header: &Header) -> Result { + let creator = recover_creator(header)?.clone(); + + // The signer is not authorized + if !self.signers.contains(&creator) { + trace!(target: "engine", "current state: {}", self); + Err(EngineError::NotAuthorized(creator))? + } + + // The signer has signed a block too recently + if self.recent_signers.contains(&creator) { + trace!(target: "engine", "current state: {}", self); + Err(EngineError::CliqueTooRecentlySigned(creator))? + } + + // Wrong difficulty + let inturn = self.is_inturn(header.number(), &creator); + + if inturn && *header.difficulty() != DIFF_INTURN { + Err(BlockError::InvalidDifficulty(Mismatch { + expected: DIFF_INTURN, + found: *header.difficulty(), + }))? + } + + if !inturn && *header.difficulty() != DIFF_NOTURN { + Err(BlockError::InvalidDifficulty(Mismatch { + expected: DIFF_NOTURN, + found: *header.difficulty(), + }))? + } + + Ok(creator) + } + + /// Verify and apply a new header to current state + pub fn apply(&mut self, header: &Header, is_checkpoint: bool) -> Result { + let creator = self.verify(header)?; + self.recent_signers.push_front(creator); + self.rotate_recent_signers(); + + if is_checkpoint { + // checkpoint block should not affect previous tallying, so we check that. + let signers = extract_signers(header)?; + if self.signers != signers { + let invalid_signers: Vec = signers.into_iter() + .filter(|s| !self.signers.contains(s)) + .map(|s| format!("{}", s)) + .collect(); + Err(EngineError::CliqueFaultyRecoveredSigners(invalid_signers))? + }; + + // TODO(niklasad1): I'm not sure if we should shrink here because it is likely that next epoch + // will need some memory and might be better for allocation algorithm to decide whether to shrink or not + // (typically doubles or halves the allocted memory when necessary) + self.votes.clear(); + self.votes_history.clear(); + self.votes.shrink_to_fit(); + self.votes_history.shrink_to_fit(); + } + + // Contains vote + if *header.author() != NULL_AUTHOR { + let decoded_seal = header.decode_seal::>()?; + if decoded_seal.len() != 2 { + Err(BlockError::InvalidSealArity(Mismatch { expected: 2, found: decoded_seal.len() }))? + } + + let nonce: H64 = decoded_seal[1].into(); + self.update_signers_on_vote(VoteType::from_nonce(nonce)?, creator, *header.author(), header.number())?; + } + + Ok(creator) + } + + fn update_signers_on_vote( + &mut self, + kind: VoteType, + signer: Address, + beneficiary: Address, + block_number: u64 + ) -> Result<(), Error> { + + trace!(target: "engine", "Attempt vote {:?} {:?}", kind, beneficiary); + + let pending_vote = PendingVote { signer, beneficiary }; + + let reverted = if self.is_valid_vote(&beneficiary, kind) { + self.add_vote(pending_vote, kind) + } else { + // This case only happens if a `signer` wants to revert their previous vote + // (does nothing if no previous vote was found) + self.revert_vote(pending_vote) + }; + + // Add all votes to the history + self.votes_history.push( + Vote { + block_number, + beneficiary, + kind, + signer, + reverted, + }); + + // If no vote was found for the beneficiary return `early` but don't propogate an error + let (votes, vote_kind) = match self.get_current_votes_and_kind(beneficiary) { + Some((v, k)) => (v, k), + None => return Ok(()), + }; + let threshold = self.signers.len() / 2; + + debug!(target: "engine", "{}/{} votes to have consensus", votes, threshold + 1); + trace!(target: "engine", "votes: {:?}", votes); + + if votes > threshold { + match vote_kind { + VoteType::Add => { + if self.signers.insert(beneficiary) { + debug!(target: "engine", "added new signer: {}", beneficiary); + } + } + VoteType::Remove => { + if self.signers.remove(&beneficiary) { + debug!(target: "engine", "removed signer: {}", beneficiary); + } + } + } + + self.rotate_recent_signers(); + self.remove_all_votes_from(beneficiary); + } + + Ok(()) + } + + /// Calculate the next timestamp for `inturn` and `noturn` fails if any of them can't be represented as + /// `SystemTime` + // TODO(niklasad1): refactor this method to be in constructor of `CliqueBlockState` instead. + // This is a quite bad API because we must mutate both variables even when already `inturn` fails + // That's why we can't return early and must have the `if-else` in the end + pub fn calc_next_timestamp(&mut self, timestamp: u64, period: u64) -> Result<(), Error> { + let inturn = CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::from_secs(timestamp.saturating_add(period))); + + self.next_timestamp_inturn = inturn; + + let delay = Duration::from_millis( + rand::thread_rng().gen_range(0u64, (self.signers.len() as u64 / 2 + 1) * SIGNING_DELAY_NOTURN_MS)); + self.next_timestamp_noturn = inturn.map(|inturn| { + inturn + delay + }); + + if self.next_timestamp_inturn.is_some() && self.next_timestamp_noturn.is_some() { + Ok(()) + } else { + Err(BlockError::TimestampOverflow)? + } + } + + /// Returns true if the block difficulty should be `inturn` + pub fn is_inturn(&self, current_block_number: u64, author: &Address) -> bool { + if let Some(pos) = self.signers.iter().position(|x| *author == *x) { + return current_block_number % self.signers.len() as u64 == pos as u64; + } + false + } + + /// Returns whether the signer is authorized to sign a block + pub fn is_authorized(&self, author: &Address) -> bool { + self.signers.contains(author) && !self.recent_signers.contains(author) + } + + /// Returns whether it makes sense to cast the specified vote in the + /// current state (e.g. don't try to add an already authorized signer). + pub fn is_valid_vote(&self, address: &Address, vote_type: VoteType) -> bool { + let in_signer = self.signers.contains(address); + match vote_type { + VoteType::Add => !in_signer, + VoteType::Remove => in_signer, + } + } + + /// Returns the list of current signers + pub fn signers(&self) -> &BTreeSet
{ + &self.signers + } + + // Note this method will always return `true` but it is intended for a uniform `API` + fn add_vote(&mut self, pending_vote: PendingVote, kind: VoteType) -> bool { + + self.votes.entry(pending_vote) + .and_modify(|state| { + state.votes = state.votes.saturating_add(1); + }) + .or_insert_with(|| VoteState { kind, votes: 1 }); + true + } + + fn revert_vote(&mut self, pending_vote: PendingVote) -> bool { + let mut revert = false; + let mut remove = false; + + self.votes.entry(pending_vote).and_modify(|state| { + if state.votes.saturating_sub(1) == 0 { + remove = true; + } + revert = true; + }); + + if remove { + self.votes.remove(&pending_vote); + } + + revert + } + + fn get_current_votes_and_kind(&self, beneficiary: Address) -> Option<(usize, VoteType)> { + let kind = self.votes.iter() + .find(|(v, _t)| v.beneficiary == beneficiary) + .map(|(_v, t)| t.kind)?; + + let votes = self.votes.keys() + .filter(|vote| vote.beneficiary == beneficiary) + .count(); + + Some((votes, kind)) + } + + fn rotate_recent_signers(&mut self) { + if self.recent_signers.len() >= ( self.signers.len() / 2 ) + 1 { + self.recent_signers.pop_back(); + } + } + + fn remove_all_votes_from(&mut self, beneficiary: Address) { + self.votes = std::mem::replace(&mut self.votes, HashMap::new()) + .into_iter() + .filter(|(v, _t)| v.signer != beneficiary && v.beneficiary != beneficiary) + .collect(); + } +} diff --git a/ethcore/src/engines/clique/mod.rs b/ethcore/src/engines/clique/mod.rs new file mode 100644 index 0000000000..8be54da266 --- /dev/null +++ b/ethcore/src/engines/clique/mod.rs @@ -0,0 +1,774 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +//! Implementation of the Clique PoA Engine. +//! +//! File structure: +//! - mod.rs -> Provides the engine API implementation, with additional block state tracking +//! - block_state.rs -> Records the Clique state for given block. +//! - params.rs -> Contains the parameters for the Clique engine. +//! - step_service.rs -> An event loop to trigger sealing. +//! - util.rs -> Various standalone utility functions. +//! - tests.rs -> Consensus tests as defined in EIP-225. + +/// How syncing works: +/// +/// 1. Client will call: +/// - `Clique::verify_block_basic()` +/// - `Clique::verify_block_unordered()` +/// - `Clique::verify_block_family()` +/// 2. Using `Clique::state()` we try and retrieve the parent state. If this isn't found +/// we need to back-fill it from the last known checkpoint. +/// 3. Once we have a good state, we can record it using `CliqueBlockState::apply()`. + +/// How sealing works: +/// +/// 1. Set a signer using `Engine::set_signer()`. If a miner account was set up through +/// a config file or CLI flag `MinerService::set_author()` will eventually set the signer +/// 2. We check that the engine seals internally through `Clique::seals_internally()` +/// Note: This is always true for Clique +/// 3. Calling `Clique::new()` will spawn a `StepService` thread. This thread will call `Engine::step()` +/// periodically. Internally, the Clique `step()` function calls `Client::update_sealing()`, which is +/// what makes and seals a block. +/// 4. `Clique::generate_seal()` will then be called by `miner`. This will return a `Seal` which +/// is either a `Seal::None` or `Seal:Regular`. The following shows how a `Seal` variant is chosen: +/// a. We return `Seal::None` if no signer is available or the signer is not authorized. +/// b. If period == 0 and block has transactions, we return `Seal::Regular`, otherwise return `Seal::None`. +/// c. If we're `INTURN`, wait for at least `period` since last block before trying to seal. +/// d. If we're not `INTURN`, we wait for a random amount of time using the algorithm specified +/// in EIP-225 before trying to seal again. +/// 5. Miner will create new block, in process it will call several engine methods to do following: +/// a. `Clique::open_block_header_timestamp()` must set timestamp correctly. +/// b. `Clique::populate_from_parent()` must set difficulty to correct value. +/// Note: `Clique::populate_from_parent()` is used in both the syncing and sealing code paths. +/// 6. We call `Clique::on_seal_block()` which will allow us to modify the block header during seal generation. +/// 7. Finally, `Clique::verify_local_seal()` is called. After this, the syncing code path will be followed +/// in order to import the new block. + +use std::cmp; +use std::collections::HashMap; +use std::collections::VecDeque; +use std::sync::{Arc, Weak}; +use std::thread; +use std::time; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +use block::ExecutedBlock; +use bytes::Bytes; +use client::{BlockId, EngineClient}; +use engines::clique::util::{extract_signers, recover_creator}; +use engines::{Engine, EngineError, Seal}; +use error::{BlockError, Error}; +use ethereum_types::{Address, H64, H160, H256, U256}; +use ethkey::Signature; +use hash::KECCAK_EMPTY_LIST_RLP; +use itertools::Itertools; +use lru_cache::LruCache; +use machine::{Call, EthereumMachine}; +use parking_lot::RwLock; +use rand::Rng; +use super::signer::EngineSigner; +use unexpected::{Mismatch, OutOfBounds}; +use time_utils::CheckedSystemTime; +use types::BlockNumber; +use types::header::{ExtendedHeader, Header}; + +use self::block_state::CliqueBlockState; +use self::params::CliqueParams; +use self::step_service::StepService; + +mod params; +mod block_state; +mod step_service; +mod util; + +// TODO(niklasad1): extract tester types into a separate mod to be shared in the code base +#[cfg(test)] +mod tests; + +// Protocol constants +/// Fixed number of extra-data prefix bytes reserved for signer vanity +pub const VANITY_LENGTH: usize = 32; +/// Fixed number of extra-data suffix bytes reserved for signer signature +pub const SIGNATURE_LENGTH: usize = 65; +/// Address length of signer +pub const ADDRESS_LENGTH: usize = 20; +/// Nonce value for DROP vote +pub const NONCE_DROP_VOTE: H64 = H64([0; 8]); +/// Nonce value for AUTH vote +pub const NONCE_AUTH_VOTE: H64 = H64([0xff; 8]); +/// Difficulty for INTURN block +pub const DIFF_INTURN: U256 = U256([2, 0, 0, 0]); +/// Difficulty for NOTURN block +pub const DIFF_NOTURN: U256 = U256([1, 0, 0, 0]); +/// Default empty author field value +pub const NULL_AUTHOR: Address = H160([0x00; 20]); +/// Default empty nonce value +pub const NULL_NONCE: H64 = NONCE_DROP_VOTE; +/// Default value for mixhash +pub const NULL_MIXHASH: H256 = H256([0; 32]); +/// Default value for uncles hash +pub const NULL_UNCLES_HASH: H256 = KECCAK_EMPTY_LIST_RLP; +/// Default noturn block wiggle factor defined in spec. +pub const SIGNING_DELAY_NOTURN_MS: u64 = 500; + +/// How many CliqueBlockState to cache in the memory. +pub const STATE_CACHE_NUM: usize = 128; + +/// Vote to add or remove the beneficiary +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)] +pub enum VoteType { + Add, + Remove, +} + +impl VoteType { + /// Try to construct a `Vote` from a nonce + pub fn from_nonce(nonce: H64) -> Result { + if nonce == NONCE_AUTH_VOTE { + Ok(VoteType::Add) + } else if nonce == NONCE_DROP_VOTE { + Ok(VoteType::Remove) + } else { + Err(EngineError::CliqueInvalidNonce(nonce))? + } + } + + /// Get the rlp encoding of the vote + pub fn as_rlp(&self) -> Vec> { + match self { + VoteType::Add => vec![rlp::encode(&NULL_MIXHASH), rlp::encode(&NONCE_AUTH_VOTE)], + VoteType::Remove => vec![rlp::encode(&NULL_MIXHASH), rlp::encode(&NONCE_DROP_VOTE)], + } + } +} + +/// Clique Engine implementation +// block_state_by_hash -> block state indexed by header hash. +#[cfg(not(test))] +pub struct Clique { + epoch_length: u64, + period: u64, + machine: EthereumMachine, + client: RwLock>>, + block_state_by_hash: RwLock>, + proposals: RwLock>, + signer: RwLock>>, + step_service: Option>, +} + +#[cfg(test)] +/// Test version of `CliqueEngine` to make all fields public +pub struct Clique { + pub epoch_length: u64, + pub period: u64, + pub machine: EthereumMachine, + pub client: RwLock>>, + pub block_state_by_hash: RwLock>, + pub proposals: RwLock>, + pub signer: RwLock>>, + pub step_service: Option>, +} + +impl Clique { + /// Initialize Clique engine from empty state. + pub fn new(our_params: CliqueParams, machine: EthereumMachine) -> Result, Error> { + let mut engine = Clique { + epoch_length: our_params.epoch, + period: our_params.period, + client: Default::default(), + block_state_by_hash: RwLock::new(LruCache::new(STATE_CACHE_NUM)), + proposals: Default::default(), + signer: Default::default(), + machine, + step_service: None, + }; + + let res = Arc::new(engine); + + if our_params.period > 0 { + engine.step_service = Some(StepService::start(Arc::downgrade(&res) as Weak>)); + } + + Ok(res) + } + + #[cfg(test)] + /// Initialize test variant of `CliqueEngine`, + /// Note we need to `mock` the miner and it is introduced to test block verification to trigger new blocks + /// to mainly test consensus edge cases + pub fn with_test(epoch_length: u64, period: u64) -> Self { + use spec::Spec; + + Self { + epoch_length, + period, + client: Default::default(), + block_state_by_hash: RwLock::new(LruCache::new(STATE_CACHE_NUM)), + proposals: Default::default(), + signer: Default::default(), + machine: Spec::new_test_machine(), + step_service: None, + } + } + + fn sign_header(&self, header: &Header) -> Result<(Signature, H256), Error> { + + match self.signer.read().as_ref() { + None => { + Err(EngineError::RequiresSigner)? + } + Some(signer) => { + let digest = header.hash(); + match signer.sign(digest) { + Ok(sig) => Ok((sig, digest)), + Err(e) => Err(EngineError::Custom(e.into()))?, + } + } + } + } + + /// Construct an new state from given checkpoint header. + fn new_checkpoint_state(&self, header: &Header) -> Result { + debug_assert_eq!(header.number() % self.epoch_length, 0); + + let mut state = CliqueBlockState::new( + extract_signers(header)?); + + // TODO(niklasad1): refactor to perform this check in the `CliqueBlockState` constructor instead + state.calc_next_timestamp(header.timestamp(), self.period)?; + + Ok(state) + } + + fn state_no_backfill(&self, hash: &H256) -> Option { + self.block_state_by_hash.write().get_mut(hash).cloned() + } + + /// Get `CliqueBlockState` for given header, backfill from last checkpoint if needed. + fn state(&self, header: &Header) -> Result { + let mut block_state_by_hash = self.block_state_by_hash.write(); + if let Some(state) = block_state_by_hash.get_mut(&header.hash()) { + return Ok(state.clone()); + } + // If we are looking for an checkpoint block state, we can directly reconstruct it. + if header.number() % self.epoch_length == 0 { + let state = self.new_checkpoint_state(header)?; + block_state_by_hash.insert(header.hash(), state.clone()); + return Ok(state); + } + // BlockState is not found in memory, which means we need to reconstruct state from last checkpoint. + match self.client.read().as_ref().and_then(|w| w.upgrade()) { + None => { + return Err(EngineError::RequiresClient)?; + } + Some(c) => { + let last_checkpoint_number = header.number() - header.number() % self.epoch_length as u64; + debug_assert_ne!(last_checkpoint_number, header.number()); + + // Catching up state, note that we don't really store block state for intermediary blocks, + // for speed. + let backfill_start = time::Instant::now(); + trace!(target: "engine", + "Back-filling block state. last_checkpoint_number: {}, target: {}({}).", + last_checkpoint_number, header.number(), header.hash()); + + let mut chain: &mut VecDeque
= &mut VecDeque::with_capacity( + (header.number() - last_checkpoint_number + 1) as usize); + + // Put ourselves in. + chain.push_front(header.clone()); + + // populate chain to last checkpoint + loop { + let (last_parent_hash, last_num) = { + let l = chain.front().expect("chain has at least one element; qed"); + (*l.parent_hash(), l.number()) + }; + + if last_num == last_checkpoint_number + 1 { + break; + } + match c.block_header(BlockId::Hash(last_parent_hash)) { + None => { + return Err(BlockError::UnknownParent(last_parent_hash))?; + } + Some(next) => { + chain.push_front(next.decode()?); + } + } + } + + // Get the state for last checkpoint. + let last_checkpoint_hash = *chain.front() + .expect("chain has at least one element; qed") + .parent_hash(); + + let last_checkpoint_header = match c.block_header(BlockId::Hash(last_checkpoint_hash)) { + None => return Err(EngineError::CliqueMissingCheckpoint(last_checkpoint_hash))?, + Some(header) => header.decode()?, + }; + + let last_checkpoint_state = match block_state_by_hash.get_mut(&last_checkpoint_hash) { + Some(state) => state.clone(), + None => self.new_checkpoint_state(&last_checkpoint_header)?, + }; + + block_state_by_hash.insert(last_checkpoint_header.hash(), last_checkpoint_state.clone()); + + // Backfill! + let mut new_state = last_checkpoint_state.clone(); + for item in chain { + new_state.apply(item, false)?; + } + new_state.calc_next_timestamp(header.timestamp(), self.period)?; + block_state_by_hash.insert(header.hash(), new_state.clone()); + + let elapsed = backfill_start.elapsed(); + trace!(target: "engine", "Back-filling succeed, took {} ms.", elapsed.as_millis()); + Ok(new_state) + } + } + } +} + +impl Engine for Clique { + fn name(&self) -> &str { "Clique" } + + fn machine(&self) -> &EthereumMachine { &self.machine } + + // Clique use same fields, nonce + mixHash + fn seal_fields(&self, _header: &Header) -> usize { 2 } + + fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 0 } + + fn on_new_block( + &self, + _block: &mut ExecutedBlock, + _epoch_begin: bool, + _ancestry: &mut Iterator, + ) -> Result<(), Error> { + Ok(()) + } + + // Clique has no block reward. + fn on_close_block(&self, _block: &mut ExecutedBlock) -> Result<(), Error> { + Ok(()) + } + + fn on_seal_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { + trace!(target: "engine", "on_seal_block"); + + let header = &mut block.header; + + let state = self.state_no_backfill(header.parent_hash()) + .ok_or_else(|| BlockError::UnknownParent(*header.parent_hash()))?; + + let is_checkpoint = header.number() % self.epoch_length == 0; + + header.set_author(NULL_AUTHOR); + + // Cast a random Vote if not checkpoint + if !is_checkpoint { + // TODO(niklasad1): this will always be false because `proposals` is never written to + let votes = self.proposals.read().iter() + .filter(|(address, vote_type)| state.is_valid_vote(*address, **vote_type)) + .map(|(address, vote_type)| (*address, *vote_type)) + .collect_vec(); + + if !votes.is_empty() { + // Pick a random vote. + let random_vote = rand::thread_rng().gen_range(0 as usize, votes.len()); + let (beneficiary, vote_type) = votes[random_vote]; + + trace!(target: "engine", "Casting vote: beneficiary {}, type {:?} ", beneficiary, vote_type); + + header.set_author(beneficiary); + header.set_seal(vote_type.as_rlp()); + } + } + + // Work on clique seal. + + let mut seal: Vec = Vec::with_capacity(VANITY_LENGTH + SIGNATURE_LENGTH); + + // At this point, extra_data should only contain miner vanity. + if header.extra_data().len() != VANITY_LENGTH { + Err(BlockError::ExtraDataOutOfBounds(OutOfBounds { + min: Some(VANITY_LENGTH), + max: Some(VANITY_LENGTH), + found: header.extra_data().len() + }))?; + } + // vanity + { + seal.extend_from_slice(&header.extra_data()[0..VANITY_LENGTH]); + } + + // If we are building an checkpoint block, add all signers now. + if is_checkpoint { + seal.reserve(state.signers().len() * 20); + state.signers().iter().foreach(|addr| { + seal.extend_from_slice(&addr[..]); + }); + } + + header.set_extra_data(seal.clone()); + + // append signature onto extra_data + let (sig, _msg) = self.sign_header(&header)?; + seal.extend_from_slice(&sig[..]); + header.set_extra_data(seal.clone()); + + header.compute_hash(); + + // locally sealed block don't go through valid_block_family(), so we have to record state here. + let mut new_state = state.clone(); + new_state.apply(&header, is_checkpoint)?; + new_state.calc_next_timestamp(header.timestamp(), self.period)?; + self.block_state_by_hash.write().insert(header.hash(), new_state); + + trace!(target: "engine", "on_seal_block: finished, final header: {:?}", header); + + Ok(()) + } + + /// Clique doesn't require external work to seal, so we always return true here. + fn seals_internally(&self) -> Option { + Some(true) + } + + /// Returns if we are ready to seal, the real sealing (signing extra_data) is actually done in `on_seal_block()`. + fn generate_seal(&self, block: &ExecutedBlock, parent: &Header) -> Seal { + trace!(target: "engine", "tried to generate_seal"); + let null_seal = util::null_seal(); + + if block.header.number() == 0 { + trace!(target: "engine", "attempted to seal genesis block"); + return Seal::None; + } + + // if sealing period is 0, and not an checkpoint block, refuse to seal + if self.period == 0 { + if block.transactions.is_empty() && block.header.number() % self.epoch_length != 0 { + return Seal::None; + } + return Seal::Regular(null_seal); + } + + // Check we actually have authority to seal. + if let Some(author) = self.signer.read().as_ref().map(|x| x.address()) { + + // ensure the voting state exists + match self.state(&parent) { + Err(e) => { + warn!(target: "engine", "generate_seal: can't get parent state(number: {}, hash: {}): {} ", + parent.number(), parent.hash(), e); + return Seal::None; + } + Ok(state) => { + // Are we authorized to seal? + if !state.is_authorized(&author) { + trace!(target: "engine", "generate_seal: Not authorized to sign right now."); + // wait for one third of period to try again. + thread::sleep(Duration::from_secs(self.period / 3 + 1)); + return Seal::None; + } + + let inturn = state.is_inturn(block.header.number(), &author); + + let now = SystemTime::now(); + + let limit = match inturn { + true => state.next_timestamp_inturn.unwrap_or(now), + false => state.next_timestamp_noturn.unwrap_or(now), + }; + + // Wait for the right moment. + if now < limit { + trace!(target: "engine", + "generate_seal: sleeping to sign: inturn: {}, now: {:?}, to: {:?}.", + inturn, now, limit); + match limit.duration_since(SystemTime::now()) { + Ok(duration) => { + thread::sleep(duration); + }, + Err(e) => { + warn!(target:"engine", "generate_seal: unable to sleep, err: {}", e); + return Seal::None; + } + } + } + + trace!(target: "engine", "generate_seal: seal ready for block {}, txs: {}.", + block.header.number(), block.transactions.len()); + return Seal::Regular(null_seal); + } + } + } + Seal::None + } + + fn verify_local_seal(&self, _header: &Header) -> Result<(), Error> { Ok(()) } + + fn verify_block_basic(&self, header: &Header) -> Result<(), Error> { + // Largely same as https://github.com/ethereum/go-ethereum/blob/master/consensus/clique/clique.go#L275 + + // Ignore genesis block. + if header.number() == 0 { + return Ok(()); + } + + // Don't waste time checking blocks from the future + { + let limit = CheckedSystemTime::checked_add(SystemTime::now(), Duration::from_secs(self.period)) + .ok_or(BlockError::TimestampOverflow)?; + + // This should succeed under the contraints that the system clock works + let limit_as_dur = limit.duration_since(UNIX_EPOCH).map_err(|e| { + Box::new(format!("Converting SystemTime to Duration failed: {}", e)) + })?; + + let hdr = Duration::from_secs(header.timestamp()); + if hdr > limit_as_dur { + let found = CheckedSystemTime::checked_add(UNIX_EPOCH, hdr).ok_or(BlockError::TimestampOverflow)?; + + Err(BlockError::TemporarilyInvalid(OutOfBounds { + min: None, + max: Some(limit), + found, + }))? + } + } + + let is_checkpoint = header.number() % self.epoch_length == 0; + + if is_checkpoint && *header.author() != NULL_AUTHOR { + return Err(EngineError::CliqueWrongAuthorCheckpoint(Mismatch { + expected: 0.into(), + found: *header.author(), + }))?; + } + + let seal_fields = header.decode_seal::>()?; + if seal_fields.len() != 2 { + Err(BlockError::InvalidSealArity(Mismatch { + expected: 2, + found: seal_fields.len(), + }))? + } + + let mixhash: H256 = seal_fields[0].into(); + let nonce: H64 = seal_fields[1].into(); + + // Nonce must be 0x00..0 or 0xff..f + if nonce != NONCE_DROP_VOTE && nonce != NONCE_AUTH_VOTE { + Err(EngineError::CliqueInvalidNonce(nonce))?; + } + + if is_checkpoint && nonce != NULL_NONCE { + Err(EngineError::CliqueInvalidNonce(nonce))?; + } + + // Ensure that the mix digest is zero as Clique don't have fork protection currently + if mixhash != NULL_MIXHASH { + Err(BlockError::MismatchedH256SealElement(Mismatch { + expected: NULL_MIXHASH, + found: mixhash, + }))? + } + + let extra_data_len = header.extra_data().len(); + + if extra_data_len < VANITY_LENGTH { + Err(EngineError::CliqueMissingVanity)? + } + + if extra_data_len < VANITY_LENGTH + SIGNATURE_LENGTH { + Err(EngineError::CliqueMissingSignature)? + } + + let signers = extra_data_len - (VANITY_LENGTH + SIGNATURE_LENGTH); + + // Checkpoint blocks must at least contain one signer + if is_checkpoint && signers == 0 { + Err(EngineError::CliqueCheckpointNoSigner)? + } + + // Addresses must be be divisable by 20 + if is_checkpoint && signers % ADDRESS_LENGTH != 0 { + Err(EngineError::CliqueCheckpointInvalidSigners(signers))? + } + + // Ensure that the block doesn't contain any uncles which are meaningless in PoA + if *header.uncles_hash() != NULL_UNCLES_HASH { + Err(BlockError::InvalidUnclesHash(Mismatch { + expected: NULL_UNCLES_HASH, + found: *header.uncles_hash(), + }))? + } + + // Ensure that the block's difficulty is meaningful (may not be correct at this point) + if *header.difficulty() != DIFF_INTURN && *header.difficulty() != DIFF_NOTURN { + Err(BlockError::DifficultyOutOfBounds(OutOfBounds { + min: Some(DIFF_NOTURN), + max: Some(DIFF_INTURN), + found: *header.difficulty(), + }))? + } + + // All basic checks passed, continue to next phase + Ok(()) + } + + fn verify_block_unordered(&self, _header: &Header) -> Result<(), Error> { + // Nothing to check here. + Ok(()) + } + + /// Verify block family by looking up parent state (backfill if needed), then try to apply current header. + /// see https://github.com/ethereum/go-ethereum/blob/master/consensus/clique/clique.go#L338 + fn verify_block_family(&self, header: &Header, parent: &Header) -> Result<(), Error> { + // Ignore genesis block. + if header.number() == 0 { + return Ok(()); + } + + // parent sanity check + if parent.hash() != *header.parent_hash() || header.number() != parent.number() + 1 { + Err(BlockError::UnknownParent(parent.hash()))? + } + + // Ensure that the block's timestamp isn't too close to it's parent + let limit = parent.timestamp().saturating_add(self.period); + if limit > header.timestamp() { + let max = CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::from_secs(header.timestamp())); + let found = CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::from_secs(limit)) + .ok_or(BlockError::TimestampOverflow)?; + + Err(BlockError::InvalidTimestamp(OutOfBounds { + min: None, + max, + found, + }))? + } + + // Retrieve the parent state + let parent_state = self.state(&parent)?; + // Try to apply current state, apply() will further check signer and recent signer. + let mut new_state = parent_state.clone(); + new_state.apply(header, header.number() % self.epoch_length == 0)?; + new_state.calc_next_timestamp(header.timestamp(), self.period)?; + self.block_state_by_hash.write().insert(header.hash(), new_state); + + Ok(()) + } + + fn genesis_epoch_data(&self, header: &Header, _call: &Call) -> Result, String> { + let mut state = self.new_checkpoint_state(header).expect("Unable to parse genesis data."); + state.calc_next_timestamp(header.timestamp(), self.period).map_err(|e| format!("{}", e))?; + self.block_state_by_hash.write().insert(header.hash(), state); + + // no proof. + Ok(Vec::new()) + } + + // Our task here is to set difficulty + fn populate_from_parent(&self, header: &mut Header, parent: &Header) { + // TODO(https://github.com/paritytech/parity-ethereum/issues/10410): this is a horrible hack, + // it is due to the fact that enact and miner both use OpenBlock::new() which will both call + // this function. more refactoring is definitely needed. + if header.extra_data().len() < VANITY_LENGTH + SIGNATURE_LENGTH { + trace!(target: "engine", "populate_from_parent in sealing"); + + // It's unclear how to prevent creating new blocks unless we are authorized, the best way (and geth does this too) + // it's just to ignore setting an correct difficulty here, we will check authorization in next step in generate_seal anyway. + if let Some(signer) = self.signer.read().as_ref() { + let state = match self.state(&parent) { + Err(e) => { + trace!(target: "engine", "populate_from_parent: Unable to find parent state: {}, ignored.", e); + return; + } + Ok(state) => state, + }; + + if state.is_authorized(&signer.address()) { + if state.is_inturn(header.number(), &signer.address()) { + header.set_difficulty(DIFF_INTURN); + } else { + header.set_difficulty(DIFF_NOTURN); + } + } + + let zero_padding_len = VANITY_LENGTH - header.extra_data().len(); + if zero_padding_len > 0 { + let mut resized_extra_data = header.extra_data().clone(); + resized_extra_data.resize(VANITY_LENGTH, 0); + header.set_extra_data(resized_extra_data); + } + } else { + trace!(target: "engine", "populate_from_parent: no signer registered"); + } + } + } + + fn set_signer(&self, signer: Box) { + trace!(target: "engine", "set_signer: {}", signer.address()); + *self.signer.write() = Some(signer); + } + + fn register_client(&self, client: Weak) { + *self.client.write() = Some(client.clone()); + } + + fn step(&self) { + if self.signer.read().is_some() { + if let Some(ref weak) = *self.client.read() { + if let Some(c) = weak.upgrade() { + c.update_sealing(); + } + } + } + } + + fn stop(&mut self) { + if let Some(mut s) = self.step_service.as_mut() { + Arc::get_mut(&mut s).map(|x| x.stop()); + } else { + warn!(target: "engine", "Stopping `CliqueStepService` failed requires mutable access"); + } + } + + /// Clique timestamp is set to parent + period , or current time which ever is higher. + fn open_block_header_timestamp(&self, parent_timestamp: u64) -> u64 { + let now = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap_or_default(); + cmp::max(now.as_secs() as u64, parent_timestamp.saturating_add(self.period)) + } + + fn is_timestamp_valid(&self, header_timestamp: u64, parent_timestamp: u64) -> bool { + header_timestamp >= parent_timestamp.saturating_add(self.period) + } + + fn fork_choice(&self, new: &ExtendedHeader, current: &ExtendedHeader) -> super::ForkChoice { + super::total_difficulty_fork_choice(new, current) + } + + // Clique uses the author field for voting, the real author is hidden in the `extra_data` field. + // So when executing tx's (like in `enact()`) we want to use the executive author + fn executive_author(&self, header: &Header) -> Result { + recover_creator(header) + } +} diff --git a/rpc/src/v1/helpers/accounts.rs b/ethcore/src/engines/clique/params.rs similarity index 60% rename from rpc/src/v1/helpers/accounts.rs rename to ethcore/src/engines/clique/params.rs index 544c47883c..e24edfcbac 100644 --- a/rpc/src/v1/helpers/accounts.rs +++ b/ethcore/src/engines/clique/params.rs @@ -14,14 +14,28 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use std::sync::Arc; -use ethcore::account_provider::AccountProvider; -use jsonrpc_core::Error; -use v1::helpers::errors; - -pub fn unwrap_provider(provider: &Option>) -> Result, Error> { - match *provider { - Some(ref arc) => Ok(arc.clone()), - None => Err(errors::public_unsupported(None)), +//! Clique specific parameters. + +use ethjson; + +/// `Clique` params. +pub struct CliqueParams { + /// Period as defined in EIP + pub period: u64, + /// Epoch length as defined in EIP + pub epoch: u64, +} + +impl From for CliqueParams { + fn from(p: ethjson::spec::CliqueParams) -> Self { + let period = p.period.map_or_else(|| 30000 as u64, Into::into); + let epoch = p.epoch.map_or_else(|| 15 as u64, Into::into); + + assert!(epoch > 0); + + CliqueParams { + period, + epoch, + } } } diff --git a/ethcore/src/engines/clique/step_service.rs b/ethcore/src/engines/clique/step_service.rs new file mode 100644 index 0000000000..7a4b5269d2 --- /dev/null +++ b/ethcore/src/engines/clique/step_service.rs @@ -0,0 +1,77 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + + +use std::sync::Weak; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::time::Duration; +use std::thread; +use std::sync::Arc; + +use engines::Engine; +use machine::Machine; + +/// Service that is managing the engine +pub struct StepService { + shutdown: Arc, + thread: Option>, +} + +impl StepService { + /// Start the `StepService` + pub fn start(engine: Weak>) -> Arc { + let shutdown = Arc::new(AtomicBool::new(false)); + let s = shutdown.clone(); + + let thread = thread::Builder::new() + .name("CliqueStepService".into()) + .spawn(move || { + // startup delay. + thread::sleep(Duration::from_secs(5)); + + loop { + // see if we are in shutdown. + if shutdown.load(Ordering::Acquire) { + trace!(target: "miner", "CliqueStepService: received shutdown signal!"); + break; + } + + trace!(target: "miner", "CliqueStepService: triggering sealing"); + + // Try sealing + engine.upgrade().map(|x| x.step()); + + // Yield + thread::sleep(Duration::from_millis(2000)); + } + trace!(target: "miner", "CliqueStepService: shutdown."); + }).expect("CliqueStepService thread failed"); + + Arc::new(StepService { + shutdown: s, + thread: Some(thread), + }) + } + + /// Stop the `StepService` + pub fn stop(&mut self) { + trace!(target: "miner", "CliqueStepService: shutting down."); + self.shutdown.store(true, Ordering::Release); + if let Some(t) = self.thread.take() { + t.join().expect("CliqueStepService thread panicked!"); + } + } +} diff --git a/ethcore/src/engines/clique/tests.rs b/ethcore/src/engines/clique/tests.rs new file mode 100644 index 0000000000..c7916192dd --- /dev/null +++ b/ethcore/src/engines/clique/tests.rs @@ -0,0 +1,804 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +//! Consensus tests for `PoA Clique Engine`, see http://eips.ethereum.org/EIPS/eip-225 for more information + +use block::*; +use engines::Engine; +use error::{Error, ErrorKind}; +use ethereum_types::{Address, H256}; +use ethkey::{Secret, KeyPair}; +use state_db::StateDB; +use super::*; +use test_helpers::get_temp_state_db; + +use std::sync::Arc; +use std::collections::HashMap; + +/// Possible signers +pub const SIGNER_TAGS: [char; 6] = ['A', 'B', 'C', 'D', 'E', 'F']; + +/// Clique block types +pub enum CliqueBlockType { + /// Epoch transition block must contain list of signers + Checkpoint, + /// Block with no votes + Empty, + /// Vote + Vote(VoteType), +} + +/// Clique tester +pub struct CliqueTester { + /// Mocked Clique + pub clique: Clique, + /// Mocked genesis state + pub genesis: Header, + /// StateDB + pub db: StateDB, + /// List of signers + pub signers: HashMap, +} + +impl CliqueTester { + /// Create a `Clique` tester with settings + pub fn with(epoch: u64, period: u64, initial_signers: Vec) -> Self { + assert_eq!(initial_signers.iter().all(|s| SIGNER_TAGS.contains(s)), true, + "Not all the initial signers is in SIGNER_TAGS, possible keys are 'A' ..= 'F'"); + + let clique = Clique::with_test(epoch, period); + let mut genesis = Header::default(); + let mut signers = HashMap::new(); + + let call = |_a, _b| { + unimplemented!("Clique doesn't use Engine::Call"); + }; + + let mut extra_data = vec![0; VANITY_LENGTH]; + + for &signer in SIGNER_TAGS.iter() { + let secret = Secret::from(H256::from(signer as u64)); + let keypair = KeyPair::from_secret(secret).unwrap(); + if initial_signers.contains(&signer) { + extra_data.extend(&*keypair.address()); + } + signers.insert(signer, keypair); + } + + // append dummy signature + extra_data.extend(std::iter::repeat(0).take(SIGNATURE_LENGTH)); + + genesis.set_extra_data(extra_data); + genesis.set_gas_limit(U256::from(0xa00000)); + genesis.set_difficulty(U256::from(1)); + genesis.set_seal(util::null_seal()); + + clique.genesis_epoch_data(&genesis, &call).expect("Create genesis failed"); + Self {clique, genesis, db: get_temp_state_db(), signers} + } + + /// Get difficulty for a given block + pub fn get_difficulty(&self, block_num: BlockNumber, header: &Header, signer: &Address) -> U256 { + let state = self.clique.state(header).unwrap(); + if state.is_inturn(block_num, signer) { + DIFF_INTURN + } else { + DIFF_NOTURN + } + } + + /// Get the state of a given block + // Note, this will read the cache and `will` not work with more than 128 blocks + pub fn get_state_at_block(&self, hash: &H256) -> CliqueBlockState { + self.clique.block_state_by_hash.write() + .get_mut(hash) + .expect("CliqueBlockState not found tested failed") + .clone() + } + + /// Get signers after a certain state + // This is generally used to fetch the state after a test has been executed and checked against + // the intial list of signers provided in the test + pub fn clique_signers(&self, hash: &H256) -> impl Iterator { + self.get_state_at_block(hash).signers().clone().into_iter() + } + + /// Fetches all addresses at current `block` and converts them back to `tags (char)` and sorts them + /// Addresses are supposed sorted based on address but these tests are using `tags` just for simplicity + /// and the order is not important! + pub fn into_tags>(&self, addr: T) -> Vec { + let mut tags: Vec = addr.filter_map(|addr| { + for (t, kp) in self.signers.iter() { + if addr == kp.address() { + return Some(*t) + } + } + None + }) + .collect(); + + tags.sort(); + tags + } + + /// Create a new `Clique` block and import + pub fn new_block_and_import( + &self, + block_type: CliqueBlockType, + last_header: &Header, + beneficary: Option
, + signer: char, + ) -> Result { + + let mut extra_data = vec![0; VANITY_LENGTH]; + let mut seal = util::null_seal(); + let last_hash = last_header.hash(); + + match block_type { + CliqueBlockType::Checkpoint => { + let signers = self.clique.state(&last_header).unwrap().signers().clone(); + for signer in signers { + extra_data.extend(&*signer); + } + } + CliqueBlockType::Vote(v) => seal = v.as_rlp(), + CliqueBlockType::Empty => (), + }; + + let db = self.db.boxed_clone(); + + let mut block = OpenBlock::new( + &self.clique, + Default::default(), + false, + db, + &last_header.clone(), + Arc::new(vec![last_hash]), + beneficary.unwrap_or_default(), + (3141562.into(), 31415620.into()), + extra_data, + false, + None, + ).unwrap(); + + { + let difficulty = self.get_difficulty(block.header.number(), last_header, &self.signers[&signer].address()); + let b = block.block_mut(); + b.header.set_timestamp(last_header.timestamp() + self.clique.period); + b.header.set_difficulty(difficulty); + b.header.set_seal(seal); + + let sign = ethkey::sign(self.signers[&signer].secret(), &b.header.hash()).unwrap(); + let mut extra_data = b.header.extra_data().clone(); + extra_data.extend_from_slice(&*sign); + b.header.set_extra_data(extra_data); + } + + let current_header = &block.header; + self.clique.verify_block_basic(current_header)?; + self.clique.verify_block_family(current_header, &last_header)?; + + Ok(current_header.clone()) + } +} + +#[test] +fn one_signer_with_no_votes() { + let tester = CliqueTester::with(10, 1, vec!['A']); + + let empty_block = tester.new_block_and_import(CliqueBlockType::Empty, &tester.genesis, None, 'A').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&empty_block.hash())); + assert_eq!(&tags, &['A']); +} + +#[test] +fn one_signer_two_votes() { + let tester = CliqueTester::with(10, 1, vec!['A']); + + // Add a vote for `B` signed by `A` + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &tester.genesis, + Some(tester.signers[&'B'].address()), 'A').unwrap(); + let tags = tester.into_tags(tester.clique_signers(&vote.hash())); + assert_eq!(&tags, &['A', 'B']); + + // Add a empty block signed by `B` + let empty = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'B').unwrap(); + + // Add vote for `C` signed by A but should not be accepted + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &empty, + Some(tester.signers[&'C'].address()), 'A').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&vote.hash())); + assert_eq!(&tags, &['A', 'B']); +} + +#[test] +fn two_signers_six_votes_deny_last() { + let tester = CliqueTester::with(10, 1, vec!['A', 'B']); + + let mut prev_header = tester.genesis.clone(); + + // Add two votes for `C` signed by `A` and `B` + for &signer in SIGNER_TAGS.iter().take(2) { + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &prev_header, + Some(tester.signers[&'C'].address()), signer).unwrap(); + prev_header = vote.clone(); + } + + // Add two votes for `D` signed by `A` and `B` + for &signer in SIGNER_TAGS.iter().take(2) { + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &prev_header, + Some(tester.signers[&'D'].address()), signer).unwrap(); + prev_header = vote.clone(); + } + + // Add a empty block signed by `C` + let empty = tester.new_block_and_import(CliqueBlockType::Empty, &prev_header, None, 'C').unwrap(); + prev_header = empty.clone(); + + // Add two votes for `E` signed by `A` and `B` + for &signer in SIGNER_TAGS.iter().take(2) { + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &prev_header, + Some(tester.signers[&'E'].address()), signer).unwrap(); + prev_header = vote.clone(); + } + + let tags = tester.into_tags(tester.clique_signers(&prev_header.hash())); + assert_eq!(&tags, &['A', 'B', 'C', 'D']); +} + +#[test] +fn one_signer_dropping_itself() { + let tester = CliqueTester::with(10, 1, vec!['A']); + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis, + Some(tester.signers[&'A'].address()), 'A').unwrap(); + let signers = tester.clique_signers(&vote.hash()); + assert!(signers.count() == 0); +} + +#[test] +fn two_signers_one_remove_vote_no_consensus() { + let tester = CliqueTester::with(10, 1, vec!['A', 'B']); + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis, + Some(tester.signers[&'B'].address()), 'A').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&vote.hash())); + assert_eq!(&tags, &['A', 'B']); +} + +#[test] +fn two_signers_consensus_remove_b() { + let tester = CliqueTester::with(10, 1, vec!['A', 'B']); + let first_vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis, + Some(tester.signers[&'B'].address()), 'A').unwrap(); + let second_vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &first_vote, + Some(tester.signers[&'B'].address()), 'B').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&second_vote.hash())); + assert_eq!(&tags, &['A']); +} + +#[test] +fn three_signers_consensus_remove_c() { + let tester = CliqueTester::with(10, 1, vec!['A', 'B', 'C']); + let first_vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis, + Some(tester.signers[&'C'].address()), 'A').unwrap(); + let second_vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &first_vote, + Some(tester.signers[&'C'].address()), 'B').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&second_vote.hash())); + assert_eq!(&tags, &['A', 'B']); +} + +#[test] +fn four_signers_half_no_consensus() { + let tester = CliqueTester::with(10, 1, vec!['A', 'B', 'C', 'D']); + let first_vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis, + Some(tester.signers[&'C'].address()), 'A').unwrap(); + + let second_vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &first_vote, + Some(tester.signers[&'C'].address()), 'B').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&second_vote.hash())); + assert_eq!(&tags, &['A', 'B', 'C', 'D']); +} + +#[test] +fn four_signers_three_consensus_rm() { + let tester = CliqueTester::with(10, 1, vec!['A', 'B', 'C', 'D']); + + let mut prev_header = tester.genesis.clone(); + + // Three votes to remove `D` signed by ['A', 'B', 'C'] + for signer in SIGNER_TAGS.iter().take(3) { + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &prev_header, + Some(tester.signers[&'D'].address()), *signer).unwrap(); + prev_header = vote.clone(); + } + + let tags = tester.into_tags(tester.clique_signers(&prev_header.hash())); + assert_eq!(&tags, &['A', 'B', 'C']); +} + +#[test] +fn vote_add_only_counted_once_per_signer() { + let tester = CliqueTester::with(10, 1, vec!['A', 'B']); + + // Add a vote for `C` signed by `A` + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &tester.genesis, + Some(tester.signers[&'C'].address()), 'A').unwrap(); + // Empty block signed by B` + let empty = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'B').unwrap(); + + // Add a vote for `C` signed by `A` + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &empty, + Some(tester.signers[&'C'].address()), 'A').unwrap(); + // Empty block signed by `B` + let empty = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'B').unwrap(); + + // Add a vote for `C` signed by `A` + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &empty, + Some(tester.signers[&'C'].address()), 'A').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&vote.hash())); + assert_eq!(&tags, &['A', 'B']); +} + +#[test] +fn vote_add_concurrently_is_permitted() { + let tester = CliqueTester::with(10, 1, vec!['A', 'B']); + + // Add a vote for `C` signed by `A` + let b = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &tester.genesis, + Some(tester.signers[&'C'].address()), 'A').unwrap(); + + // Empty block signed by `B` + let b = tester.new_block_and_import(CliqueBlockType::Empty, &b, None, 'B').unwrap(); + + // Add a vote for `D` signed by `A` + let b = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &b, + Some(tester.signers[&'D'].address()), 'A').unwrap(); + + // Empty block signed by `B` + let b = tester.new_block_and_import(CliqueBlockType::Empty, &b, None, 'B').unwrap(); + + // Empty block signed by `A` + let b = tester.new_block_and_import(CliqueBlockType::Empty, &b, None, 'A').unwrap(); + + // Add a vote for `D` signed by `B` + let b = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &b, + Some(tester.signers[&'D'].address()), 'B').unwrap(); + + // Empty block signed by `A` + let b = tester.new_block_and_import(CliqueBlockType::Empty, &b, None, 'A').unwrap(); + + // Add a vote for `C` signed by `B` + let b = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &b, + Some(tester.signers[&'C'].address()), 'B').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&b.hash())); + assert_eq!(&tags, &['A', 'B', 'C', 'D']); +} + +#[test] +fn vote_rm_only_counted_once_per_signer() { + let tester = CliqueTester::with(10, 1, vec!['A', 'B']); + + let mut prev_header = tester.genesis.clone(); + + for _ in 0..2 { + // Vote to remove `B` signed by `A` + let b = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &prev_header, + Some(tester.signers[&'B'].address()), 'A').unwrap(); + // Empty block signed by `B` + let b = tester.new_block_and_import(CliqueBlockType::Empty, &b, None, 'B').unwrap(); + + prev_header = b.clone(); + } + + // Add a vote for `B` signed by `A` + let b = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &prev_header, + Some(tester.signers[&'B'].address()), 'A').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&b.hash())); + assert_eq!(&tags, &['A', 'B']); +} + +#[test] +fn vote_rm_concurrently_is_permitted() { + let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C', 'D']); + + // Add a vote for `C` signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis, + Some(tester.signers[&'C'].address()), 'A').unwrap(); + + // Empty block signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'B').unwrap(); + // Empty block signed by `C` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap(); + + // Add a vote for `D` signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'D'].address()), 'A').unwrap(); + + // Empty block signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'B').unwrap(); + // Empty block signed by `C` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap(); + // Empty block signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap(); + + // Add a vote for `D` signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'D'].address()), 'B').unwrap(); + // Add a vote for `D` signed by `C` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'D'].address()), 'C').unwrap(); + + // Empty block signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap(); + // Add a vote for `C` signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'C'].address()), 'B').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&block.hash())); + assert_eq!(&tags, &['A', 'B']); +} + +#[test] +fn vote_to_rm_are_immediate_and_ensure_votes_are_rm() { + let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C']); + + // Vote to remove `B` signed by `C` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis, + Some(tester.signers[&'B'].address()), 'C').unwrap(); + // Vote to remove `C` signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'C'].address()), 'A').unwrap(); + // Vote to remove `C` signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'C'].address()), 'B').unwrap(); + // Vote to remove `B` signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'B'].address()), 'A').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&block.hash())); + assert_eq!(&tags, &['A', 'B']); +} + +#[test] +fn vote_to_rm_are_immediate_and_votes_should_be_dropped_from_kicked_signer() { + let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C']); + + // Vote to add `D` signed by `C` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &tester.genesis, + Some(tester.signers[&'D'].address()), 'C').unwrap(); + // Vote to remove `C` signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'C'].address()), 'A').unwrap(); + + // Vote to remove `C` signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'C'].address()), 'B').unwrap(); + + // Vote to add `D` signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &block, + Some(tester.signers[&'D'].address()), 'A').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&block.hash())); + assert_eq!(&tags, &['A', 'B']); +} + +#[test] +fn cascading_not_allowed() { + let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C', 'D']); + + // Vote against `C` signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis, + Some(tester.signers[&'C'].address()), 'A').unwrap(); + + // Empty block signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'B').unwrap(); + + // Empty block signed by `C` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap(); + + // Vote against `D` signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'D'].address()), 'A').unwrap(); + + // Vote against `C` signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'C'].address()), 'B').unwrap(); + + // Empty block signed by `C` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap(); + + // Empty block signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap(); + + // Vote against `D` signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'D'].address()), 'B').unwrap(); + + // Vote against `D` signed by `C` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'D'].address()), 'C').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&block.hash())); + assert_eq!(&tags, &['A', 'B', 'C']); +} + +#[test] +fn consensus_out_of_bounds_consensus_execute_on_touch() { + let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C', 'D']); + + // Vote against `C` signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis, + Some(tester.signers[&'C'].address()), 'A').unwrap(); + + // Empty block signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'B').unwrap(); + + // Empty block signed by `C` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap(); + + // Vote against `D` signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'D'].address()), 'A').unwrap(); + + // Vote against `C` signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'C'].address()), 'B').unwrap(); + + // Empty block signed by `C` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap(); + + // Empty block signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap(); + + // Vote against `D` signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'D'].address()), 'B').unwrap(); + + // Vote against `D` signed by `C` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'D'].address()), 'C').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&block.hash())); + assert_eq!(&tags, &['A', 'B', 'C'], "D should have been removed after 3/4 remove votes"); + + // Empty block signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap(); + + // Vote for `C` signed by `C` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &block, + Some(tester.signers[&'C'].address()), 'C').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&block.hash())); + assert_eq!(&tags, &['A', 'B']); +} + +#[test] +fn consensus_out_of_bounds_first_touch() { + let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C', 'D']); + + // Vote against `C` signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis, + Some(tester.signers[&'C'].address()), 'A').unwrap(); + + // Empty block signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'B').unwrap(); + + // Empty block signed by `C` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap(); + + // Vote against `D` signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'D'].address()), 'A').unwrap(); + + // Vote against `C` signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'C'].address()), 'B').unwrap(); + + // Empty block signed by `C` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap(); + + // Empty block signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap(); + + // Vote against `D` signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'D'].address()), 'B').unwrap(); + + // Vote against `D` signed by `C` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block, + Some(tester.signers[&'D'].address()), 'C').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&block.hash())); + assert_eq!(&tags, &['A', 'B', 'C']); + + // Empty block signed by `A` + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap(); + + // Vote for `C` signed by `B` + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &block, + Some(tester.signers[&'C'].address()), 'B').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&block.hash())); + assert_eq!(&tags, &['A', 'B', 'C']); +} + +#[test] +fn pending_votes_doesnt_survive_authorization_changes() { + let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C', 'D', 'E']); + + let mut prev_header = tester.genesis.clone(); + + // Vote for `F` from [`A`, `B`, `C`] + for sign in SIGNER_TAGS.iter().take(3) { + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &prev_header, + Some(tester.signers[&'F'].address()), *sign).unwrap(); + prev_header = block.clone(); + } + + let tags = tester.into_tags(tester.clique_signers(&prev_header.hash())); + assert_eq!(&tags, &['A', 'B', 'C', 'D', 'E', 'F'], "F should have been added"); + + // Vote against `F` from [`D`, `E`, `B`, `C`] + for sign in SIGNER_TAGS.iter().skip(3).chain(SIGNER_TAGS.iter().skip(1).take(2)) { + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &prev_header, + Some(tester.signers[&'F'].address()), *sign).unwrap(); + prev_header = block.clone(); + } + + let tags = tester.into_tags(tester.clique_signers(&prev_header.hash())); + assert_eq!(&tags, &['A', 'B', 'C', 'D', 'E'], "F should have been removed"); + + // Vote for `F` from [`D`, `E`] + for sign in SIGNER_TAGS.iter().skip(3).take(2) { + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &prev_header, + Some(tester.signers[&'F'].address()), *sign).unwrap(); + prev_header = block.clone(); + } + + // Vote against `A` from [`B`, `C`, `D`] + for sign in SIGNER_TAGS.iter().skip(1).take(3) { + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &prev_header, + Some(tester.signers[&'A'].address()), *sign).unwrap(); + prev_header = block.clone(); + } + + let tags = tester.into_tags(tester.clique_signers(&prev_header.hash())); + assert_eq!(&tags, &['B', 'C', 'D', 'E'], "A should have been removed"); + + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &prev_header, + Some(tester.signers[&'F'].address()), 'B').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&block.hash())); + assert_eq!(&tags, &['B', 'C', 'D', 'E', 'F'], "F should have been added again"); +} + +#[test] +fn epoch_transition_reset_all_votes() { + let tester = CliqueTester::with(3, 1, vec!['A', 'B']); + + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &tester.genesis, + Some(tester.signers[&'C'].address()), 'A').unwrap(); + + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'B').unwrap(); + let block = tester.new_block_and_import(CliqueBlockType::Checkpoint, &block, None, 'A').unwrap(); + + let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &block, + Some(tester.signers[&'C'].address()), 'B').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&block.hash())); + assert_eq!(&tags, &['A', 'B'], "Votes should have been reset after checkpoint"); +} + +#[test] +fn unauthorized_signer_should_not_be_able_to_sign_block() { + let tester = CliqueTester::with(3, 1, vec!['A']); + let err = tester.new_block_and_import(CliqueBlockType::Empty, &tester.genesis, None, 'B').unwrap_err(); + + match err.kind() { + ErrorKind::Engine(EngineError::NotAuthorized(_)) => (), + _ => assert!(true == false, "Wrong error kind"), + } +} + +#[test] +fn signer_should_not_be_able_to_sign_two_consequtive_blocks() { + let tester = CliqueTester::with(3, 1, vec!['A', 'B']); + let b = tester.new_block_and_import(CliqueBlockType::Empty, &tester.genesis, None, 'A').unwrap(); + let err = tester.new_block_and_import(CliqueBlockType::Empty, &b, None, 'A').unwrap_err(); + + match err.kind() { + ErrorKind::Engine(EngineError::CliqueTooRecentlySigned(_)) => (), + _ => assert!(true == false, "Wrong error kind"), + } +} + + +#[test] +fn recent_signers_should_not_reset_on_checkpoint() { + let tester = CliqueTester::with(3, 1, vec!['A', 'B', 'C']); + + let block = tester.new_block_and_import(CliqueBlockType::Empty, &tester.genesis, None, 'A').unwrap(); + let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'B').unwrap(); + let block = tester.new_block_and_import(CliqueBlockType::Checkpoint, &block, None, 'A').unwrap(); + + let err = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap_err(); + + match err.kind() { + ErrorKind::Engine(EngineError::CliqueTooRecentlySigned(_)) => (), + _ => assert!(true == false, "Wrong error kind"), + } +} + +// Not part of http://eips.ethereum.org/EIPS/eip-225 +#[test] +fn bonus_consensus_should_keep_track_of_votes_before_latest_per_signer() { + let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C', 'D']); + + // Add a vote for `E` signed by `A` + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &tester.genesis, + Some(tester.signers[&'E'].address()), 'A').unwrap(); + // Empty block signed by `B` + let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'B').unwrap(); + + // Empty block signed by `C` + let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'C').unwrap(); + + // Empty block signed by `D` + let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'D').unwrap(); + + // Add a vote for `F` signed by `A` + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &vote, + Some(tester.signers[&'F'].address()), 'A').unwrap(); + // Empty block signed by `C` + let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'C').unwrap(); + + // Empty block signed by `D` + let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'D').unwrap(); + + // Add a vote for `E` signed by `B` + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &vote, + Some(tester.signers[&'E'].address()), 'B').unwrap(); + // Empty block signed by `A` + let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'A').unwrap(); + + // Empty block signed by `C` + let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'C').unwrap(); + + // Empty block signed by `D` + let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'D').unwrap(); + + // Add a vote for `F` signed by `B` + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &vote, + Some(tester.signers[&'F'].address()), 'B').unwrap(); + + // Empty block signed by A` + let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'A').unwrap(); + + // Add a vote for `E` signed by `C` + let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &vote, + Some(tester.signers[&'E'].address()), 'C').unwrap(); + + let tags = tester.into_tags(tester.clique_signers(&vote.hash())); + assert_eq!(&tags, &['A', 'B', 'C', 'D', 'E']); +} diff --git a/ethcore/src/engines/clique/util.rs b/ethcore/src/engines/clique/util.rs new file mode 100644 index 0000000000..3f75289e91 --- /dev/null +++ b/ethcore/src/engines/clique/util.rs @@ -0,0 +1,115 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +use std::collections::BTreeSet; + +use engines::EngineError; +use engines::clique::{ADDRESS_LENGTH, SIGNATURE_LENGTH, VANITY_LENGTH, NULL_NONCE, NULL_MIXHASH}; +use error::Error; +use ethereum_types::{Address, H256}; +use ethkey::{public_to_address, recover as ec_recover, Signature}; +use lru_cache::LruCache; +use parking_lot::RwLock; +use rlp::encode; +use types::header::Header; + +/// How many recovered signature to cache in the memory. +pub const CREATOR_CACHE_NUM: usize = 4096; +lazy_static! { + /// key: header hash + /// value: creator address + static ref CREATOR_BY_HASH: RwLock> = RwLock::new(LruCache::new(CREATOR_CACHE_NUM)); +} + +/// Recover block creator from signature +pub fn recover_creator(header: &Header) -> Result { + // Initialization + let mut cache = CREATOR_BY_HASH.write(); + + if let Some(creator) = cache.get_mut(&header.hash()) { + return Ok(*creator); + } + + let data = header.extra_data(); + if data.len() < VANITY_LENGTH { + Err(EngineError::CliqueMissingVanity)? + } + + if data.len() < VANITY_LENGTH + SIGNATURE_LENGTH { + Err(EngineError::CliqueMissingSignature)? + } + + // Split `signed_extra data` and `signature` + let (signed_data_slice, signature_slice) = data.split_at(data.len() - SIGNATURE_LENGTH); + + // convert `&[u8]` to `[u8; 65]` + let signature = { + let mut s = [0; SIGNATURE_LENGTH]; + s.copy_from_slice(signature_slice); + s + }; + + // modify header and hash it + let unsigned_header = &mut header.clone(); + unsigned_header.set_extra_data(signed_data_slice.to_vec()); + let msg = unsigned_header.hash(); + + let pubkey = ec_recover(&Signature::from(signature), &msg)?; + let creator = public_to_address(&pubkey); + + cache.insert(header.hash(), creator.clone()); + Ok(creator) +} + +/// Extract signer list from extra_data. +/// +/// Layout of extra_data: +/// ---- +/// VANITY: 32 bytes +/// Signers: N * 32 bytes as hex encoded (20 characters) +/// Signature: 65 bytes +/// -- +pub fn extract_signers(header: &Header) -> Result, Error> { + let data = header.extra_data(); + + if data.len() <= VANITY_LENGTH + SIGNATURE_LENGTH { + Err(EngineError::CliqueCheckpointNoSigner)? + } + + // extract only the portion of extra_data which includes the signer list + let signers_raw = &data[(VANITY_LENGTH)..data.len() - (SIGNATURE_LENGTH)]; + + if signers_raw.len() % ADDRESS_LENGTH != 0 { + Err(EngineError::CliqueCheckpointInvalidSigners(signers_raw.len()))? + } + + let num_signers = signers_raw.len() / 20; + + let signers: BTreeSet
= (0..num_signers) + .map(|i| { + let start = i * ADDRESS_LENGTH; + let end = start + ADDRESS_LENGTH; + signers_raw[start..end].into() + }) + .collect(); + + Ok(signers) +} + +/// Retrieve `null_seal` +pub fn null_seal() -> Vec> { + vec![encode(&NULL_MIXHASH.to_vec()), encode(&NULL_NONCE.to_vec())] +} diff --git a/ethcore/src/engines/instant_seal.rs b/ethcore/src/engines/instant_seal.rs index 595805c199..ec6f42bc7d 100644 --- a/ethcore/src/engines/instant_seal.rs +++ b/ethcore/src/engines/instant_seal.rs @@ -15,7 +15,10 @@ // along with Parity Ethereum. If not, see . use engines::{Engine, Seal}; -use parity_machine::{Machine, Transactions, TotalScoredHeader}; +use machine::Machine; +use types::header::{Header, ExtendedHeader}; +use block::ExecutedBlock; +use std::sync::atomic::{AtomicU64, Ordering}; /// `InstantSeal` params. #[derive(Default, Debug, PartialEq)] @@ -37,22 +40,21 @@ impl From<::ethjson::spec::InstantSealParams> for InstantSealParams { pub struct InstantSeal { params: InstantSealParams, machine: M, + last_sealed_block: AtomicU64, } impl InstantSeal { /// Returns new instance of InstantSeal over the given state machine. pub fn new(params: InstantSealParams, machine: M) -> Self { InstantSeal { - params, machine, + params, + machine, + last_sealed_block: AtomicU64::new(0), } } } -impl Engine for InstantSeal - where M::LiveBlock: Transactions, - M::ExtendedHeader: TotalScoredHeader, - ::Value: Ord -{ +impl Engine for InstantSeal { fn name(&self) -> &str { "InstantSeal" } @@ -61,11 +63,23 @@ impl Engine for InstantSeal fn seals_internally(&self) -> Option { Some(true) } - fn generate_seal(&self, block: &M::LiveBlock, _parent: &M::Header) -> Seal { - if block.transactions().is_empty() { Seal::None } else { Seal::Regular(Vec::new()) } + fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal { + if !block.transactions.is_empty() { + let block_number = block.header.number(); + let last_sealed_block = self.last_sealed_block.load(Ordering::SeqCst); + // Return a regular seal if the given block is _higher_ than + // the last sealed one + if block_number > last_sealed_block { + let prev_last_sealed_block = self.last_sealed_block.compare_and_swap(last_sealed_block, block_number, Ordering::SeqCst); + if prev_last_sealed_block == last_sealed_block { + return Seal::Regular(Vec::new()) + } + } + } + Seal::None } - fn verify_local_seal(&self, _header: &M::Header) -> Result<(), M::Error> { + fn verify_local_seal(&self, _header: &Header) -> Result<(), M::Error> { Ok(()) } @@ -84,7 +98,7 @@ impl Engine for InstantSeal header_timestamp >= parent_timestamp } - fn fork_choice(&self, new: &M::ExtendedHeader, current: &M::ExtendedHeader) -> super::ForkChoice { + fn fork_choice(&self, new: &ExtendedHeader, current: &ExtendedHeader) -> super::ForkChoice { super::total_difficulty_fork_choice(new, current) } } @@ -106,9 +120,9 @@ mod tests { let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let genesis_header = spec.genesis_header(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::default(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::default(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let b = b.close_and_lock().unwrap(); - if let Seal::Regular(seal) = engine.generate_seal(b.block(), &genesis_header) { + if let Seal::Regular(seal) = engine.generate_seal(&b, &genesis_header) { assert!(b.try_seal(engine, seal).is_ok()); } } diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index deb85cd35f..5124f079db 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -18,47 +18,51 @@ mod authority_round; mod basic_authority; +mod clique; mod instant_seal; mod null_engine; -mod signer; mod validator_set; pub mod block_reward; +pub mod signer; pub use self::authority_round::AuthorityRound; pub use self::basic_authority::BasicAuthority; -pub use self::epoch::{EpochVerifier, Transition as EpochTransition}; pub use self::instant_seal::{InstantSeal, InstantSealParams}; pub use self::null_engine::NullEngine; +pub use self::signer::EngineSigner; +pub use self::clique::Clique; // TODO [ToDr] Remove re-export (#10130) pub use types::engines::ForkChoice; -pub use types::engines::epoch; +pub use types::engines::epoch::{self, Transition as EpochTransition}; use std::sync::{Weak, Arc}; use std::collections::{BTreeMap, HashMap}; use std::{fmt, error}; -use account_provider::AccountProvider; use builtin::Builtin; use vm::{EnvInfo, Schedule, CreateContractAddress, CallType, ActionValue}; use error::Error; use types::BlockNumber; -use types::header::Header; +use types::header::{Header, ExtendedHeader}; use snapshot::SnapshotComponents; use spec::CommonParams; use types::transaction::{self, UnverifiedTransaction, SignedTransaction}; -use ethkey::{Password, Signature}; -use parity_machine::{Machine, LocalizedMachine as Localized, TotalScoredHeader}; -use ethereum_types::{H256, U256, Address}; +use ethkey::{Signature}; +use machine::{self, Machine, AuxiliaryRequest, AuxiliaryData}; +use ethereum_types::{H64, H256, U256, Address}; use unexpected::{Mismatch, OutOfBounds}; use bytes::Bytes; use types::ancestry_action::AncestryAction; +use block::ExecutedBlock; /// Default EIP-210 contract code. /// As defined in https://github.com/ethereum/EIPs/pull/210 pub const DEFAULT_BLOCKHASH_CONTRACT: &'static str = "73fffffffffffffffffffffffffffffffffffffffe33141561006a5760014303600035610100820755610100810715156100455760003561010061010083050761010001555b6201000081071515610064576000356101006201000083050761020001555b5061013e565b4360003512151561008457600060405260206040f361013d565b61010060003543031315156100a857610100600035075460605260206060f361013c565b6101006000350715156100c55762010000600035430313156100c8565b60005b156100ea576101006101006000350507610100015460805260206080f361013b565b620100006000350715156101095763010000006000354303131561010c565b60005b1561012f57610100620100006000350507610200015460a052602060a0f361013a565b600060c052602060c0f35b5b5b5b5b"; +/// The number of generations back that uncles can be. +pub const MAX_UNCLE_AGE: usize = 6; /// Voting errors. #[derive(Debug)] @@ -83,12 +87,45 @@ pub enum EngineError { RequiresClient, /// Invalid engine specification or implementation. InvalidEngine, + /// Requires signer ref, but none registered. + RequiresSigner, + /// Checkpoint is missing + CliqueMissingCheckpoint(H256), + /// Missing vanity data + CliqueMissingVanity, + /// Missing signature + CliqueMissingSignature, + /// Missing signers + CliqueCheckpointNoSigner, + /// List of signers is invalid + CliqueCheckpointInvalidSigners(usize), + /// Wrong author on a checkpoint + CliqueWrongAuthorCheckpoint(Mismatch
), + /// Wrong checkpoint authors recovered + CliqueFaultyRecoveredSigners(Vec), + /// Invalid nonce (should contain vote) + CliqueInvalidNonce(H64), + /// The signer signed a block to recently + CliqueTooRecentlySigned(Address), + /// Custom + Custom(String), } impl fmt::Display for EngineError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::EngineError::*; let msg = match *self { + CliqueMissingCheckpoint(ref hash) => format!("Missing checkpoint block: {}", hash), + CliqueMissingVanity => format!("Extra data is missing vanity data"), + CliqueMissingSignature => format!("Extra data is missing signature"), + CliqueCheckpointInvalidSigners(len) => format!("Checkpoint block list was of length: {} of checkpoint but + it needs to be bigger than zero and a divisible by 20", len), + CliqueCheckpointNoSigner => format!("Checkpoint block list of signers was empty"), + CliqueInvalidNonce(ref mis) => format!("Unexpected nonce {} expected {} or {}", mis, 0_u64, u64::max_value()), + CliqueWrongAuthorCheckpoint(ref oob) => format!("Unexpected checkpoint author: {}", oob), + CliqueFaultyRecoveredSigners(ref mis) => format!("Faulty recovered signers {:?}", mis), + CliqueTooRecentlySigned(ref address) => format!("The signer: {} has signed a block too recently", address), + Custom(ref s) => s.clone(), DoubleVote(ref address) => format!("Author {} issued too many blocks.", address), NotProposer(ref mis) => format!("Author is not a current proposer: {}", mis), NotAuthorized(ref address) => format!("Signer {} is not authorized.", address), @@ -98,6 +135,7 @@ impl fmt::Display for EngineError { FailedSystemCall(ref msg) => format!("Failed to make system call: {}", msg), MalformedMessage(ref msg) => format!("Received malformed consensus message: {}", msg), RequiresClient => format!("Call requires client but none registered"), + RequiresSigner => format!("Call requires signer but none registered"), InvalidEngine => format!("Invalid engine specification or implementation"), }; @@ -118,7 +156,7 @@ pub enum Seal { Proposal(Vec), /// Regular block seal; should be part of the blockchain. Regular(Vec), - /// Engine does generate seal for this block right now. + /// Engine does not generate seal for this block right now. None, } @@ -176,8 +214,7 @@ pub type PendingTransitionStore<'a> = Fn(H256) -> Option: Send + Sync { /// Generate a proof, given the state. - // TODO: make this into an &M::StateContext - fn generate_proof<'a>(&self, state: &>::StateContext) -> Result, String>; + fn generate_proof<'a>(&self, state: &machine::Call) -> Result, String>; /// Check a proof generated elsewhere (potentially by a peer). // `engine` needed to check state proofs, while really this should // just be state machine params. @@ -217,7 +254,7 @@ impl<'a, M: Machine> ConstructedVerifier<'a, M> { /// Results of a query of whether an epoch change occurred at the given block. pub enum EpochChange { /// Cannot determine until more data is passed. - Unsure(M::AuxiliaryRequest), + Unsure(AuxiliaryRequest), /// No epoch change. No, /// The epoch will change, with proof. @@ -235,17 +272,14 @@ pub trait Engine: Sync + Send { fn machine(&self) -> &M; /// The number of additional header fields required for this engine. - fn seal_fields(&self, _header: &M::Header) -> usize { 0 } + fn seal_fields(&self, _header: &Header) -> usize { 0 } /// Additional engine-specific information for the user/developer concerning `header`. - fn extra_info(&self, _header: &M::Header) -> BTreeMap { BTreeMap::new() } + fn extra_info(&self, _header: &Header) -> BTreeMap { BTreeMap::new() } /// Maximum number of uncles a block is allowed to declare. fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 0 } - /// The number of generations back that uncles can be. - fn maximum_uncle_age(&self) -> usize { 6 } - /// Optional maximum gas limit. fn maximum_gas_limit(&self) -> Option { None } @@ -253,18 +287,21 @@ pub trait Engine: Sync + Send { /// `epoch_begin` set to true if this block kicks off an epoch. fn on_new_block( &self, - _block: &mut M::LiveBlock, + _block: &mut ExecutedBlock, _epoch_begin: bool, - _ancestry: &mut Iterator, + _ancestry: &mut Iterator, ) -> Result<(), M::Error> { Ok(()) } /// Block transformation functions, after the transactions. - fn on_close_block(&self, _block: &mut M::LiveBlock) -> Result<(), M::Error> { + fn on_close_block(&self, _block: &mut ExecutedBlock) -> Result<(), M::Error> { Ok(()) } + /// Allow mutating the header during seal generation. Currently only used by Clique. + fn on_seal_block(&self, _block: &mut ExecutedBlock) -> Result<(), Error> { Ok(()) } + /// None means that it requires external input (e.g. PoW) to seal a block. /// Some(true) means the engine is currently prime for seal generation (i.e. node is the current validator). /// Some(false) means that the node might seal internally but is not qualified now. @@ -279,7 +316,7 @@ pub trait Engine: Sync + Send { /// /// It is fine to require access to state or a full client for this function, since /// light clients do not generate seals. - fn generate_seal(&self, _block: &M::LiveBlock, _parent: &M::Header) -> Seal { Seal::None } + fn generate_seal(&self, _block: &ExecutedBlock, _parent: &Header) -> Seal { Seal::None } /// Verify a locally-generated seal of a header. /// @@ -291,25 +328,25 @@ pub trait Engine: Sync + Send { /// /// It is fine to require access to state or a full client for this function, since /// light clients do not generate seals. - fn verify_local_seal(&self, header: &M::Header) -> Result<(), M::Error>; + fn verify_local_seal(&self, header: &Header) -> Result<(), M::Error>; /// Phase 1 quick block verification. Only does checks that are cheap. Returns either a null `Ok` or a general error detailing the problem with import. /// The verification module can optionally avoid checking the seal (`check_seal`), if seal verification is disabled this method won't be called. - fn verify_block_basic(&self, _header: &M::Header) -> Result<(), M::Error> { Ok(()) } + fn verify_block_basic(&self, _header: &Header) -> Result<(), M::Error> { Ok(()) } /// Phase 2 verification. Perform costly checks such as transaction signatures. Returns either a null `Ok` or a general error detailing the problem with import. /// The verification module can optionally avoid checking the seal (`check_seal`), if seal verification is disabled this method won't be called. - fn verify_block_unordered(&self, _header: &M::Header) -> Result<(), M::Error> { Ok(()) } + fn verify_block_unordered(&self, _header: &Header) -> Result<(), M::Error> { Ok(()) } /// Phase 3 verification. Check block information against parent. Returns either a null `Ok` or a general error detailing the problem with import. - fn verify_block_family(&self, _header: &M::Header, _parent: &M::Header) -> Result<(), M::Error> { Ok(()) } + fn verify_block_family(&self, _header: &Header, _parent: &Header) -> Result<(), M::Error> { Ok(()) } /// Phase 4 verification. Verify block header against potentially external data. /// Should only be called when `register_client` has been called previously. - fn verify_block_external(&self, _header: &M::Header) -> Result<(), M::Error> { Ok(()) } + fn verify_block_external(&self, _header: &Header) -> Result<(), M::Error> { Ok(()) } /// Genesis epoch data. - fn genesis_epoch_data<'a>(&self, _header: &M::Header, _state: &>::StateContext) -> Result, String> { Ok(Vec::new()) } + fn genesis_epoch_data<'a>(&self, _header: &Header, _state: &machine::Call) -> Result, String> { Ok(Vec::new()) } /// Whether an epoch change is signalled at the given header but will require finality. /// If a change can be enacted immediately then return `No` from this function but @@ -320,7 +357,7 @@ pub trait Engine: Sync + Send { /// Return `Yes` or `No` when the answer is definitively known. /// /// Should not interact with state. - fn signals_epoch_end<'a>(&self, _header: &M::Header, _aux: >::AuxiliaryData) + fn signals_epoch_end<'a>(&self, _header: &Header, _aux: AuxiliaryData<'a>) -> EpochChange { EpochChange::No @@ -336,9 +373,9 @@ pub trait Engine: Sync + Send { /// Return optional transition proof. fn is_epoch_end( &self, - _chain_head: &M::Header, + _chain_head: &Header, _finalized: &[H256], - _chain: &Headers, + _chain: &Headers
, _transition_store: &PendingTransitionStore, ) -> Option> { None @@ -355,8 +392,8 @@ pub trait Engine: Sync + Send { /// Return optional transition proof. fn is_epoch_end_light( &self, - _chain_head: &M::Header, - _chain: &Headers, + _chain_head: &Header, + _chain: &Headers
, _transition_store: &PendingTransitionStore, ) -> Option> { None @@ -364,24 +401,20 @@ pub trait Engine: Sync + Send { /// Create an epoch verifier from validation proof and a flag indicating /// whether finality is required. - fn epoch_verifier<'a>(&self, _header: &M::Header, _proof: &'a [u8]) -> ConstructedVerifier<'a, M> { - ConstructedVerifier::Trusted(Box::new(self::epoch::NoOp)) + fn epoch_verifier<'a>(&self, _header: &Header, _proof: &'a [u8]) -> ConstructedVerifier<'a, M> { + ConstructedVerifier::Trusted(Box::new(NoOp)) } /// Populate a header's fields based on its parent's header. /// Usually implements the chain scoring rule based on weight. - fn populate_from_parent(&self, _header: &mut M::Header, _parent: &M::Header) { } + fn populate_from_parent(&self, _header: &mut Header, _parent: &Header) { } /// Handle any potential consensus messages; /// updating consensus state and potentially issuing a new one. fn handle_message(&self, _message: &[u8]) -> Result<(), EngineError> { Err(EngineError::UnexpectedMessage) } - /// Find out if the block is a proposal block and should not be inserted into the DB. - /// Takes a header of a fully verified block. - fn is_proposal(&self, _verified_header: &M::Header) -> bool { false } - - /// Register an account which signs consensus messages. - fn set_signer(&self, _account_provider: Arc, _address: Address, _password: Password) {} + /// Register a component which signs consensus messages. + fn set_signer(&self, _signer: Box) {} /// Sign using the EngineSigner, to be used for consensus tx signing. fn sign(&self, _hash: H256) -> Result { unimplemented!() } @@ -393,7 +426,7 @@ pub trait Engine: Sync + Send { fn step(&self) {} /// Stops any services that the may hold the Engine and makes it safe to drop. - fn stop(&self) {} + fn stop(&mut self) {} /// Create a factory for building snapshot chunks and restoring from them. /// Returning `None` indicates that this engine doesn't support snapshot creation. @@ -421,16 +454,21 @@ pub trait Engine: Sync + Send { /// Gather all ancestry actions. Called at the last stage when a block is committed. The Engine must guarantee that /// the ancestry exists. - fn ancestry_actions(&self, _header: &M::Header, _ancestry: &mut Iterator) -> Vec { + fn ancestry_actions(&self, _header: &Header, _ancestry: &mut Iterator) -> Vec { Vec::new() } /// Check whether the given new block is the best block, after finalization check. - fn fork_choice(&self, new: &M::ExtendedHeader, best: &M::ExtendedHeader) -> ForkChoice; + fn fork_choice(&self, new: &ExtendedHeader, best: &ExtendedHeader) -> ForkChoice; + + /// Returns author should used when executing tx's for this block. + fn executive_author(&self, header: &Header) -> Result { + Ok(*header.author()) + } } /// Check whether a given block is the best block based on the default total difficulty rule. -pub fn total_difficulty_fork_choice(new: &T, best: &T) -> ForkChoice where ::Value: Ord { +pub fn total_difficulty_fork_choice(new: &ExtendedHeader, best: &ExtendedHeader) -> ForkChoice { if new.total_score() > best.total_score() { ForkChoice::New } else { @@ -523,3 +561,29 @@ pub trait EthEngine: Engine<::machine::EthereumMachine> { // convenience wrappers for existing functions. impl EthEngine for T where T: Engine<::machine::EthereumMachine> { } + +/// Verifier for all blocks within an epoch with self-contained state. +pub trait EpochVerifier: Send + Sync { + /// Lightly verify the next block header. + /// This may not be a header belonging to a different epoch. + fn verify_light(&self, header: &Header) -> Result<(), M::Error>; + + /// Perform potentially heavier checks on the next block header. + fn verify_heavy(&self, header: &Header) -> Result<(), M::Error> { + self.verify_light(header) + } + + /// Check a finality proof against this epoch verifier. + /// Returns `Some(hashes)` if the proof proves finality of these hashes. + /// Returns `None` if the proof doesn't prove anything. + fn check_finality_proof(&self, _proof: &[u8]) -> Option> { + None + } +} + +/// Special "no-op" verifier for stateless, epoch-less engines. +pub struct NoOp; + +impl EpochVerifier for NoOp { + fn verify_light(&self, _header: &Header) -> Result<(), M::Error> { Ok(()) } +} diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index c62d372e9d..27138985ad 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -17,9 +17,10 @@ use engines::Engine; use engines::block_reward::{self, RewardKind}; use ethereum_types::U256; -use machine::WithRewards; -use parity_machine::{Header, LiveBlock, WithBalances, TotalScoredHeader}; +use machine::Machine; use types::BlockNumber; +use types::header::{Header, ExtendedHeader}; +use block::ExecutedBlock; /// Params for a null engine. #[derive(Clone, Default)] @@ -58,26 +59,23 @@ impl Default for NullEngine { } } -impl Engine for NullEngine - where M::ExtendedHeader: TotalScoredHeader, - ::Value: Ord -{ +impl Engine for NullEngine { fn name(&self) -> &str { "NullEngine" } fn machine(&self) -> &M { &self.machine } - fn on_close_block(&self, block: &mut M::LiveBlock) -> Result<(), M::Error> { + fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), M::Error> { use std::ops::Shr; - let author = *LiveBlock::header(&*block).author(); - let number = LiveBlock::header(&*block).number(); + let author = *block.header.author(); + let number = block.header.number(); let reward = self.params.block_reward; if reward == U256::zero() { return Ok(()) } - let n_uncles = LiveBlock::uncles(&*block).len(); + let n_uncles = block.uncles.len(); let mut rewards = Vec::new(); @@ -86,7 +84,7 @@ impl Engine for NullEngine rewards.push((author, RewardKind::Author, result_block_reward)); // bestow uncle rewards. - for u in LiveBlock::uncles(&*block) { + for u in &block.uncles { let uncle_author = u.author(); let result_uncle_reward = (reward * U256::from(8 + u.number() - number)).shr(3); rewards.push((*uncle_author, RewardKind::uncle(number, u.number()), result_uncle_reward)); @@ -97,7 +95,7 @@ impl Engine for NullEngine fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 2 } - fn verify_local_seal(&self, _header: &M::Header) -> Result<(), M::Error> { + fn verify_local_seal(&self, _header: &Header) -> Result<(), M::Error> { Ok(()) } @@ -105,7 +103,7 @@ impl Engine for NullEngine Some(Box::new(::snapshot::PowSnapshot::new(10000, 10000))) } - fn fork_choice(&self, new: &M::ExtendedHeader, current: &M::ExtendedHeader) -> super::ForkChoice { + fn fork_choice(&self, new: &ExtendedHeader, current: &ExtendedHeader) -> super::ForkChoice { super::total_difficulty_fork_choice(new, current) } } diff --git a/ethcore/src/engines/signer.rs b/ethcore/src/engines/signer.rs index 68a88745bc..bccaca1915 100644 --- a/ethcore/src/engines/signer.rs +++ b/ethcore/src/engines/signer.rs @@ -16,49 +16,68 @@ //! A signer used by Engines which need to sign messages. -use std::sync::Arc; use ethereum_types::{H256, Address}; -use ethkey::{Password, Signature}; -use account_provider::{self, AccountProvider}; +use ethkey::{self, Signature}; /// Everything that an Engine needs to sign messages. -pub struct EngineSigner { - account_provider: Arc, - address: Option
, - password: Option, +pub trait EngineSigner: Send + Sync { + /// Sign a consensus message hash. + fn sign(&self, hash: H256) -> Result; + + /// Signing address + fn address(&self) -> Address; } -impl Default for EngineSigner { - fn default() -> Self { - EngineSigner { - account_provider: Arc::new(AccountProvider::transient_provider()), - address: Default::default(), - password: Default::default(), - } - } +/// Creates a new `EngineSigner` from given key pair. +pub fn from_keypair(keypair: ethkey::KeyPair) -> Box { + Box::new(Signer(keypair)) } -impl EngineSigner { - /// Set up the signer to sign with given address and password. - pub fn set(&mut self, ap: Arc, address: Address, password: Password) { - self.account_provider = ap; - self.address = Some(address); - self.password = Some(password); - debug!(target: "poa", "Setting Engine signer to {}", address); - } +struct Signer(ethkey::KeyPair); - /// Sign a consensus message hash. - pub fn sign(&self, hash: H256) -> Result { - self.account_provider.sign(self.address.unwrap_or_else(Default::default), self.password.clone(), hash) +impl EngineSigner for Signer { + fn sign(&self, hash: H256) -> Result { + ethkey::sign(self.0.secret(), &hash) } - /// Signing address. - pub fn address(&self) -> Option
{ - self.address.clone() + fn address(&self) -> Address { + self.0.address() } +} - /// Check if the signing address was set. - pub fn is_some(&self) -> bool { - self.address.is_some() +#[cfg(test)] +mod test_signer { + use std::sync::Arc; + + use ethkey::Password; + use accounts::{self, AccountProvider, SignError}; + + use super::*; + + impl EngineSigner for (Arc, Address, Password) { + fn sign(&self, hash: H256) -> Result { + match self.0.sign(self.1, Some(self.2.clone()), hash) { + Err(SignError::NotUnlocked) => unreachable!(), + Err(SignError::NotFound) => Err(ethkey::Error::InvalidAddress), + Err(SignError::Hardware(err)) => { + warn!("Error using hardware wallet for engine: {:?}", err); + Err(ethkey::Error::InvalidSecret) + }, + Err(SignError::SStore(accounts::Error::EthKey(err))) => Err(err), + Err(SignError::SStore(accounts::Error::EthKeyCrypto(err))) => { + warn!("Low level crypto error: {:?}", err); + Err(ethkey::Error::InvalidSecret) + }, + Err(SignError::SStore(err)) => { + warn!("Error signing for engine: {:?}", err); + Err(ethkey::Error::InvalidSignature) + }, + Ok(ok) => Ok(ok), + } + } + + fn address(&self) -> Address { + self.1 + } } } diff --git a/ethcore/src/engines/validator_set/contract.rs b/ethcore/src/engines/validator_set/contract.rs index b13ebdd105..f0064a8c20 100644 --- a/ethcore/src/engines/validator_set/contract.rs +++ b/ethcore/src/engines/validator_set/contract.rs @@ -141,10 +141,10 @@ mod tests { use rlp::encode; use spec::Spec; use types::header::Header; - use account_provider::AccountProvider; - use miner::MinerService; + use accounts::AccountProvider; + use miner::{self, MinerService}; use types::ids::BlockId; - use test_helpers::generate_dummy_client_with_spec_and_accounts; + use test_helpers::generate_dummy_client_with_spec; use call_contract::CallContract; use client::{BlockChainClient, ChainInfo, BlockInfo}; use super::super::ValidatorSet; @@ -152,7 +152,7 @@ mod tests { #[test] fn fetches_validators() { - let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_contract, None); + let client = generate_dummy_client_with_spec(Spec::new_validator_contract); let vc = Arc::new(ValidatorContract::new("0000000000000000000000000000000000000005".parse::
().unwrap())); vc.register_client(Arc::downgrade(&client) as _); let last_hash = client.best_block_header().hash(); @@ -164,13 +164,14 @@ mod tests { fn reports_validators() { let tap = Arc::new(AccountProvider::transient_provider()); let v1 = tap.insert_account(keccak("1").into(), &"".into()).unwrap(); - let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_contract, Some(tap.clone())); + let client = generate_dummy_client_with_spec(Spec::new_validator_contract); client.engine().register_client(Arc::downgrade(&client) as _); let validator_contract = "0000000000000000000000000000000000000005".parse::
().unwrap(); // Make sure reporting can be done. client.miner().set_gas_range_target((1_000_000.into(), 1_000_000.into())); - client.miner().set_author(v1, Some("".into())).unwrap(); + let signer = Box::new((tap.clone(), v1, "".into())); + client.miner().set_author(miner::Author::Sealer(signer)); // Check a block that is a bit in future, reject it but don't report the validator. let mut header = Header::default(); diff --git a/ethcore/src/engines/validator_set/multi.rs b/ethcore/src/engines/validator_set/multi.rs index 4b3c33abac..b9ef677478 100644 --- a/ethcore/src/engines/validator_set/multi.rs +++ b/ethcore/src/engines/validator_set/multi.rs @@ -74,7 +74,7 @@ impl Multi { impl ValidatorSet for Multi { fn default_caller(&self, block_id: BlockId) -> Box { self.correct_set(block_id).map(|set| set.default_caller(block_id)) - .unwrap_or(Box::new(|_, _| Err("No validator set for given ID.".into()))) + .unwrap_or_else(|| Box::new(|_, _| Err("No validator set for given ID.".into()))) } fn on_epoch_begin(&self, _first: bool, header: &Header, call: &mut SystemCall) -> Result<(), ::error::Error> { @@ -141,7 +141,7 @@ impl ValidatorSet for Multi { *self.block_number.write() = Box::new(move |id| client .upgrade() .ok_or_else(|| "No client!".into()) - .and_then(|c| c.block_number(id).ok_or("Unknown block".into()))); + .and_then(|c| c.block_number(id).ok_or_else(|| "Unknown block".into()))); } } @@ -150,15 +150,15 @@ mod tests { use std::sync::Arc; use std::collections::BTreeMap; use hash::keccak; - use account_provider::AccountProvider; + use accounts::AccountProvider; use client::{BlockChainClient, ChainInfo, BlockInfo, ImportBlock}; use engines::EpochChange; use engines::validator_set::ValidatorSet; use ethkey::Secret; use types::header::Header; - use miner::MinerService; + use miner::{self, MinerService}; use spec::Spec; - use test_helpers::{generate_dummy_client_with_spec_and_accounts, generate_dummy_client_with_spec_and_data}; + use test_helpers::{generate_dummy_client_with_spec, generate_dummy_client_with_spec_and_data}; use types::ids::BlockId; use ethereum_types::Address; use verification::queue::kind::blocks::Unverified; @@ -171,26 +171,29 @@ mod tests { let s0: Secret = keccak("0").into(); let v0 = tap.insert_account(s0.clone(), &"".into()).unwrap(); let v1 = tap.insert_account(keccak("1").into(), &"".into()).unwrap(); - let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_multi, Some(tap)); + let client = generate_dummy_client_with_spec(Spec::new_validator_multi); client.engine().register_client(Arc::downgrade(&client) as _); // Make sure txs go through. client.miner().set_gas_range_target((1_000_000.into(), 1_000_000.into())); // Wrong signer for the first block. - client.miner().set_author(v1, Some("".into())).unwrap(); + let signer = Box::new((tap.clone(), v1, "".into())); + client.miner().set_author(miner::Author::Sealer(signer)); client.transact_contract(Default::default(), Default::default()).unwrap(); ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 0); // Right signer for the first block. - client.miner().set_author(v0, Some("".into())).unwrap(); + let signer = Box::new((tap.clone(), v0, "".into())); + client.miner().set_author(miner::Author::Sealer(signer)); ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 1); // This time v0 is wrong. client.transact_contract(Default::default(), Default::default()).unwrap(); ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 1); - client.miner().set_author(v1, Some("".into())).unwrap(); + let signer = Box::new((tap.clone(), v1, "".into())); + client.miner().set_author(miner::Author::Sealer(signer)); ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 2); // v1 is still good. diff --git a/ethcore/src/engines/validator_set/safe_contract.rs b/ethcore/src/engines/validator_set/safe_contract.rs index a5f94d4127..49d539df3f 100644 --- a/ethcore/src/engines/validator_set/safe_contract.rs +++ b/ethcore/src/engines/validator_set/safe_contract.rs @@ -445,19 +445,19 @@ mod tests { use ethereum_types::Address; use types::ids::BlockId; use spec::Spec; - use account_provider::AccountProvider; + use accounts::AccountProvider; use types::transaction::{Transaction, Action}; use client::{ChainInfo, BlockInfo, ImportBlock}; use ethkey::Secret; - use miner::MinerService; - use test_helpers::{generate_dummy_client_with_spec_and_accounts, generate_dummy_client_with_spec_and_data}; + use miner::{self, MinerService}; + use test_helpers::{generate_dummy_client_with_spec, generate_dummy_client_with_spec_and_data}; use super::super::ValidatorSet; use super::{ValidatorSafeContract, EVENT_NAME_HASH}; use verification::queue::kind::blocks::Unverified; #[test] fn fetches_validators() { - let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None); + let client = generate_dummy_client_with_spec(Spec::new_validator_safe_contract); let vc = Arc::new(ValidatorSafeContract::new("0000000000000000000000000000000000000005".parse::
().unwrap())); vc.register_client(Arc::downgrade(&client) as _); let last_hash = client.best_block_header().hash(); @@ -472,11 +472,12 @@ mod tests { let v0 = tap.insert_account(s0.clone(), &"".into()).unwrap(); let v1 = tap.insert_account(keccak("0").into(), &"".into()).unwrap(); let chain_id = Spec::new_validator_safe_contract().chain_id(); - let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, Some(tap)); + let client = generate_dummy_client_with_spec(Spec::new_validator_safe_contract); client.engine().register_client(Arc::downgrade(&client) as _); let validator_contract = "0000000000000000000000000000000000000005".parse::
().unwrap(); + let signer = Box::new((tap.clone(), v1, "".into())); - client.miner().set_author(v1, Some("".into())).unwrap(); + client.miner().set_author(miner::Author::Sealer(signer)); // Remove "1" validator. let tx = Transaction { nonce: 0.into(), @@ -504,11 +505,13 @@ mod tests { assert_eq!(client.chain_info().best_block_number, 1); // Switch to the validator that is still there. - client.miner().set_author(v0, Some("".into())).unwrap(); + let signer = Box::new((tap.clone(), v0, "".into())); + client.miner().set_author(miner::Author::Sealer(signer)); ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 2); // Switch back to the added validator, since the state is updated. - client.miner().set_author(v1, Some("".into())).unwrap(); + let signer = Box::new((tap.clone(), v1, "".into())); + client.miner().set_author(miner::Author::Sealer(signer)); let tx = Transaction { nonce: 2.into(), gas_price: 0.into(), @@ -539,7 +542,7 @@ mod tests { use types::header::Header; use types::log_entry::LogEntry; - let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None); + let client = generate_dummy_client_with_spec(Spec::new_validator_safe_contract); let engine = client.engine().clone(); let validator_contract = "0000000000000000000000000000000000000005".parse::
().unwrap(); @@ -576,7 +579,7 @@ mod tests { use types::header::Header; use engines::{EpochChange, Proof}; - let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None); + let client = generate_dummy_client_with_spec(Spec::new_validator_safe_contract); let engine = client.engine().clone(); let mut new_header = Header::default(); diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index 712a35f4be..d5aa45ba0e 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -16,6 +16,10 @@ //! General error types for use in ethcore. +// Silence: `use of deprecated item 'std::error::Error::cause': replaced by Error::source, which can support downcasting` +// https://github.com/paritytech/parity-ethereum/issues/10302 +#![allow(deprecated)] + use std::{fmt, error}; use std::time::SystemTime; @@ -25,16 +29,15 @@ use ethtrie::TrieError; use rlp; use snappy::InvalidInput; use snapshot::Error as SnapshotError; -use types::transaction::Error as TransactionError; use types::BlockNumber; +use types::transaction::Error as TransactionError; use unexpected::{Mismatch, OutOfBounds}; -use account_provider::SignError as AccountsError; use engines::EngineError; pub use executed::{ExecutionError, CallError}; -#[derive(Debug, PartialEq, Clone, Copy, Eq)] +#[derive(Debug, PartialEq, Clone, Eq)] /// Errors concerning block processing. pub enum BlockError { /// Block has too many uncles. @@ -85,7 +88,7 @@ pub enum BlockError { /// Timestamp header field is too far in future. TemporarilyInvalid(OutOfBounds), /// Log bloom header field is invalid. - InvalidLogBloom(Mismatch), + InvalidLogBloom(Box>), /// Number field of header is invalid. InvalidNumber(Mismatch), /// Block number isn't sensible. @@ -247,12 +250,6 @@ error_chain! { display("Snapshot error {}", err) } - #[doc = "Account Provider error"] - AccountProvider(err: AccountsError) { - description("Accounts Provider error") - display("Accounts Provider error {}", err) - } - #[doc = "PoW hash is invalid or out of date."] PowHashInvalid { description("PoW hash is invalid or out of date.") @@ -273,12 +270,6 @@ error_chain! { } } -impl From for Error { - fn from(err: AccountsError) -> Error { - ErrorKind::AccountProvider(err).into() - } -} - impl From for Error { fn from(err: SnapshotError) -> Error { match err { diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 5c4365cb24..698e23cf7e 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -113,6 +113,8 @@ pub struct EthashParams { pub block_reward_contract: Option, /// Difficulty bomb delays. pub difficulty_bomb_delays: BTreeMap, + /// Block to transition to progpow + pub progpow_transition: u64, } impl From for EthashParams { @@ -153,6 +155,7 @@ impl From for EthashParams { }), expip2_transition: p.expip2_transition.map_or(u64::max_value(), Into::into), expip2_duration_limit: p.expip2_duration_limit.map_or(30, Into::into), + progpow_transition: p.progpow_transition.map_or(u64::max_value(), Into::into), block_reward_contract_transition: p.block_reward_contract_transition.map_or(0, Into::into), block_reward_contract: match (p.block_reward_contract_code, p.block_reward_contract_address) { (Some(code), _) => Some(BlockRewardContract::new_from_code(Arc::new(code.into()))), @@ -182,10 +185,12 @@ impl Ethash { machine: EthereumMachine, optimize_for: T, ) -> Arc { + let progpow_transition = ethash_params.progpow_transition; + Arc::new(Ethash { ethash_params, machine, - pow: EthashManager::new(cache_dir.as_ref(), optimize_for.into()), + pow: EthashManager::new(cache_dir.as_ref(), optimize_for.into(), progpow_transition), }) } } @@ -236,17 +241,16 @@ impl Engine for Arc { /// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current). fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { use std::ops::Shr; - use parity_machine::LiveBlock; - let author = *LiveBlock::header(&*block).author(); - let number = LiveBlock::header(&*block).number(); + let author = *block.header.author(); + let number = block.header.number(); let rewards = match self.ethash_params.block_reward_contract { Some(ref c) if number >= self.ethash_params.block_reward_contract_transition => { let mut beneficiaries = Vec::new(); beneficiaries.push((author, RewardKind::Author)); - for u in LiveBlock::uncles(&*block) { + for u in &block.uncles { let uncle_author = u.author(); beneficiaries.push((*uncle_author, RewardKind::uncle(number, u.number()))); } @@ -269,7 +273,8 @@ impl Engine for Arc { let eras_rounds = self.ethash_params.ecip1017_era_rounds; let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, number); - let n_uncles = LiveBlock::uncles(&*block).len(); + //let n_uncles = LiveBlock::uncles(&*block).len(); + let n_uncles = block.uncles.len(); // Bestow block rewards. let mut result_block_reward = reward + reward.shr(5) * U256::from(n_uncles); @@ -277,7 +282,7 @@ impl Engine for Arc { rewards.push((author, RewardKind::Author, result_block_reward)); // Bestow uncle rewards. - for u in LiveBlock::uncles(&*block) { + for u in &block.uncles { let uncle_author = u.author(); let result_uncle_reward = if eras == 0 { (reward * U256::from(8 + u.number() - number)).shr(3) @@ -320,7 +325,8 @@ impl Engine for Arc { let difficulty = ethash::boundary_to_difficulty(&H256(quick_get_difficulty( &header.bare_hash().0, seal.nonce.low_u64(), - &seal.mix_hash.0 + &seal.mix_hash.0, + header.number() >= self.ethash_params.progpow_transition ))); if &difficulty < header.difficulty() { @@ -523,6 +529,7 @@ mod tests { block_reward_contract: None, block_reward_contract_transition: 0, difficulty_bomb_delays: BTreeMap::new(), + progpow_transition: u64::max_value(), } } @@ -533,9 +540,9 @@ mod tests { let genesis_header = spec.genesis_header(); let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let b = b.close().unwrap(); - assert_eq!(b.state().balance(&Address::zero()).unwrap(), U256::from_str("4563918244f40000").unwrap()); + assert_eq!(b.state.balance(&Address::zero()).unwrap(), U256::from_str("4563918244f40000").unwrap()); } #[test] @@ -582,15 +589,15 @@ mod tests { let genesis_header = spec.genesis_header(); let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let mut b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let mut b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let mut uncle = Header::new(); let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); uncle.set_author(uncle_author); b.push_uncle(uncle).unwrap(); let b = b.close().unwrap(); - assert_eq!(b.state().balance(&Address::zero()).unwrap(), "478eae0e571ba000".into()); - assert_eq!(b.state().balance(&uncle_author).unwrap(), "3cb71f51fc558000".into()); + assert_eq!(b.state.balance(&Address::zero()).unwrap(), "478eae0e571ba000".into()); + assert_eq!(b.state.balance(&uncle_author).unwrap(), "3cb71f51fc558000".into()); } #[test] @@ -600,14 +607,14 @@ mod tests { let genesis_header = spec.genesis_header(); let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap(); let b = b.close().unwrap(); let ubi_contract: Address = "00efdd5883ec628983e9063c7d969fe268bbf310".into(); let dev_contract: Address = "00756cf8159095948496617f5fb17ed95059f536".into(); - assert_eq!(b.state().balance(&Address::zero()).unwrap(), U256::from_str("d8d726b7177a80000").unwrap()); - assert_eq!(b.state().balance(&ubi_contract).unwrap(), U256::from_str("2b5e3af16b1880000").unwrap()); - assert_eq!(b.state().balance(&dev_contract).unwrap(), U256::from_str("c249fdd327780000").unwrap()); + assert_eq!(b.state.balance(&Address::zero()).unwrap(), U256::from_str("d8d726b7177a80000").unwrap()); + assert_eq!(b.state.balance(&ubi_contract).unwrap(), U256::from_str("2b5e3af16b1880000").unwrap()); + assert_eq!(b.state.balance(&dev_contract).unwrap(), U256::from_str("c249fdd327780000").unwrap()); } #[test] diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs index b7c60789a3..f66eb453ad 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/ethcore/src/ethereum/mod.rs @@ -57,9 +57,19 @@ pub fn new_poanet<'a, T: Into>>(params: T) -> Spec { load(params.into(), include_bytes!("../../res/ethereum/poacore.json")) } -/// Create a new Tobalaba mainnet chain spec. -pub fn new_tobalaba<'a, T: Into>>(params: T) -> Spec { - load(params.into(), include_bytes!("../../res/ethereum/tobalaba.json")) +/// Create a new xDai chain spec. +pub fn new_xdai<'a, T: Into>>(params: T) -> Spec { + load(params.into(), include_bytes!("../../res/ethereum/xdai.json")) +} + +/// Create a new Volta mainnet chain spec. +pub fn new_volta<'a, T: Into>>(params: T) -> Spec { + load(params.into(), include_bytes!("../../res/ethereum/volta.json")) +} + +/// Create a new EWC mainnet chain spec. +pub fn new_ewc<'a, T: Into>>(params: T) -> Spec { + load(params.into(), include_bytes!("../../res/ethereum/ewc.json")) } /// Create a new Expanse mainnet chain spec. @@ -79,21 +89,16 @@ pub fn new_ellaism<'a, T: Into>>(params: T) -> Spec { load(params.into(), include_bytes!("../../res/ethereum/ellaism.json")) } -/// Create a new Easthub mainnet chain spec. -pub fn new_easthub<'a, T: Into>>(params: T) -> Spec { - load(params.into(), include_bytes!("../../res/ethereum/easthub.json")) -} - -/// Create a new Ethereum Social mainnet chain spec. -pub fn new_social<'a, T: Into>>(params: T) -> Spec { - load(params.into(), include_bytes!("../../res/ethereum/social.json")) -} - /// Create a new MIX mainnet chain spec. pub fn new_mix<'a, T: Into>>(params: T) -> Spec { load(params.into(), include_bytes!("../../res/ethereum/mix.json")) } +/// Create a new Callisto chain spec +pub fn new_callisto<'a, T: Into>>(params: T) -> Spec { + load(params.into(), include_bytes!("../../res/ethereum/callisto.json")) +} + /// Create a new Morden testnet chain spec. pub fn new_morden<'a, T: Into>>(params: T) -> Spec { load(params.into(), include_bytes!("../../res/ethereum/morden.json")) @@ -109,16 +114,26 @@ pub fn new_kovan<'a, T: Into>>(params: T) -> Spec { load(params.into(), include_bytes!("../../res/ethereum/kovan.json")) } +/// Create a new Rinkeby testnet chain spec. +pub fn new_rinkeby<'a, T: Into>>(params: T) -> Spec { + load(params.into(), include_bytes!("../../res/ethereum/rinkeby.json")) +} + +/// Create a new Görli testnet chain spec. +pub fn new_goerli<'a, T: Into>>(params: T) -> Spec { + load(params.into(), include_bytes!("../../res/ethereum/goerli.json")) +} + +/// Create a new Kotti testnet chain spec. +pub fn new_kotti<'a, T: Into>>(params: T) -> Spec { + load(params.into(), include_bytes!("../../res/ethereum/kotti.json")) +} + /// Create a new POA Sokol testnet chain spec. pub fn new_sokol<'a, T: Into>>(params: T) -> Spec { load(params.into(), include_bytes!("../../res/ethereum/poasokol.json")) } -/// Create a new Callisto chaun spec -pub fn new_callisto<'a, T: Into>>(params: T) -> Spec { - load(params.into(), include_bytes!("../../res/ethereum/callisto.json")) -} - // For tests /// Create a new Foundation Frontier-era chain spec as though it never changes to Homestead. @@ -151,6 +166,9 @@ pub fn new_constantinople_test() -> Spec { load(None, include_bytes!("../../res/ /// Create a new Foundation St. Peter's (Contantinople Fix) era spec. pub fn new_constantinople_fix_test() -> Spec { load(None, include_bytes!("../../res/ethereum/st_peters_test.json")) } +/// Create a new Foundation Istanbul era spec. +pub fn new_istanbul_test() -> Spec { load(None, include_bytes!("../../res/ethereum/istanbul_test.json")) } + /// Create a new Musicoin-MCIP3-era spec. pub fn new_mcip3_test() -> Spec { load(None, include_bytes!("../../res/ethereum/mcip3_test.json")) } @@ -174,6 +192,9 @@ pub fn new_constantinople_test_machine() -> EthereumMachine { load_machine(inclu /// Create a new Foundation St. Peter's (Contantinople Fix) era spec. pub fn new_constantinople_fix_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/st_peters_test.json")) } +/// Create a new Foundation Istanbul era spec. +pub fn new_istanbul_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/istanbul_test.json")) } + /// Create a new Musicoin-MCIP3-era spec. pub fn new_mcip3_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/mcip3_test.json")) } diff --git a/ethcore/src/executed.rs b/ethcore/src/executed.rs index f9be002ff8..10e06fd05e 100644 --- a/ethcore/src/executed.rs +++ b/ethcore/src/executed.rs @@ -167,7 +167,7 @@ pub enum CallError { /// Couldn't find requested block's state in the chain. StatePruned, /// Couldn't find an amount of gas that didn't result in an exception. - Exceptional, + Exceptional(vm::Error), /// Corrupt state. StateCorrupt, /// Error executing. @@ -187,7 +187,7 @@ impl fmt::Display for CallError { let msg = match *self { TransactionNotFound => "Transaction couldn't be found in the chain".into(), StatePruned => "Couldn't find the transaction block's state in the chain".into(), - Exceptional => "An exception happened in the execution".into(), + Exceptional(ref e) => format!("An exception ({}) happened in the execution", e), StateCorrupt => "Stored state found to be corrupted.".into(), Execution(ref e) => format!("{}", e), }; @@ -197,4 +197,4 @@ impl fmt::Display for CallError { } /// Transaction execution result. -pub type ExecutionResult = Result; +pub type ExecutionResult = Result, ExecutionError>; diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 68d4edc794..cac6dc7638 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -33,7 +33,7 @@ use externalities::*; use trace::{self, Tracer, VMTracer}; use types::transaction::{Action, SignedTransaction}; use transaction_ext::Transaction; -use crossbeam; +use crossbeam_utils::thread; pub use executed::{Executed, ExecutionResult}; #[cfg(debug_assertions)] @@ -395,7 +395,8 @@ impl<'a> CallCreateExecutive<'a> { let default = []; let data = if let Some(ref d) = params.data { d as &[u8] } else { &default as &[u8] }; - let cost = builtin.cost(data); + // NOTE(niklasad1): block number is used by `builtin alt_bn128 ops` to enable eip1108 + let cost = builtin.cost(data, self.info.number); if cost <= params.gas { let mut builtin_out_buffer = Vec::new(); let result = { @@ -976,11 +977,18 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { if stack_depth != depth_threshold { self.call_with_stack_depth(params, substate, stack_depth, tracer, vm_tracer) } else { - crossbeam::scope(|scope| { - scope.builder().stack_size(::std::cmp::max(self.schedule.max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, local_stack_size)).spawn(move || { - self.call_with_stack_depth(params, substate, stack_depth, tracer, vm_tracer) - }).expect("Sub-thread creation cannot fail; the host might run out of resources; qed") - }).join().expect("Sub-thread never panics; qed") + thread::scope(|scope| { + let stack_size = cmp::max(self.schedule.max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, local_stack_size); + scope.builder() + .stack_size(stack_size) + .spawn(|_| { + self.call_with_stack_depth(params, substate, stack_depth, tracer, vm_tracer) + }) + .expect("Sub-thread creation cannot fail; the host might run out of resources; qed") + .join() + }) + .expect("Sub-thread never panics; qed") + .expect("Sub-thread never panics; qed") } } @@ -1060,11 +1068,18 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { if stack_depth != depth_threshold { self.create_with_stack_depth(params, substate, stack_depth, tracer, vm_tracer) } else { - crossbeam::scope(|scope| { - scope.builder().stack_size(::std::cmp::max(self.schedule.max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, local_stack_size)).spawn(move || { - self.create_with_stack_depth(params, substate, stack_depth, tracer, vm_tracer) - }).expect("Sub-thread creation cannot fail; the host might run out of resources; qed") - }).join().expect("Sub-thread never panics; qed") + thread::scope(|scope| { + let stack_size = cmp::max(self.schedule.max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, local_stack_size); + scope.builder() + .stack_size(stack_size) + .spawn(|_| { + self.create_with_stack_depth(params, substate, stack_depth, tracer, vm_tracer) + }) + .expect("Sub-thread creation cannot fail; the host might run out of resources; qed") + .join() + }) + .expect("Sub-thread never panics; qed") + .expect("Sub-thread never panics; qed") } } diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index a2f35b6ded..27ef053650 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -117,7 +117,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> { fn initial_storage_at(&self, key: &H256) -> vm::Result { if self.state.is_base_storage_root_unchanged(&self.origin_info.address)? { - self.state.checkpoint_storage_at(0, &self.origin_info.address, key).map(|v| v.unwrap_or(H256::zero())).map_err(Into::into) + self.state.checkpoint_storage_at(0, &self.origin_info.address, key).map(|v| v.unwrap_or_default()).map_err(Into::into) } else { warn!(target: "externalities", "Detected existing account {:#x} where a forced contract creation happened.", self.origin_info.address); Ok(H256::zero()) @@ -314,7 +314,11 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> } fn extcodehash(&self, address: &Address) -> vm::Result> { - Ok(self.state.code_hash(address)?) + if self.state.exists_and_not_null(address)? { + Ok(self.state.code_hash(address)?) + } else { + Ok(None) + } } fn extcodesize(&self, address: &Address) -> vm::Result> { @@ -395,6 +399,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> self.env_info } + fn chain_id(&self) -> u64 { + self.machine.params().chain_id + } + fn depth(&self) -> usize { self.depth } @@ -415,6 +423,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> self.vm_tracer.trace_prepare_execute(pc, instruction, gas_cost, mem_written, store_written) } + fn trace_failed(&mut self) { + self.vm_tracer.trace_failed(); + } + fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem: &[u8]) { self.vm_tracer.trace_executed(gas_used, stack_push, mem) } diff --git a/ethcore/src/json_tests/executive.rs b/ethcore/src/json_tests/executive.rs index cd9e8f2aec..0dae76e414 100644 --- a/ethcore/src/json_tests/executive.rs +++ b/ethcore/src/json_tests/executive.rs @@ -210,6 +210,8 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B> self.ext.env_info() } + fn chain_id(&self) -> u64 { 0 } + fn depth(&self) -> usize { 0 } diff --git a/ethcore/src/json_tests/skip.rs b/ethcore/src/json_tests/skip.rs index 06538bc2aa..b6ef9795f6 100644 --- a/ethcore/src/json_tests/skip.rs +++ b/ethcore/src/json_tests/skip.rs @@ -18,10 +18,7 @@ use ethjson; -#[cfg(all(not(test), feature = "ci-skip-tests"))] -compile_error!("ci-skip-tests can only be enabled for testing builds."); - -#[cfg(feature="ci-skip-issue")] +#[cfg(feature="ci-skip-tests")] lazy_static!{ pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = { let skip_data = include_bytes!("../../res/ethereum/tests-issues/currents.json"); @@ -29,7 +26,7 @@ lazy_static!{ }; } -#[cfg(not(feature="ci-skip-issue"))] +#[cfg(not(feature="ci-skip-tests"))] lazy_static!{ pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = { ethjson::test::SkipStates::empty() diff --git a/ethcore/src/json_tests/state.rs b/ethcore/src/json_tests/state.rs index 6f95a0bb73..c51a2c361c 100644 --- a/ethcore/src/json_tests/state.rs +++ b/ethcore/src/json_tests/state.rs @@ -18,7 +18,7 @@ use std::path::Path; use super::test_common::*; use pod_state::PodState; use trace; -use client::{EvmTestClient, EvmTestError, TransactResult}; +use client::{EvmTestClient, EvmTestError, TransactErr, TransactSuccess}; use ethjson; use types::transaction::SignedTransaction; use vm::EnvInfo; @@ -90,18 +90,18 @@ pub fn json_chain_test(json_data: &[u8], start_stop_ho flushln!("{} fail", info); failed.push(name.clone()); }, - Ok(TransactResult::Ok { state_root, .. }) if state_root != post_root => { + Ok(Ok(TransactSuccess { state_root, .. })) if state_root != post_root => { println!("{} !!! State mismatch (got: {}, expect: {}", info, state_root, post_root); flushln!("{} fail", info); failed.push(name.clone()); }, - Ok(TransactResult::Err { state_root, ref error, .. }) if state_root != post_root => { + Ok(Err(TransactErr { state_root, ref error, .. })) if state_root != post_root => { println!("{} !!! State mismatch (got: {}, expect: {}", info, state_root, post_root); println!("{} !!! Execution error: {:?}", info, error); flushln!("{} fail", info); failed.push(name.clone()); }, - Ok(TransactResult::Err { error, .. }) => { + Ok(Err(TransactErr { error, .. })) => { flushln!("{} ok ({:?})", info, error); }, Ok(_) => { @@ -178,7 +178,6 @@ mod state_tests { declare_test!{GeneralStateTest_stZeroCallsRevert, "GeneralStateTests/stZeroCallsRevert/"} declare_test!{GeneralStateTest_stZeroCallsTest, "GeneralStateTests/stZeroCallsTest/"} declare_test!{GeneralStateTest_stZeroKnowledge, "GeneralStateTests/stZeroKnowledge/"} - declare_test!{GeneralStateTest_stSStoreTest, "GeneralStateTests/stSStoreTest/"} // Attempts to send a transaction that requires more than current balance: // Tx: diff --git a/ethcore/src/json_tests/trie.rs b/ethcore/src/json_tests/trie.rs index 6d367f2083..d56490ec7e 100644 --- a/ethcore/src/json_tests/trie.rs +++ b/ethcore/src/json_tests/trie.rs @@ -18,9 +18,6 @@ use ethjson; use trie::{TrieFactory, TrieSpec}; use ethtrie::RlpCodec; use ethereum_types::H256; -use memorydb::MemoryDB; -use keccak_hasher::KeccakHasher; -use kvdb::DBValue; use super::HookType; @@ -37,7 +34,7 @@ fn test_trie(json: &[u8], trie: TrieSpec, start_stop_h for (name, test) in tests.into_iter() { start_stop_hook(&name, HookType::OnStart); - let mut memdb = MemoryDB::::new(); + let mut memdb = journaldb::new_memory_db(); let mut root = H256::default(); let mut t = factory.create(&mut memdb, &mut root); diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 2e291aecf4..4437ec6883 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -61,7 +61,8 @@ extern crate ansi_term; extern crate bn; extern crate byteorder; extern crate common_types as types; -extern crate crossbeam; +extern crate crossbeam_utils; +extern crate eip_152; extern crate ethabi; extern crate ethash; extern crate ethcore_blockchain as blockchain; @@ -73,8 +74,7 @@ extern crate ethcore_miner; extern crate ethereum_types; extern crate ethjson; extern crate ethkey; -extern crate ethstore; -extern crate hashdb; +extern crate hash_db; extern crate heapsize; extern crate itertools; extern crate journaldb; @@ -85,15 +85,14 @@ extern crate kvdb_memorydb; extern crate len_caching_lock; extern crate lru_cache; extern crate memory_cache; -extern crate memorydb; +extern crate memory_db; extern crate num; extern crate num_cpus; extern crate parity_bytes as bytes; extern crate parity_crypto; -extern crate parity_machine; extern crate parity_snappy as snappy; extern crate parking_lot; -extern crate patricia_trie as trie; +extern crate trie_db as trie; extern crate patricia_trie_ethereum as ethtrie; extern crate rand; extern crate rayon; @@ -101,12 +100,15 @@ extern crate rlp; extern crate rustc_hex; extern crate serde; extern crate stats; +extern crate time_utils; extern crate triehash_ethereum as triehash; extern crate unexpected; extern crate using_queue; extern crate vm; extern crate wasm; +#[cfg(test)] +extern crate ethcore_accounts as accounts; #[cfg(feature = "stratum")] extern crate ethcore_stratum; #[cfg(any(test, feature = "tempdir"))] @@ -115,12 +117,13 @@ extern crate tempdir; extern crate kvdb_rocksdb; #[cfg(any(test, feature = "blooms-db"))] extern crate blooms_db; - -#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))] -extern crate hardware_wallet; - -#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))] -extern crate fake_hardware_wallet as hardware_wallet; +#[cfg(any(test, feature = "env_logger"))] +extern crate env_logger; +#[cfg(test)] +extern crate rlp_compress; +#[cfg(test)] +#[macro_use] +extern crate hex_literal; #[macro_use] extern crate ethabi_derive; @@ -144,12 +147,12 @@ extern crate serde_derive; #[cfg_attr(test, macro_use)] extern crate evm; -#[cfg(any(test, feature = "env_logger"))] -extern crate env_logger; -#[cfg(test)] -extern crate rlp_compress; +#[cfg(all(test, feature = "price-info"))] +extern crate fetch; + +#[cfg(all(test, feature = "price-info"))] +extern crate parity_runtime; -pub mod account_provider; pub mod block; pub mod builtin; pub mod client; diff --git a/ethcore/src/machine.rs b/ethcore/src/machine/impls.rs similarity index 90% rename from ethcore/src/machine.rs rename to ethcore/src/machine/impls.rs index a12702e846..fca611d4e8 100644 --- a/ethcore/src/machine.rs +++ b/ethcore/src/machine/impls.rs @@ -24,11 +24,11 @@ use ethereum_types::{U256, H256, Address}; use rlp::Rlp; use types::transaction::{self, SYSTEM_ADDRESS, UNSIGNED_SENDER, UnverifiedTransaction, SignedTransaction}; use types::BlockNumber; -use types::header::{Header, ExtendedHeader}; +use types::header::Header; use vm::{CallType, ActionParams, ActionValue, ParamsType}; use vm::{EnvInfo, Schedule, CreateContractAddress}; -use block::{ExecutedBlock, IsBlock}; +use block::ExecutedBlock; use builtin::Builtin; use call_contract::CallContract; use client::BlockInfo; @@ -36,7 +36,7 @@ use error::Error; use executive::Executive; use spec::CommonParams; use state::{CleanupMode, Substate}; -use trace::{NoopTracer, NoopVMTracer, Tracer, ExecutiveTracer, RewardType, Tracing}; +use trace::{NoopTracer, NoopVMTracer}; use tx_filter::TransactionFilter; /// Parity tries to round block.gas_limit to multiple of this constant @@ -126,7 +126,7 @@ impl EthereumMachine { data: Option>, ) -> Result, Error> { let (code, code_hash) = { - let state = block.state(); + let state = &block.state; (state.code(&contract_address)?, state.code_hash(&contract_address)?) @@ -173,7 +173,7 @@ impl EthereumMachine { origin: SYSTEM_ADDRESS, gas, gas_price: 0.into(), - value: value.unwrap_or(ActionValue::Transfer(0.into())), + value: value.unwrap_or_else(|| ActionValue::Transfer(0.into())), code, code_hash, data, @@ -193,12 +193,12 @@ impl EthereumMachine { /// Push last known block hash to the state. fn push_last_hash(&self, block: &mut ExecutedBlock) -> Result<(), Error> { let params = self.params(); - if block.header().number() == params.eip210_transition { + if block.header.number() == params.eip210_transition { let state = block.state_mut(); state.init_code(¶ms.eip210_contract_address, params.eip210_contract_code.clone())?; } - if block.header().number() >= params.eip210_transition { - let parent_hash = block.header().parent_hash().clone(); + if block.header.number() >= params.eip210_transition { + let parent_hash = *block.header.parent_hash(); let _ = self.execute_as_system( block, params.eip210_contract_address, @@ -215,7 +215,7 @@ impl EthereumMachine { self.push_last_hash(block)?; if let Some(ref ethash_params) = self.ethash_extensions { - if block.header().number() == ethash_params.dao_hardfork_transition { + if block.header.number() == ethash_params.dao_hardfork_transition { let state = block.state_mut(); for child in ðash_params.dao_hardfork_accounts { let beneficiary = ðash_params.dao_hardfork_beneficiary; @@ -428,26 +428,13 @@ pub enum AuxiliaryRequest { Both, } -impl ::parity_machine::Machine for EthereumMachine { - type Header = Header; - type ExtendedHeader = ExtendedHeader; - - type LiveBlock = ExecutedBlock; +impl super::Machine for EthereumMachine { type EngineClient = ::client::EngineClient; - type AuxiliaryRequest = AuxiliaryRequest; - type AncestryAction = ::types::ancestry_action::AncestryAction; type Error = Error; -} - -impl<'a> ::parity_machine::LocalizedMachine<'a> for EthereumMachine { - type StateContext = Call<'a>; - type AuxiliaryData = AuxiliaryData<'a>; -} -impl ::parity_machine::WithBalances for EthereumMachine { fn balance(&self, live: &ExecutedBlock, address: &Address) -> Result { - live.state().balance(address).map_err(Into::into) + live.state.balance(address).map_err(Into::into) } fn add_balance(&self, live: &mut ExecutedBlock, address: &Address, amount: &U256) -> Result<(), Error> { @@ -455,37 +442,6 @@ impl ::parity_machine::WithBalances for EthereumMachine { } } -/// A state machine that uses block rewards. -pub trait WithRewards: ::parity_machine::Machine { - /// Note block rewards, traces each reward storing information about benefactor, amount and type - /// of reward. - fn note_rewards( - &self, - live: &mut Self::LiveBlock, - rewards: &[(Address, RewardType, U256)], - ) -> Result<(), Self::Error>; -} - -impl WithRewards for EthereumMachine { - fn note_rewards( - &self, - live: &mut Self::LiveBlock, - rewards: &[(Address, RewardType, U256)], - ) -> Result<(), Self::Error> { - if let Tracing::Enabled(ref mut traces) = *live.traces_mut() { - let mut tracer = ExecutiveTracer::default(); - - for &(address, ref reward_type, amount) in rewards { - tracer.trace_reward(address, amount, reward_type.clone()); - } - - traces.push(tracer.drain().into()); - } - - Ok(()) - } -} - // Try to round gas_limit a bit so that: // 1) it will still be in desired range // 2) it will be a nearest (with tendency to increase) multiple of PARITY_GAS_LIMIT_DETERMINANT @@ -518,7 +474,7 @@ mod tests { #[test] fn should_disallow_unsigned_transactions() { - let rlp = "ea80843b9aca0083015f90948921ebb5f79e9e3920abe571004d0b1d5119c154865af3107a400080038080".into(); + let rlp = "ea80843b9aca0083015f90948921ebb5f79e9e3920abe571004d0b1d5119c154865af3107a400080038080"; let transaction: UnverifiedTransaction = ::rlp::decode(&::rustc_hex::FromHex::from_hex(rlp).unwrap()).unwrap(); let spec = ::ethereum::new_ropsten_test(); let ethparams = get_default_ethash_extensions(); diff --git a/ethcore/src/machine/mod.rs b/ethcore/src/machine/mod.rs new file mode 100644 index 0000000000..882dc011a2 --- /dev/null +++ b/ethcore/src/machine/mod.rs @@ -0,0 +1,7 @@ +//! Generalization of a state machine for a consensus engine. + +mod impls; +mod traits; + +pub use self::impls::*; +pub use self::traits::*; diff --git a/ethcore/src/machine/traits.rs b/ethcore/src/machine/traits.rs new file mode 100644 index 0000000000..1523885e0e --- /dev/null +++ b/ethcore/src/machine/traits.rs @@ -0,0 +1,37 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +//! Generalization of a state machine for a consensus engine. +//! This will define traits for the header, block, and state of a blockchain. + +use ethereum_types::{U256, Address}; +use block::ExecutedBlock; + +/// Generalization of types surrounding blockchain-suitable state machines. +pub trait Machine: Send + Sync { + /// A handle to a blockchain client for this machine. + type EngineClient: ?Sized; + + /// Errors which can occur when querying or interacting with the machine. + type Error; + + /// Get the balance, in base units, associated with an account. + /// Extracts data from the live block. + fn balance(&self, live: &ExecutedBlock, address: &Address) -> Result; + + /// Increment the balance of an account in the state of the live block. + fn add_balance(&self, live: &mut ExecutedBlock, address: &Address, amount: &U256) -> Result<(), Self::Error>; +} diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 998ce62804..f31973c13c 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -23,14 +23,15 @@ use ansi_term::Colour; use bytes::Bytes; use call_contract::CallContract; use ethcore_miner::gas_pricer::GasPricer; +use ethcore_miner::local_accounts::LocalAccounts; use ethcore_miner::pool::{self, TransactionQueue, VerifiedTransaction, QueueStatus, PrioritizationStrategy}; +use ethcore_miner::service_transaction_checker::ServiceTransactionChecker; #[cfg(feature = "work-notify")] use ethcore_miner::work_notify::NotifyWork; use ethereum_types::{H256, U256, Address}; -use ethkey::Password; use io::IoChannel; use miner::pool_client::{PoolClient, CachedNonceClient, NonceCache}; -use miner; +use miner::{self, MinerService}; use parking_lot::{Mutex, RwLock}; use rayon::prelude::*; use types::transaction::{ @@ -46,13 +47,13 @@ use types::header::Header; use types::receipt::RichReceipt; use using_queue::{UsingQueue, GetAction}; -use account_provider::{AccountProvider, SignError as AccountError}; -use block::{ClosedBlock, IsBlock, SealedBlock}; +use block::{ClosedBlock, SealedBlock}; use client::{ BlockChain, ChainInfo, BlockProducer, SealedBlockImporter, Nonce, TransactionInfo, TransactionId }; use client::{BlockId, ClientIoMessage}; -use engines::{EthEngine, Seal}; +use client::traits::EngineClient; +use engines::{EthEngine, Seal, EngineSigner}; use error::{Error, ErrorKind}; use executed::ExecutionError; use executive::contract_address; @@ -197,6 +198,24 @@ pub struct AuthoringParams { pub extra_data: Bytes, } +/// Block sealing mechanism +pub enum Author { + /// Sealing block is external and we only need a reward beneficiary (i.e. PoW) + External(Address), + /// Sealing is done internally, we need a way to create signatures to seal block (i.e. PoA) + Sealer(Box), +} + +impl Author { + /// Get author's address. + pub fn address(&self) -> Address { + match *self { + Author::External(address) => address, + Author::Sealer(ref sealer) => sealer.address(), + } + } +} + struct SealingWork { queue: UsingQueue, enabled: bool, @@ -227,8 +246,9 @@ pub struct Miner { // TODO [ToDr] Arc is only required because of price updater transaction_queue: Arc, engine: Arc, - accounts: Option>, + accounts: Arc, io_channel: RwLock>>, + service_transaction_checker: Option, } impl Miner { @@ -245,16 +265,17 @@ impl Miner { } /// Creates new instance of miner Arc. - pub fn new( + pub fn new( options: MinerOptions, gas_pricer: GasPricer, spec: &Spec, - accounts: Option>, + accounts: A, ) -> Self { let limits = options.pool_limits.clone(); let verifier_options = options.pool_verification_options.clone(); let tx_queue_strategy = options.tx_queue_strategy; let nonce_cache_size = cmp::max(4096, limits.max_count / 4); + let refuse_service_transactions = options.refuse_service_transactions; Miner { sealing: Mutex::new(SealingWork { @@ -272,16 +293,21 @@ impl Miner { nonce_cache: NonceCache::new(nonce_cache_size), options, transaction_queue: Arc::new(TransactionQueue::new(limits, verifier_options, tx_queue_strategy)), - accounts, + accounts: Arc::new(accounts), engine: spec.engine.clone(), io_channel: RwLock::new(None), + service_transaction_checker: if refuse_service_transactions { + None + } else { + Some(ServiceTransactionChecker::default()) + }, } } /// Creates new instance of miner with given spec and accounts. /// /// NOTE This should be only used for tests. - pub fn new_for_tests(spec: &Spec, accounts: Option>) -> Miner { + pub fn new_for_tests(spec: &Spec, accounts: Option>) -> Miner { let minimal_gas_price = 0.into(); Miner::new(MinerOptions { pool_verification_options: pool::verifier::Options { @@ -292,7 +318,7 @@ impl Miner { }, reseal_min_period: Duration::from_secs(0), ..Default::default() - }, GasPricer::new_fixed(minimal_gas_price), spec, accounts) + }, GasPricer::new_fixed(minimal_gas_price), spec, accounts.unwrap_or_default()) } /// Sets `IoChannel` @@ -333,6 +359,11 @@ impl Miner { }); } + /// Returns ServiceTransactionChecker + pub fn service_transaction_checker(&self) -> Option { + self.service_transaction_checker.clone() + } + /// Retrieves an existing pending block iff it's not older than given block number. /// /// NOTE: This will not prepare a new pending block if it's not existing. @@ -344,7 +375,7 @@ impl Miner { .and_then(|b| { // to prevent a data race between block import and updating pending block // we allow the number to be equal. - if b.block().header().number() >= latest_block_number { + if b.header.number() >= latest_block_number { Some(f(b)) } else { None @@ -359,8 +390,8 @@ impl Miner { chain, &self.nonce_cache, &*self.engine, - self.accounts.as_ref().map(|x| &**x), - self.options.refuse_service_transactions, + &*self.accounts, + self.service_transaction_checker.as_ref(), ) } @@ -374,7 +405,7 @@ impl Miner { // Open block let (mut open_block, original_work_hash) = { let mut sealing = self.sealing.lock(); - let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.block().header().hash()); + let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.header.hash()); let best_hash = chain_info.best_block_hash; // check to see if last ClosedBlock in would_seals is actually same parent block. @@ -383,7 +414,7 @@ impl Miner { // if at least one was pushed successfully, close and enqueue new ClosedBlock; // otherwise, leave everything alone. // otherwise, author a fresh block. - let mut open_block = match sealing.queue.get_pending_if(|b| b.block().header().parent_hash() == &best_hash) { + let mut open_block = match sealing.queue.get_pending_if(|b| b.header.parent_hash() == &best_hash) { Some(old_block) => { trace!(target: "miner", "prepare_block: Already have previous work; updating and returning"); // add transactions to old_block @@ -418,7 +449,7 @@ impl Miner { let mut invalid_transactions = HashSet::new(); let mut not_allowed_transactions = HashSet::new(); let mut senders_to_penalize = HashSet::new(); - let block_number = open_block.block().header().number(); + let block_number = open_block.header.number(); let mut tx_count = 0usize; let mut skipped_transactions = 0usize; @@ -435,7 +466,7 @@ impl Miner { let max_transactions = if min_tx_gas.is_zero() { usize::max_value() } else { - MAX_SKIPPED_TRANSACTIONS.saturating_add(cmp::min(*open_block.block().header().gas_limit() / min_tx_gas, u64::max_value().into()).as_u64() as usize) + MAX_SKIPPED_TRANSACTIONS.saturating_add(cmp::min(*open_block.header.gas_limit() / min_tx_gas, u64::max_value().into()).as_u64() as usize) }; let pending: Vec> = self.transaction_queue.pending( @@ -464,7 +495,7 @@ impl Miner { let sender = transaction.sender(); // Re-verify transaction again vs current state. - let result = client.verify_signed(&transaction) + let result = client.verify_for_pending_block(&transaction, &open_block.header) .map_err(|e| e.into()) .and_then(|_| { open_block.push_transaction(transaction, None) @@ -612,13 +643,16 @@ impl Miner { } } - /// Attempts to perform internal sealing (one that does not require work) and handles the result depending on the type of Seal. + // TODO: (https://github.com/paritytech/parity-ethereum/issues/10407) + // This is only used in authority_round path, and should be refactored to merge with the other seal() path. + // Attempts to perform internal sealing (one that does not require work) and handles the result depending on the + // type of Seal. fn seal_and_import_block_internally(&self, chain: &C, block: ClosedBlock) -> bool where C: BlockChain + SealedBlockImporter, { { let sealing = self.sealing.lock(); - if block.transactions().is_empty() + if block.transactions.is_empty() && !self.forced_sealing() && Instant::now() <= sealing.next_mandatory_reseal { @@ -628,7 +662,7 @@ impl Miner { trace!(target: "miner", "seal_block_internally: attempting internal seal."); - let parent_header = match chain.block_header(BlockId::Hash(*block.header().parent_hash())) { + let parent_header = match chain.block_header(BlockId::Hash(*block.header.parent_hash())) { Some(h) => { match h.decode() { Ok(decoded_hdr) => decoded_hdr, @@ -638,7 +672,7 @@ impl Miner { None => return false, }; - match self.engine.generate_seal(block.block(), &parent_header) { + match self.engine.generate_seal(&block, &parent_header) { // Save proposal for later seal submission and broadcast it. Seal::Proposal(seal) => { trace!(target: "miner", "Received a Proposal seal."); @@ -687,11 +721,11 @@ impl Miner { /// Prepares work which has to be done to seal. fn prepare_work(&self, block: ClosedBlock, original_work_hash: Option) { let (work, is_new) = { - let block_header = block.block().header().clone(); + let block_header = block.header.clone(); let block_hash = block_header.hash(); let mut sealing = self.sealing.lock(); - let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.block().header().hash()); + let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.header.hash()); trace!( target: "miner", @@ -724,7 +758,7 @@ impl Miner { trace!( target: "miner", "prepare_work: leaving (last={:?})", - sealing.queue.peek_last_ref().map(|b| b.block().header().hash()) + sealing.queue.peek_last_ref().map(|b| b.header.hash()) ); (work, is_new) }; @@ -797,7 +831,6 @@ impl Miner { /// Prepare pending block, check whether sealing is needed, and then update sealing. fn prepare_and_update_sealing(&self, chain: &C) { - use miner::MinerService; // Make sure to do it after transaction is imported and lock is dropped. // We need to create pending block and enable sealing. @@ -827,14 +860,11 @@ impl miner::MinerService for Miner { self.params.write().extra_data = extra_data; } - fn set_author(&self, address: Address, password: Option) -> Result<(), AccountError> { - self.params.write().author = address; + fn set_author(&self, author: Author) { + self.params.write().author = author.address(); - if self.engine.seals_internally().is_some() && password.is_some() { - if let Some(ref ap) = self.accounts { - let password = password.unwrap_or_else(|| Password::from(String::new())); - // Sign test message - ap.sign(address.clone(), Some(password.clone()), Default::default())?; + if let Author::Sealer(signer) = author { + if self.engine.seals_internally().is_some() { // Enable sealing self.sealing.lock().enabled = true; // -------------------------------------------------------------------------- @@ -842,14 +872,10 @@ impl miner::MinerService for Miner { // | (some `Engine`s call `EngineClient.update_sealing()`) | // | Make sure to release the locks before calling that method. | // -------------------------------------------------------------------------- - self.engine.set_signer(ap.clone(), address, password); - Ok(()) + self.engine.set_signer(signer); } else { - warn!(target: "miner", "No account provider"); - Err(AccountError::NotFound) + warn!("Setting an EngineSigner while Engine does not require one."); } - } else { - Ok(()) } } @@ -862,6 +888,32 @@ impl miner::MinerService for Miner { self.params.read().gas_range_target.0 / 5 } + fn set_minimal_gas_price(&self, new_price: U256) -> Result { + match *self.gas_pricer.lock() { + // Binding the gas pricer to `gp` here to prevent + // a deadlock when calling recalibrate() + ref mut gp @ GasPricer::Fixed(_) => { + trace!(target: "miner", "minimal_gas_price: recalibrating fixed..."); + *gp = GasPricer::new_fixed(new_price); + + let txq = self.transaction_queue.clone(); + let mut options = self.options.pool_verification_options.clone(); + gp.recalibrate(move |gas_price| { + debug!(target: "miner", "minimal_gas_price: Got gas price! {}", gas_price); + options.minimal_gas_price = gas_price; + txq.set_verifier_options(options); + }); + + Ok(true) + }, + #[cfg(feature = "price-info")] + GasPricer::Calibrated(_) => { + let error_msg = "Can't update fixed gas price while automatic gas calibration is enabled."; + return Err(error_msg); + }, + } + } + fn import_external_transactions( &self, chain: &C, @@ -917,11 +969,12 @@ impl miner::MinerService for Miner { pending: PendingTransaction, trusted: bool ) -> Result<(), transaction::Error> { - // treat the tx as local if the option is enabled, or if we have the account + // treat the tx as local if the option is enabled, if we have the account, or if + // the account is specified as a Prioritized Local Addresses let sender = pending.sender(); let treat_as_local = trusted || !self.options.tx_queue_no_unfamiliar_locals - || self.accounts.as_ref().map(|accts| accts.has_account(sender)).unwrap_or(false); + || self.accounts.is_local(&sender); if treat_as_local { self.import_own_transaction(chain, pending) @@ -956,7 +1009,7 @@ impl miner::MinerService for Miner { let from_pending = || { self.map_existing_pending_block(|sealing| { - sealing.transactions() + sealing.transactions .iter() .map(|signed| signed.hash()) .collect() @@ -1003,7 +1056,7 @@ impl miner::MinerService for Miner { let from_pending = || { self.map_existing_pending_block(|sealing| { - sealing.transactions() + sealing.transactions .iter() .map(|signed| pool::VerifiedTransaction::from_pending_block_transaction(signed.clone())) .map(Arc::new) @@ -1048,9 +1101,9 @@ impl miner::MinerService for Miner { fn pending_receipts(&self, best_block: BlockNumber) -> Option> { self.map_existing_pending_block(|pending| { - let receipts = pending.receipts(); - pending.transactions() - .into_iter() + let receipts = &pending.receipts; + pending.transactions + .iter() .enumerate() .map(|(index, tx)| { let prev_gas = if index == 0 { Default::default() } else { receipts[index - 1].gas_used }; @@ -1064,7 +1117,7 @@ impl miner::MinerService for Miner { Action::Call(_) => None, Action::Create => { let sender = tx.sender(); - Some(contract_address(self.engine.create_address_scheme(pending.header().number()), &sender, &tx.nonce, &tx.data).0) + Some(contract_address(self.engine.create_address_scheme(pending.header.number()), &sender, &tx.nonce, &tx.data).0) } }, logs: receipt.logs.clone(), @@ -1101,10 +1154,10 @@ impl miner::MinerService for Miner { // refuse to seal the first block of the chain if it contains hard forks // which should be on by default. - if block.block().header().number() == 1 { + if block.header.number() == 1 { if let Some(name) = self.engine.params().nonzero_bugfix_hard_fork() { warn!("Your chain specification contains one or more hard forks which are required to be \ - on by default. Please remove these forks and start your chain again: {}.", name); + on by default. Please remove these forks and start your chain again: {}.", name); return; } } @@ -1142,7 +1195,7 @@ impl miner::MinerService for Miner { self.prepare_pending_block(chain); self.sealing.lock().queue.use_last_ref().map(|b| { - let header = b.header(); + let header = &b.header; (header.hash(), header.number(), header.timestamp(), *header.difficulty()) }) } @@ -1156,9 +1209,9 @@ impl miner::MinerService for Miner { } else { GetAction::Take }, - |b| &b.hash() == &block_hash + |b| &b.header.bare_hash() == &block_hash ) { - trace!(target: "miner", "Submitted block {}={}={} with seal {:?}", block_hash, b.hash(), b.header().bare_hash(), seal); + trace!(target: "miner", "Submitted block {}={} with seal {:?}", block_hash, b.header.bare_hash(), seal); b.lock().try_seal(&*self.engine, seal).or_else(|e| { warn!(target: "miner", "Mined solution rejected: {}", e); Err(ErrorKind::PowInvalid.into()) @@ -1169,8 +1222,8 @@ impl miner::MinerService for Miner { }; result.and_then(|sealed| { - let n = sealed.header().number(); - let h = sealed.header().hash(); + let n = sealed.header.number(); + let h = sealed.header.hash(); info!(target: "miner", "Submitted block imported OK. #{}: {}", Colour::White.bold().paint(format!("{}", n)), Colour::White.bold().paint(format!("{:x}", h))); Ok(sealed) }) @@ -1243,17 +1296,20 @@ impl miner::MinerService for Miner { let nonce_cache = self.nonce_cache.clone(); let engine = self.engine.clone(); let accounts = self.accounts.clone(); - let refuse_service_transactions = self.options.refuse_service_transactions; + let service_transaction_checker = self.service_transaction_checker.clone(); let cull = move |chain: &::client::Client| { let client = PoolClient::new( chain, &nonce_cache, &*engine, - accounts.as_ref().map(|x| &**x), - refuse_service_transactions, + &*accounts, + service_transaction_checker.as_ref(), ); queue.cull(client); + if is_internal_import { + chain.update_sealing(); + } }; if let Err(e) = channel.send(ClientIoMessage::execute(cull)) { @@ -1261,30 +1317,53 @@ impl miner::MinerService for Miner { } } else { self.transaction_queue.cull(client); + if is_internal_import { + self.update_sealing(chain); + } } } + if let Some(ref service_transaction_checker) = self.service_transaction_checker { + match service_transaction_checker.refresh_cache(chain) { + Ok(true) => { + trace!(target: "client", "Service transaction cache was refreshed successfully"); + }, + Ok(false) => { + trace!(target: "client", "Registrar or/and service transactions contract does not exist"); + }, + Err(e) => error!(target: "client", "Error occurred while refreshing service transaction cache: {}", e) + }; + }; } fn pending_state(&self, latest_block_number: BlockNumber) -> Option { - self.map_existing_pending_block(|b| b.state().clone(), latest_block_number) + self.map_existing_pending_block(|b| b.state.clone(), latest_block_number) } fn pending_block_header(&self, latest_block_number: BlockNumber) -> Option
{ - self.map_existing_pending_block(|b| b.header().clone(), latest_block_number) + self.map_existing_pending_block(|b| b.header.clone(), latest_block_number) } fn pending_block(&self, latest_block_number: BlockNumber) -> Option { - self.map_existing_pending_block(|b| b.to_base(), latest_block_number) + self.map_existing_pending_block(|b| { + Block { + header: b.header.clone(), + transactions: b.transactions.iter().cloned().map(Into::into).collect(), + uncles: b.uncles.to_vec(), + } + }, latest_block_number) } fn pending_transactions(&self, latest_block_number: BlockNumber) -> Option> { - self.map_existing_pending_block(|b| b.transactions().into_iter().cloned().collect(), latest_block_number) + self.map_existing_pending_block(|b| b.transactions.iter().cloned().collect(), latest_block_number) } } #[cfg(test)] mod tests { + use std::iter::FromIterator; + use super::*; + use accounts::AccountProvider; use ethkey::{Generator, Random}; use hash::keccak; use rustc_hex::FromHex; @@ -1292,7 +1371,7 @@ mod tests { use client::{TestBlockChainClient, EachBlockWith, ChainInfo, ImportSealedBlock}; use miner::{MinerService, PendingOrdering}; - use test_helpers::{generate_dummy_client, generate_dummy_client_with_spec_and_accounts}; + use test_helpers::{generate_dummy_client, generate_dummy_client_with_spec}; use types::transaction::{Transaction}; #[test] @@ -1355,7 +1434,7 @@ mod tests { }, GasPricer::new_fixed(0u64.into()), &Spec::new_test(), - None, // accounts provider + ::std::collections::HashSet::new(), // local accounts ) } @@ -1468,8 +1547,8 @@ mod tests { // given let keypair = Random.generate().unwrap(); let client = TestBlockChainClient::default(); - let account_provider = AccountProvider::transient_provider(); - account_provider.insert_account(keypair.secret().clone(), &"".into()).expect("can add accounts to the provider we just created"); + let mut local_accounts = ::std::collections::HashSet::new(); + local_accounts.insert(keypair.address()); let miner = Miner::new( MinerOptions { @@ -1478,7 +1557,7 @@ mod tests { }, GasPricer::new_fixed(0u64.into()), &Spec::new_test(), - Some(Arc::new(account_provider)), + local_accounts, ); let transaction = transaction(); let best_block = 0; @@ -1510,6 +1589,32 @@ mod tests { assert_eq!(miner.prepare_pending_block(&client), BlockPreparationStatus::NotPrepared); } + #[test] + fn should_prioritize_locals() { + let client = TestBlockChainClient::default(); + let transaction = transaction(); + let miner = Miner::new( + MinerOptions { + tx_queue_no_unfamiliar_locals: true, // should work even with this enabled + ..miner().options + }, + GasPricer::new_fixed(0u64.into()), + &Spec::new_test(), + HashSet::from_iter(vec![transaction.sender()].into_iter()), + ); + let best_block = 0; + + // Miner with sender as a known local address should prioritize transactions from that address + let res2 = miner.import_claimed_local_transaction(&client, PendingTransaction::new(transaction, None), false); + + // check to make sure the prioritized transaction is pending + assert_eq!(res2.unwrap(), ()); + assert_eq!(miner.pending_transactions(best_block).unwrap().len(), 1); + assert_eq!(miner.pending_receipts(best_block).unwrap().len(), 1); + assert_eq!(miner.ready_transactions(&client, 10, PendingOrdering::Priority).len(), 1); + assert_eq!(miner.prepare_pending_block(&client), BlockPreparationStatus::NotPrepared); + } + #[test] fn should_not_seal_unless_enabled() { let miner = miner(); @@ -1547,12 +1652,19 @@ mod tests { } #[test] - fn should_fail_setting_engine_signer_without_account_provider() { - let spec = Spec::new_instant; + fn should_not_fail_setting_engine_signer_without_account_provider() { + let spec = Spec::new_test_round; let tap = Arc::new(AccountProvider::transient_provider()); let addr = tap.insert_account(keccak("1").into(), &"".into()).unwrap(); - let client = generate_dummy_client_with_spec_and_accounts(spec, None); - assert!(match client.miner().set_author(addr, Some("".into())) { Err(AccountError::NotFound) => true, _ => false }); + let client = generate_dummy_client_with_spec(spec); + let engine_signer = Box::new((tap.clone(), addr, "".into())); + let msg = Default::default(); + assert!(client.engine().sign(msg).is_err()); + + // should set engine signer and miner author + client.miner().set_author(Author::Sealer(engine_signer)); + assert_eq!(client.miner().authoring_params().author, addr); + assert!(client.engine().sign(msg).is_ok()); } #[test] @@ -1606,4 +1718,60 @@ mod tests { assert!(miner.is_currently_sealing()); } + + #[test] + fn should_set_new_minimum_gas_price() { + // Creates a new GasPricer::Fixed behind the scenes + let miner = Miner::new_for_tests(&Spec::new_test(), None); + + let expected_minimum_gas_price: U256 = 0x1337.into(); + miner.set_minimal_gas_price(expected_minimum_gas_price).unwrap(); + + let txq_options = miner.transaction_queue.status().options; + let current_minimum_gas_price = txq_options.minimal_gas_price; + + assert!(current_minimum_gas_price == expected_minimum_gas_price); + } + + #[cfg(feature = "price-info")] + fn dynamic_gas_pricer() -> GasPricer { + use std::time::Duration; + use parity_runtime::Executor; + use fetch::Client as FetchClient; + use ethcore_miner::gas_price_calibrator::{GasPriceCalibrator, GasPriceCalibratorOptions}; + + // Don't really care about any of these settings since + // the gas pricer is never actually going to be used + let fetch = FetchClient::new(1).unwrap(); + let p = Executor::new_sync(); + + GasPricer::new_calibrated( + GasPriceCalibrator::new( + GasPriceCalibratorOptions { + usd_per_tx: 0.0, + recalibration_period: Duration::from_secs(0), + }, + fetch, + p, + ) + ) + } + + #[test] + #[cfg(feature = "price-info")] + fn should_fail_to_set_new_minimum_gas_price() { + // We get a fixed gas pricer by default, need to change that + let miner = Miner::new_for_tests(&Spec::new_test(), None); + let calibrated_gas_pricer = dynamic_gas_pricer(); + *miner.gas_pricer.lock() = calibrated_gas_pricer; + + let expected_minimum_gas_price: U256 = 0x1337.into(); + let result = miner.set_minimal_gas_price(expected_minimum_gas_price); + assert!(result.is_err()); + + let received_error_msg = result.unwrap_err(); + let expected_error_msg = "Can't update fixed gas price while automatic gas calibration is enabled."; + + assert!(received_error_msg == expected_error_msg); + } } diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 4f5ba4c1f8..fd7ab96513 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -25,7 +25,8 @@ pub mod pool_client; #[cfg(feature = "stratum")] pub mod stratum; -pub use self::miner::{Miner, MinerOptions, Penalization, PendingSet, AuthoringParams}; +pub use self::miner::{Miner, MinerOptions, Penalization, PendingSet, AuthoringParams, Author}; +pub use ethcore_miner::local_accounts::LocalAccounts; pub use ethcore_miner::pool::PendingOrdering; use std::sync::Arc; @@ -34,7 +35,6 @@ use std::collections::{BTreeSet, BTreeMap}; use bytes::Bytes; use ethcore_miner::pool::{VerifiedTransaction, QueueStatus, local_transactions}; use ethereum_types::{H256, U256, Address}; -use ethkey::Password; use types::transaction::{self, UnverifiedTransaction, SignedTransaction, PendingTransaction}; use types::BlockNumber; use types::block::Block; @@ -130,8 +130,8 @@ pub trait MinerService : Send + Sync { /// Set info necessary to sign consensus messages and block authoring. /// - /// On PoW password is optional. - fn set_author(&self, address: Address, password: Option) -> Result<(), ::account_provider::SignError>; + /// On chains where sealing is done externally (e.g. PoW) we provide only reward beneficiary. + fn set_author(&self, author: Author); // Transaction Pool @@ -205,4 +205,8 @@ pub trait MinerService : Send + Sync { /// Suggested gas limit. fn sensible_gas_limit(&self) -> U256; + + /// Set a new minimum gas limit. + /// Will not work if dynamic gas calibration is set. + fn set_minimal_gas_price(&self, gas_price: U256) -> Result; } diff --git a/ethcore/src/miner/pool_client.rs b/ethcore/src/miner/pool_client.rs index a75454a3fd..93cc0e8cfb 100644 --- a/ethcore/src/miner/pool_client.rs +++ b/ethcore/src/miner/pool_client.rs @@ -23,6 +23,7 @@ use std::{ }; use ethereum_types::{H256, U256, Address}; +use ethcore_miner::local_accounts::LocalAccounts; use ethcore_miner::pool; use ethcore_miner::pool::client::NonceClient; use ethcore_miner::service_transaction_checker::ServiceTransactionChecker; @@ -34,7 +35,6 @@ use types::transaction::{ use types::header::Header; use parking_lot::RwLock; -use account_provider::AccountProvider; use call_contract::CallContract; use client::{TransactionId, BlockInfo, Nonce}; use engines::EthEngine; @@ -73,9 +73,9 @@ pub struct PoolClient<'a, C: 'a> { chain: &'a C, cached_nonces: CachedNonceClient<'a, C>, engine: &'a EthEngine, - accounts: Option<&'a AccountProvider>, + accounts: &'a LocalAccounts, best_block_header: Header, - service_transaction_checker: Option, + service_transaction_checker: Option<&'a ServiceTransactionChecker>, } impl<'a, C: 'a> Clone for PoolClient<'a, C> { @@ -92,15 +92,15 @@ impl<'a, C: 'a> Clone for PoolClient<'a, C> { } impl<'a, C: 'a> PoolClient<'a, C> where -C: BlockInfo + CallContract, + C: BlockInfo + CallContract, { /// Creates new client given chain, nonce cache, accounts and service transaction verifier. pub fn new( chain: &'a C, cache: &'a NonceCache, engine: &'a EthEngine, - accounts: Option<&'a AccountProvider>, - refuse_service_transactions: bool, + accounts: &'a LocalAccounts, + service_transaction_checker: Option<&'a ServiceTransactionChecker>, ) -> Self { let best_block_header = chain.best_block_header(); PoolClient { @@ -109,19 +109,17 @@ C: BlockInfo + CallContract, engine, accounts, best_block_header, - service_transaction_checker: if refuse_service_transactions { - None - } else { - Some(Default::default()) - }, + service_transaction_checker, } } - /// Verifies if signed transaction is executable. + /// Verifies transaction against its block (before its import into this block) + /// Also Verifies if signed transaction is executable. /// /// This should perform any verifications that rely on chain status. - pub fn verify_signed(&self, tx: &SignedTransaction) -> Result<(), transaction::Error> { - self.engine.machine().verify_transaction(&tx, &self.best_block_header, self.chain) + pub fn verify_for_pending_block(&self, tx: &SignedTransaction, header: &Header) -> Result<(), transaction::Error> { + self.engine.machine().verify_transaction_basic(tx, header)?; + self.engine.machine().verify_transaction(tx, &self.best_block_header, self.chain) } } @@ -142,8 +140,7 @@ impl<'a, C: 'a> pool::client::Client for PoolClient<'a, C> where self.engine.verify_transaction_basic(&tx, &self.best_block_header)?; let tx = self.engine.verify_transaction_unordered(tx, &self.best_block_header)?; - self.verify_signed(&tx)?; - + self.engine.machine().verify_transaction(&tx, &self.best_block_header, self.chain)?; Ok(tx) } @@ -151,7 +148,7 @@ impl<'a, C: 'a> pool::client::Client for PoolClient<'a, C> where pool::client::AccountDetails { nonce: self.cached_nonces.account_nonce(address), balance: self.chain.latest_balance(address), - is_local: self.accounts.map_or(false, |accounts| accounts.has_account(*address)), + is_local: self.accounts.is_local(address), } } diff --git a/ethcore/src/pod_account.rs b/ethcore/src/pod_account.rs index 9f5f3a237b..39dce6e36d 100644 --- a/ethcore/src/pod_account.rs +++ b/ethcore/src/pod_account.rs @@ -21,7 +21,7 @@ use std::collections::BTreeMap; use itertools::Itertools; use hash::{keccak}; use ethereum_types::{H256, U256}; -use hashdb::HashDB; +use hash_db::HashDB; use kvdb::DBValue; use keccak_hasher::KeccakHasher; use triehash::sec_trie_root; diff --git a/ethcore/src/snapshot/account.rs b/ethcore/src/snapshot/account.rs index 81e4d4a0e2..2a9ac911f1 100644 --- a/ethcore/src/snapshot/account.rs +++ b/ethcore/src/snapshot/account.rs @@ -22,11 +22,12 @@ use bytes::Bytes; use ethereum_types::{H256, U256}; use ethtrie::{TrieDB, TrieDBMut}; use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP}; -use hashdb::HashDB; +use hash_db::HashDB; use rlp::{RlpStream, Rlp}; -use snapshot::Error; +use snapshot::{Error, Progress}; use std::collections::HashSet; use trie::{Trie, TrieMut}; +use std::sync::atomic::Ordering; // An empty account -- these were replaced with RLP null data for a space optimization in v1. const ACC_EMPTY: BasicAccount = BasicAccount { @@ -65,8 +66,17 @@ impl CodeState { // walk the account's storage trie, returning a vector of RLP items containing the // account address hash, account properties and the storage. Each item contains at most `max_storage_items` // storage records split according to snapshot format definition. -pub fn to_fat_rlps(account_hash: &H256, acc: &BasicAccount, acct_db: &AccountDB, used_code: &mut HashSet, first_chunk_size: usize, max_chunk_size: usize) -> Result, Error> { - let db = TrieDB::new(acct_db, &acc.storage_root)?; +pub fn to_fat_rlps( + account_hash: &H256, + acc: &BasicAccount, + acct_db: &AccountDB, + used_code: &mut HashSet, + first_chunk_size: usize, + max_chunk_size: usize, + p: &Progress, +) -> Result, Error> { + let db = &(acct_db as &dyn HashDB<_,_>); + let db = TrieDB::new(db, &acc.storage_root)?; let mut chunks = Vec::new(); let mut db_iter = db.iter()?; let mut target_chunk_size = first_chunk_size; @@ -77,7 +87,7 @@ pub fn to_fat_rlps(account_hash: &H256, acc: &BasicAccount, acct_db: &AccountDB, account_stream.begin_list(5); account_stream.append(&acc.nonce) - .append(&acc.balance); + .append(&acc.balance); // [has_code, code_hash]. if acc.code_hash == KECCAK_EMPTY { @@ -111,6 +121,10 @@ pub fn to_fat_rlps(account_hash: &H256, acc: &BasicAccount, acct_db: &AccountDB, } loop { + if p.abort.load(Ordering::SeqCst) { + trace!(target: "snapshot", "to_fat_rlps: aborting snapshot"); + return Err(Error::SnapshotAborted); + } match db_iter.next() { Some(Ok((k, v))) => { let pair = { @@ -187,7 +201,7 @@ pub fn from_fat_rlp( }; let pairs = rlp.at(4)?; for pair_rlp in pairs.iter() { - let k: Bytes = pair_rlp.val_at(0)?; + let k: Bytes = pair_rlp.val_at(0)?; let v: Bytes = pair_rlp.val_at(1)?; storage_trie.insert(&k, &v)?; @@ -210,10 +224,11 @@ mod tests { use types::basic_account::BasicAccount; use test_helpers::get_temp_state_db; use snapshot::tests::helpers::fill_storage; + use snapshot::Progress; use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP, keccak}; use ethereum_types::{H256, Address}; - use hashdb::HashDB; + use hash_db::HashDB; use kvdb::DBValue; use rlp::Rlp; @@ -235,10 +250,10 @@ mod tests { let thin_rlp = ::rlp::encode(&account); assert_eq!(::rlp::decode::(&thin_rlp).unwrap(), account); - - let fat_rlps = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap(); + let p = Progress::default(); + let fat_rlps = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hash_db(), &addr), &mut Default::default(), usize::max_value(), usize::max_value(), &p).unwrap(); let fat_rlp = Rlp::new(&fat_rlps[0]).at(1).unwrap(); - assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account); + assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account); } #[test] @@ -247,7 +262,7 @@ mod tests { let addr = Address::random(); let account = { - let acct_db = AccountDBMut::new(db.as_hashdb_mut(), &addr); + let acct_db = AccountDBMut::new(db.as_hash_db_mut(), &addr); let mut root = KECCAK_NULL_RLP; fill_storage(acct_db, &mut root, &mut H256::zero()); BasicAccount { @@ -261,9 +276,11 @@ mod tests { let thin_rlp = ::rlp::encode(&account); assert_eq!(::rlp::decode::(&thin_rlp).unwrap(), account); - let fat_rlp = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap(); + let p = Progress::default(); + + let fat_rlp = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hash_db(), &addr), &mut Default::default(), usize::max_value(), usize::max_value(), &p).unwrap(); let fat_rlp = Rlp::new(&fat_rlp[0]).at(1).unwrap(); - assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account); + assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account); } #[test] @@ -272,7 +289,7 @@ mod tests { let addr = Address::random(); let account = { - let acct_db = AccountDBMut::new(db.as_hashdb_mut(), &addr); + let acct_db = AccountDBMut::new(db.as_hash_db_mut(), &addr); let mut root = KECCAK_NULL_RLP; fill_storage(acct_db, &mut root, &mut H256::zero()); BasicAccount { @@ -286,12 +303,13 @@ mod tests { let thin_rlp = ::rlp::encode(&account); assert_eq!(::rlp::decode::(&thin_rlp).unwrap(), account); - let fat_rlps = to_fat_rlps(&keccak(addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), 500, 1000).unwrap(); + let p = Progress::default(); + let fat_rlps = to_fat_rlps(&keccak(addr), &account, &AccountDB::new(db.as_hash_db(), &addr), &mut Default::default(), 500, 1000, &p).unwrap(); let mut root = KECCAK_NULL_RLP; let mut restored_account = None; for rlp in fat_rlps { let fat_rlp = Rlp::new(&rlp).at(1).unwrap(); - restored_account = Some(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp, root).unwrap().0); + restored_account = Some(from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &addr), fat_rlp, root).unwrap().0); root = restored_account.as_ref().unwrap().storage_root.clone(); } assert_eq!(restored_account, Some(account)); @@ -305,12 +323,12 @@ mod tests { let addr2 = Address::random(); let code_hash = { - let mut acct_db = AccountDBMut::new(db.as_hashdb_mut(), &addr1); + let mut acct_db = AccountDBMut::new(db.as_hash_db_mut(), &addr1); acct_db.insert(b"this is definitely code") }; { - let mut acct_db = AccountDBMut::new(db.as_hashdb_mut(), &addr2); + let mut acct_db = AccountDBMut::new(db.as_hash_db_mut(), &addr2); acct_db.emplace(code_hash.clone(), DBValue::from_slice(b"this is definitely code")); } @@ -318,30 +336,31 @@ mod tests { nonce: 50.into(), balance: 123456789.into(), storage_root: KECCAK_NULL_RLP, - code_hash: code_hash, + code_hash, }; let account2 = BasicAccount { nonce: 400.into(), balance: 98765432123456789usize.into(), storage_root: KECCAK_NULL_RLP, - code_hash: code_hash, + code_hash, }; let mut used_code = HashSet::new(); - - let fat_rlp1 = to_fat_rlps(&keccak(&addr1), &account1, &AccountDB::new(db.as_hashdb(), &addr1), &mut used_code, usize::max_value(), usize::max_value()).unwrap(); - let fat_rlp2 = to_fat_rlps(&keccak(&addr2), &account2, &AccountDB::new(db.as_hashdb(), &addr2), &mut used_code, usize::max_value(), usize::max_value()).unwrap(); + let p1 = Progress::default(); + let p2 = Progress::default(); + let fat_rlp1 = to_fat_rlps(&keccak(&addr1), &account1, &AccountDB::new(db.as_hash_db(), &addr1), &mut used_code, usize::max_value(), usize::max_value(), &p1).unwrap(); + let fat_rlp2 = to_fat_rlps(&keccak(&addr2), &account2, &AccountDB::new(db.as_hash_db(), &addr2), &mut used_code, usize::max_value(), usize::max_value(), &p2).unwrap(); assert_eq!(used_code.len(), 1); let fat_rlp1 = Rlp::new(&fat_rlp1[0]).at(1).unwrap(); let fat_rlp2 = Rlp::new(&fat_rlp2[0]).at(1).unwrap(); - let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr2), fat_rlp2, H256::zero()).unwrap(); + let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &addr2), fat_rlp2, H256::zero()).unwrap(); assert!(maybe_code.is_none()); assert_eq!(acc, account2); - let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr1), fat_rlp1, H256::zero()).unwrap(); + let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &addr1), fat_rlp1, H256::zero()).unwrap(); assert_eq!(maybe_code, Some(b"this is definitely code".to_vec())); assert_eq!(acc, account1); } @@ -349,6 +368,6 @@ mod tests { #[test] fn encoding_empty_acc() { let mut db = get_temp_state_db(); - assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &Address::default()), Rlp::new(&::rlp::NULL_RLP), H256::zero()).unwrap(), (ACC_EMPTY, None)); + assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hash_db_mut(), &Address::zero()), Rlp::new(&::rlp::NULL_RLP), H256::zero()).unwrap(), (ACC_EMPTY, None)); } } diff --git a/ethcore/src/snapshot/consensus/authority.rs b/ethcore/src/snapshot/consensus/authority.rs index 909e00281c..4423e07401 100644 --- a/ethcore/src/snapshot/consensus/authority.rs +++ b/ethcore/src/snapshot/consensus/authority.rs @@ -76,7 +76,7 @@ impl SnapshotComponents for PoaSnapshot { } let header = chain.block_header_data(&transition.block_hash) - .ok_or(Error::BlockNotFound(transition.block_hash))?; + .ok_or_else(|| Error::BlockNotFound(transition.block_hash))?; let entry = { let mut entry_stream = RlpStream::new_list(2); @@ -101,12 +101,12 @@ impl SnapshotComponents for PoaSnapshot { let (block, receipts) = chain.block(&block_at) .and_then(|b| chain.block_receipts(&block_at).map(|r| (b, r))) - .ok_or(Error::BlockNotFound(block_at))?; + .ok_or_else(|| Error::BlockNotFound(block_at))?; let block = block.decode()?; let parent_td = chain.block_details(block.header.parent_hash()) .map(|d| d.total_difficulty) - .ok_or(Error::BlockNotFound(block_at))?; + .ok_or_else(|| Error::BlockNotFound(block_at))?; rlps.push({ let mut stream = RlpStream::new_list(5); diff --git a/ethcore/src/snapshot/consensus/work.rs b/ethcore/src/snapshot/consensus/work.rs index 0293d1a2fd..106fe4474c 100644 --- a/ethcore/src/snapshot/consensus/work.rs +++ b/ethcore/src/snapshot/consensus/work.rs @@ -116,7 +116,7 @@ impl<'a> PowWorker<'a> { let (block, receipts) = self.chain.block(&self.current_hash) .and_then(|b| self.chain.block_receipts(&self.current_hash).map(|r| (b, r))) - .ok_or(Error::BlockNotFound(self.current_hash))?; + .ok_or_else(|| Error::BlockNotFound(self.current_hash))?; let abridged_rlp = AbridgedBlock::from_block_view(&block.view()).into_inner(); @@ -160,7 +160,7 @@ impl<'a> PowWorker<'a> { let (last_header, last_details) = self.chain.block_header_data(&last) .and_then(|n| self.chain.block_details(&last).map(|d| (n, d))) - .ok_or(Error::BlockNotFound(last))?; + .ok_or_else(|| Error::BlockNotFound(last))?; let parent_number = last_header.number() - 1; let parent_hash = last_header.parent_hash(); diff --git a/ethcore/src/snapshot/error.rs b/ethcore/src/snapshot/error.rs index b71f79f805..6faa19da22 100644 --- a/ethcore/src/snapshot/error.rs +++ b/ethcore/src/snapshot/error.rs @@ -61,6 +61,8 @@ pub enum Error { ChunkTooLarge, /// Snapshots not supported by the consensus engine. SnapshotsUnsupported, + /// Aborted snapshot + SnapshotAborted, /// Bad epoch transition. BadEpochProof(u64), /// Wrong chunk format. @@ -91,6 +93,7 @@ impl fmt::Display for Error { Error::ChunkTooSmall => write!(f, "Chunk size is too small."), Error::ChunkTooLarge => write!(f, "Chunk size is too large."), Error::SnapshotsUnsupported => write!(f, "Snapshots unsupported by consensus engine."), + Error::SnapshotAborted => write!(f, "Snapshot was aborted."), Error::BadEpochProof(i) => write!(f, "Bad epoch proof for transition to epoch {}", i), Error::WrongChunkFormat(ref msg) => write!(f, "Wrong chunk format: {}", msg), Error::UnlinkedAncientBlockChain => write!(f, "Unlinked ancient blocks chain"), diff --git a/ethcore/src/snapshot/io.rs b/ethcore/src/snapshot/io.rs index c5f178cd32..536862e7be 100644 --- a/ethcore/src/snapshot/io.rs +++ b/ethcore/src/snapshot/io.rs @@ -310,10 +310,7 @@ impl LooseReader { dir.pop(); - Ok(LooseReader { - dir: dir, - manifest: manifest, - }) + Ok(LooseReader { dir, manifest }) } } diff --git a/ethcore/src/snapshot/mod.rs b/ethcore/src/snapshot/mod.rs index f054e54198..79b4eae949 100644 --- a/ethcore/src/snapshot/mod.rs +++ b/ethcore/src/snapshot/mod.rs @@ -22,7 +22,7 @@ use std::collections::{HashMap, HashSet}; use std::cmp; use std::sync::Arc; -use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering}; use hash::{keccak, KECCAK_NULL_RLP, KECCAK_EMPTY}; use account_db::{AccountDB, AccountDBMut}; @@ -32,7 +32,7 @@ use types::header::Header; use types::ids::BlockId; use ethereum_types::{H256, U256}; -use hashdb::HashDB; +use hash_db::HashDB; use keccak_hasher::KeccakHasher; use snappy; use bytes::Bytes; @@ -50,7 +50,7 @@ use self::io::SnapshotWriter; use super::state_db::StateDB; use super::state::Account as StateAccount; -use crossbeam::scope; +use crossbeam_utils::thread; use rand::{Rng, OsRng}; pub use self::error::Error; @@ -107,7 +107,7 @@ impl Default for SnapshotConfiguration { fn default() -> Self { SnapshotConfiguration { no_periodic: false, - processing_threads: ::std::cmp::max(1, num_cpus::get() / 2), + processing_threads: ::std::cmp::max(1, num_cpus::get_physical() / 2), } } } @@ -117,8 +117,9 @@ impl Default for SnapshotConfiguration { pub struct Progress { accounts: AtomicUsize, blocks: AtomicUsize, - size: AtomicUsize, // Todo [rob] use Atomicu64 when it stabilizes. + size: AtomicU64, done: AtomicBool, + abort: AtomicBool, } impl Progress { @@ -127,6 +128,7 @@ impl Progress { self.accounts.store(0, Ordering::Release); self.blocks.store(0, Ordering::Release); self.size.store(0, Ordering::Release); + self.abort.store(false, Ordering::Release); // atomic fence here to ensure the others are written first? // logs might very rarely get polluted if not. @@ -140,7 +142,7 @@ impl Progress { pub fn blocks(&self) -> usize { self.blocks.load(Ordering::Acquire) } /// Get the written size of the snapshot in bytes. - pub fn size(&self) -> usize { self.size.load(Ordering::Acquire) } + pub fn size(&self) -> u64 { self.size.load(Ordering::Acquire) } /// Whether the snapshot is complete. pub fn done(&self) -> bool { self.done.load(Ordering::Acquire) } @@ -148,27 +150,28 @@ impl Progress { } /// Take a snapshot using the given blockchain, starting block hash, and database, writing into the given writer. pub fn take_snapshot( - engine: &EthEngine, + chunker: Box, chain: &BlockChain, - block_at: H256, - state_db: &HashDB, + block_hash: H256, + state_db: &dyn HashDB, writer: W, p: &Progress, processing_threads: usize, ) -> Result<(), Error> { - let start_header = chain.block_header_data(&block_at) - .ok_or(Error::InvalidStartingBlock(BlockId::Hash(block_at)))?; + let start_header = chain.block_header_data(&block_hash) + .ok_or_else(|| Error::InvalidStartingBlock(BlockId::Hash(block_hash)))?; let state_root = start_header.state_root(); - let number = start_header.number(); + let block_number = start_header.number(); - info!("Taking snapshot starting at block {}", number); + info!("Taking snapshot starting at block {}", block_number); + let version = chunker.current_version(); let writer = Mutex::new(writer); - let chunker = engine.snapshot_components().ok_or(Error::SnapshotsUnsupported)?; - let snapshot_version = chunker.current_version(); - let (state_hashes, block_hashes) = scope(|scope| -> Result<(Vec, Vec), Error> { + let (state_hashes, block_hashes) = thread::scope(|scope| -> Result<(Vec, Vec), Error> { let writer = &writer; - let block_guard = scope.spawn(move || chunk_secondary(chunker, chain, block_at, writer, p)); + let block_guard = scope.spawn(move |_| { + chunk_secondary(chunker, chain, block_hash, writer, p) + }); // The number of threads must be between 1 and SNAPSHOT_SUBPARTS assert!(processing_threads >= 1, "Cannot use less than 1 threads for creating snapshots"); @@ -178,12 +181,12 @@ pub fn take_snapshot( let mut state_guards = Vec::with_capacity(num_threads as usize); for thread_idx in 0..num_threads { - let state_guard = scope.spawn(move || -> Result, Error> { + let state_guard = scope.spawn(move |_| -> Result, Error> { let mut chunk_hashes = Vec::new(); for part in (thread_idx..SNAPSHOT_SUBPARTS).step_by(num_threads) { debug!(target: "snapshot", "Chunking part {} in thread {}", part, thread_idx); - let mut hashes = chunk_state(state_db, &state_root, writer, p, Some(part))?; + let mut hashes = chunk_state(state_db, &state_root, writer, p, Some(part), thread_idx)?; chunk_hashes.append(&mut hashes); } @@ -202,17 +205,17 @@ pub fn take_snapshot( debug!(target: "snapshot", "Took a snapshot of {} accounts", p.accounts.load(Ordering::SeqCst)); Ok((state_hashes, block_hashes)) - })?; + }).expect("Sub-thread never panics; qed")?; info!(target: "snapshot", "produced {} state chunks and {} block chunks.", state_hashes.len(), block_hashes.len()); let manifest_data = ManifestData { - version: snapshot_version, - state_hashes: state_hashes, - block_hashes: block_hashes, - state_root: state_root, - block_number: number, - block_hash: block_at, + version, + state_hashes, + block_hashes, + state_root, + block_number, + block_hash, }; writer.into_inner().finish(manifest_data)?; @@ -228,7 +231,13 @@ pub fn take_snapshot( /// Secondary chunks are engine-specific, but they intend to corroborate the state data /// in the state chunks. /// Returns a list of chunk hashes, with the first having the blocks furthest from the genesis. -pub fn chunk_secondary<'a>(mut chunker: Box, chain: &'a BlockChain, start_hash: H256, writer: &Mutex, progress: &'a Progress) -> Result, Error> { +pub fn chunk_secondary<'a>( + mut chunker: Box, + chain: &'a BlockChain, + start_hash: H256, + writer: &Mutex, + progress: &'a Progress +) -> Result, Error> { let mut chunk_hashes = Vec::new(); let mut snappy_buffer = vec![0; snappy::max_compressed_len(PREFERRED_CHUNK_SIZE)]; @@ -243,7 +252,7 @@ pub fn chunk_secondary<'a>(mut chunker: Box, chain: &'a Bloc trace!(target: "snapshot", "wrote secondary chunk. hash: {:x}, size: {}, uncompressed size: {}", hash, size, raw_data.len()); - progress.size.fetch_add(size, Ordering::SeqCst); + progress.size.fetch_add(size as u64, Ordering::SeqCst); chunk_hashes.push(hash); Ok(()) }; @@ -266,8 +275,9 @@ struct StateChunker<'a> { rlps: Vec, cur_size: usize, snappy_buffer: Vec, - writer: &'a Mutex, + writer: &'a Mutex, progress: &'a Progress, + thread_idx: usize, } impl<'a> StateChunker<'a> { @@ -297,10 +307,10 @@ impl<'a> StateChunker<'a> { let hash = keccak(&compressed); self.writer.lock().write_state_chunk(hash, compressed)?; - trace!(target: "snapshot", "wrote state chunk. size: {}, uncompressed size: {}", compressed_size, raw_data.len()); + trace!(target: "snapshot", "Thread {} wrote state chunk. size: {}, uncompressed size: {}", self.thread_idx, compressed_size, raw_data.len()); self.progress.accounts.fetch_add(num_entries, Ordering::SeqCst); - self.progress.size.fetch_add(compressed_size, Ordering::SeqCst); + self.progress.size.fetch_add(compressed_size as u64, Ordering::SeqCst); self.hashes.push(hash); self.cur_size = 0; @@ -321,16 +331,24 @@ impl<'a> StateChunker<'a> { /// /// Returns a list of hashes of chunks created, or any error it may /// have encountered. -pub fn chunk_state<'a>(db: &HashDB, root: &H256, writer: &Mutex, progress: &'a Progress, part: Option) -> Result, Error> { - let account_trie = TrieDB::new(db, &root)?; +pub fn chunk_state<'a>( + db: &dyn HashDB, + root: &H256, + writer: &Mutex, + progress: &'a Progress, + part: Option, + thread_idx: usize, +) -> Result, Error> { + let account_trie = TrieDB::new(&db, &root)?; let mut chunker = StateChunker { hashes: Vec::new(), rlps: Vec::new(), cur_size: 0, snappy_buffer: vec![0; snappy::max_compressed_len(PREFERRED_CHUNK_SIZE)], - writer: writer, - progress: progress, + writer, + progress, + thread_idx, }; let mut used_code = HashSet::new(); @@ -365,7 +383,7 @@ pub fn chunk_state<'a>(db: &HashDB, root: &H256, writer: let account = ::rlp::decode(&*account_data)?; let account_db = AccountDB::from_hash(db, account_key_hash); - let fat_rlps = account::to_fat_rlps(&account_key_hash, &account, &account_db, &mut used_code, PREFERRED_CHUNK_SIZE - chunker.chunk_size(), PREFERRED_CHUNK_SIZE)?; + let fat_rlps = account::to_fat_rlps(&account_key_hash, &account, &account_db, &mut used_code, PREFERRED_CHUNK_SIZE - chunker.chunk_size(), PREFERRED_CHUNK_SIZE, progress)?; for (i, fat_rlp) in fat_rlps.into_iter().enumerate() { if i > 0 { chunker.write_chunk()?; @@ -383,7 +401,7 @@ pub fn chunk_state<'a>(db: &HashDB, root: &H256, writer: /// Used to rebuild the state trie piece by piece. pub struct StateRebuilder { - db: Box, + db: Box, state_root: H256, known_code: HashMap, // code hashes mapped to first account with this code. missing_code: HashMap>, // maps code hashes to lists of accounts missing that code. @@ -393,7 +411,7 @@ pub struct StateRebuilder { impl StateRebuilder { /// Create a new state rebuilder to write into the given backing DB. - pub fn new(db: Arc, pruning: Algorithm) -> Self { + pub fn new(db: Arc, pruning: Algorithm) -> Self { StateRebuilder { db: journaldb::new(db.clone(), pruning, ::db::COL_STATE), state_root: KECCAK_NULL_RLP, @@ -411,10 +429,10 @@ impl StateRebuilder { let mut pairs = Vec::with_capacity(rlp.item_count()?); // initialize the pairs vector with empty values so we have slots to write into. - pairs.resize(rlp.item_count()?, (H256::new(), Vec::new())); + pairs.resize(rlp.item_count()?, (H256::zero(), Vec::new())); let status = rebuild_accounts( - self.db.as_hashdb_mut(), + self.db.as_hash_db_mut(), rlp, &mut pairs, &self.known_code, @@ -429,7 +447,7 @@ impl StateRebuilder { // patch up all missing code. must be done after collecting all new missing code entries. for (code_hash, code, first_with) in status.new_code { for addr_hash in self.missing_code.remove(&code_hash).unwrap_or_else(Vec::new) { - let mut db = AccountDBMut::from_hash(self.db.as_hashdb_mut(), addr_hash); + let mut db = AccountDBMut::from_hash(self.db.as_hash_db_mut(), addr_hash); db.emplace(code_hash, DBValue::from_slice(&code)); } @@ -441,9 +459,9 @@ impl StateRebuilder { // batch trie writes { let mut account_trie = if self.state_root != KECCAK_NULL_RLP { - TrieDBMut::from_existing(self.db.as_hashdb_mut(), &mut self.state_root)? + TrieDBMut::from_existing(self.db.as_hash_db_mut(), &mut self.state_root)? } else { - TrieDBMut::new(self.db.as_hashdb_mut(), &mut self.state_root) + TrieDBMut::new(self.db.as_hash_db_mut(), &mut self.state_root) }; for (hash, thin_rlp) in pairs { @@ -468,7 +486,7 @@ impl StateRebuilder { /// Finalize the restoration. Check for accounts missing code and make a dummy /// journal entry. /// Once all chunks have been fed, there should be nothing missing. - pub fn finalize(mut self, era: u64, id: H256) -> Result, ::error::Error> { + pub fn finalize(mut self, era: u64, id: H256) -> Result, ::error::Error> { let missing = self.missing_code.keys().cloned().collect::>(); if !missing.is_empty() { return Err(Error::MissingCode(missing).into()) } @@ -493,7 +511,7 @@ struct RebuiltStatus { // rebuild a set of accounts and their storage. // returns a status detailing newly-loaded code and accounts missing code. fn rebuild_accounts( - db: &mut HashDB, + db: &mut dyn HashDB, account_fat_rlps: Rlp, out_chunk: &mut [(H256, Bytes)], known_code: &HashMap, @@ -512,7 +530,7 @@ fn rebuild_accounts( // fill out the storage trie and code while decoding. let (acc, maybe_code) = { let mut acct_db = AccountDBMut::from_hash(db, hash); - let storage_root = known_storage_roots.get(&hash).cloned().unwrap_or(H256::zero()); + let storage_root = known_storage_roots.get(&hash).cloned().unwrap_or_default(); account::from_fat_rlp(&mut acct_db, fat_rlp, storage_root)? }; @@ -560,7 +578,7 @@ const POW_VERIFY_RATE: f32 = 0.02; /// Verify an old block with the given header, engine, blockchain, body. If `always` is set, it will perform /// the fullest verification possible. If not, it will take a random sample to determine whether it will /// do heavy or light verification. -pub fn verify_old_block(rng: &mut OsRng, header: &Header, engine: &EthEngine, chain: &BlockChain, always: bool) -> Result<(), ::error::Error> { +pub fn verify_old_block(rng: &mut OsRng, header: &Header, engine: &dyn EthEngine, chain: &BlockChain, always: bool) -> Result<(), ::error::Error> { engine.verify_block_basic(header)?; if always || rng.gen::() <= POW_VERIFY_RATE { diff --git a/ethcore/src/snapshot/service.rs b/ethcore/src/snapshot/service.rs index 0da3f919fe..ddae76a00a 100644 --- a/ethcore/src/snapshot/service.rs +++ b/ethcore/src/snapshot/service.rs @@ -340,7 +340,7 @@ impl Service { // replace one the client's database with our own. fn replace_client_db(&self) -> Result<(), Error> { let migrated_blocks = self.migrate_blocks()?; - trace!(target: "snapshot", "Migrated {} ancient blocks", migrated_blocks); + info!(target: "snapshot", "Migrated {} ancient blocks", migrated_blocks); let rest_db = self.restoration_db(); self.client.restore_db(&*rest_db.to_string_lossy())?; @@ -415,7 +415,7 @@ impl Service { _ => break, } - // Writting changes to DB and logging every now and then + // Writing changes to DB and logging every now and then if block_number % 1_000 == 0 { next_db.key_value().write_buffered(batch); next_chain.commit(); @@ -424,7 +424,7 @@ impl Service { } if block_number % 10_000 == 0 { - trace!(target: "snapshot", "Block restoration at #{}", block_number); + info!(target: "snapshot", "Block restoration at #{}", block_number); } } @@ -479,16 +479,12 @@ impl Service { let guard = Guard::new(temp_dir.clone()); let res = client.take_snapshot(writer, BlockId::Number(num), &self.progress); - self.taking_snapshot.store(false, Ordering::SeqCst); if let Err(e) = res { if client.chain_info().best_block_number >= num + client.pruning_history() { - // "Cancelled" is mincing words a bit -- what really happened - // is that the state we were snapshotting got pruned out - // before we could finish. - info!("Periodic snapshot failed: block state pruned.\ - Run with a longer `--pruning-history` or with `--no-periodic-snapshot`"); - return Ok(()) + // The state we were snapshotting was pruned before we could finish. + info!("Periodic snapshot failed: block state pruned. Run with a longer `--pruning-history` or with `--no-periodic-snapshot`"); + return Err(e); } else { return Err(e); } @@ -846,14 +842,29 @@ impl SnapshotService for Service { } } + fn abort_snapshot(&self) { + if self.taking_snapshot.load(Ordering::SeqCst) { + trace!(target: "snapshot", "Aborting snapshot – Snapshot under way"); + self.progress.abort.store(true, Ordering::SeqCst); + } + } + fn shutdown(&self) { + trace!(target: "snapshot", "Shut down SnapshotService"); self.abort_restore(); + trace!(target: "snapshot", "Shut down SnapshotService - restore aborted"); + self.abort_snapshot(); + trace!(target: "snapshot", "Shut down SnapshotService - snapshot aborted"); } } impl Drop for Service { fn drop(&mut self) { + trace!(target: "shutdown", "Dropping Service"); self.abort_restore(); + trace!(target: "shutdown", "Dropping Service - restore aborted"); + self.abort_snapshot(); + trace!(target: "shutdown", "Dropping Service - snapshot aborted"); } } diff --git a/ethcore/src/snapshot/tests/helpers.rs b/ethcore/src/snapshot/tests/helpers.rs index 31913c2f40..817e024998 100644 --- a/ethcore/src/snapshot/tests/helpers.rs +++ b/ethcore/src/snapshot/tests/helpers.rs @@ -35,7 +35,7 @@ use rand::Rng; use kvdb::DBValue; use ethereum_types::H256; -use hashdb::HashDB; +use hash_db::HashDB; use keccak_hasher::KeccakHasher; use journaldb; use trie::{TrieMut, Trie}; @@ -65,7 +65,7 @@ impl StateProducer { pub fn tick(&mut self, rng: &mut R, db: &mut HashDB) { // modify existing accounts. let mut accounts_to_modify: Vec<_> = { - let trie = TrieDB::new(&*db, &self.state_root).unwrap(); + let trie = TrieDB::new(&db, &self.state_root).unwrap(); let temp = trie.iter().unwrap() // binding required due to complicated lifetime stuff .filter(|_| rng.gen::() < ACCOUNT_CHURN) .map(Result::unwrap) @@ -130,15 +130,6 @@ pub fn fill_storage(mut db: AccountDBMut, root: &mut H256, seed: &mut H256) { } } -/// Compare two state dbs. -pub fn compare_dbs(one: &HashDB, two: &HashDB) { - let keys = one.keys(); - - for key in keys.keys() { - assert_eq!(one.get(&key).unwrap(), two.get(&key).unwrap()); - } -} - /// Take a snapshot from the given client into a temporary file. /// Return a snapshot reader for it. pub fn snap(client: &Client) -> (Box, TempDir) { diff --git a/ethcore/src/snapshot/tests/proof_of_authority.rs b/ethcore/src/snapshot/tests/proof_of_authority.rs index 5ffcdab1b7..f1610e6ccd 100644 --- a/ethcore/src/snapshot/tests/proof_of_authority.rs +++ b/ethcore/src/snapshot/tests/proof_of_authority.rs @@ -20,12 +20,12 @@ use std::cell::RefCell; use std::sync::Arc; use std::str::FromStr; -use account_provider::AccountProvider; +use accounts::AccountProvider; use client::{Client, BlockChainClient, ChainInfo}; use ethkey::Secret; use snapshot::tests::helpers as snapshot_helpers; use spec::Spec; -use test_helpers::generate_dummy_client_with_spec_and_accounts; +use test_helpers::generate_dummy_client_with_spec; use types::transaction::{Transaction, Action, SignedTransaction}; use tempdir::TempDir; @@ -88,8 +88,7 @@ enum Transition { // create a chain with the given transitions and some blocks beyond that transition. fn make_chain(accounts: Arc, blocks_beyond: usize, transitions: Vec) -> Arc { - let client = generate_dummy_client_with_spec_and_accounts( - spec_fixed_to_contract, Some(accounts.clone())); + let client = generate_dummy_client_with_spec(spec_fixed_to_contract); let mut cur_signers = vec![*RICH_ADDR]; { @@ -100,13 +99,14 @@ fn make_chain(accounts: Arc, blocks_beyond: usize, transitions: { // push a block with given number, signed by one of the signers, with given transactions. let push_block = |signers: &[Address], n, txs: Vec| { - use miner::MinerService; + use miner::{self, MinerService}; let idx = n as usize % signers.len(); trace!(target: "snapshot", "Pushing block #{}, {} txs, author={}", n, txs.len(), signers[idx]); - client.miner().set_author(signers[idx], Some(PASS.into())).unwrap(); + let signer = Box::new((accounts.clone(), signers[idx], PASS.into())); + client.miner().set_author(miner::Author::Sealer(signer)); client.miner().import_external_transactions(&*client, txs.into_iter().map(Into::into).collect()); diff --git a/ethcore/src/snapshot/tests/service.rs b/ethcore/src/snapshot/tests/service.rs index 535e7c2993..515e5992ff 100644 --- a/ethcore/src/snapshot/tests/service.rs +++ b/ethcore/src/snapshot/tests/service.rs @@ -184,18 +184,19 @@ fn keep_ancient_blocks() { let start_header = bc.block_header_data(&best_hash).unwrap(); let state_root = start_header.state_root(); let state_hashes = chunk_state( - state_db.as_hashdb(), + state_db.as_hash_db(), &state_root, &writer, &Progress::default(), - None + None, + 0 ).unwrap(); let manifest = ::snapshot::ManifestData { version: 2, - state_hashes: state_hashes, - state_root: state_root, - block_hashes: block_hashes, + state_hashes, + state_root, + block_hashes, block_number: NUM_BLOCKS, block_hash: best_hash, }; diff --git a/ethcore/src/snapshot/tests/state.rs b/ethcore/src/snapshot/tests/state.rs index 44a624715e..0d97603324 100644 --- a/ethcore/src/snapshot/tests/state.rs +++ b/ethcore/src/snapshot/tests/state.rs @@ -24,7 +24,7 @@ use types::basic_account::BasicAccount; use snapshot::account; use snapshot::{chunk_state, Error as SnapshotError, Progress, StateRebuilder, SNAPSHOT_SUBPARTS}; use snapshot::io::{PackedReader, PackedWriter, SnapshotReader, SnapshotWriter}; -use super::helpers::{compare_dbs, StateProducer}; +use super::helpers::StateProducer; use error::{Error, ErrorKind}; @@ -32,15 +32,15 @@ use rand::{XorShiftRng, SeedableRng}; use ethereum_types::H256; use journaldb::{self, Algorithm}; use kvdb_rocksdb::{Database, DatabaseConfig}; -use memorydb::MemoryDB; use parking_lot::Mutex; use tempdir::TempDir; #[test] fn snap_and_restore() { + use hash_db::HashDB; let mut producer = StateProducer::new(); let mut rng = XorShiftRng::from_seed([1, 2, 3, 4]); - let mut old_db = MemoryDB::new(); + let mut old_db = journaldb::new_memory_db(); let db_cfg = DatabaseConfig::with_columns(::db::NUM_COLUMNS); for _ in 0..150 { @@ -55,7 +55,7 @@ fn snap_and_restore() { let mut state_hashes = Vec::new(); for part in 0..SNAPSHOT_SUBPARTS { - let mut hashes = chunk_state(&old_db, &state_root, &writer, &Progress::default(), Some(part)).unwrap(); + let mut hashes = chunk_state(&old_db, &state_root, &writer, &Progress::default(), Some(part), 0).unwrap(); state_hashes.append(&mut hashes); } @@ -91,8 +91,11 @@ fn snap_and_restore() { let new_db = journaldb::new(db, Algorithm::OverlayRecent, ::db::COL_STATE); assert_eq!(new_db.earliest_era(), Some(1000)); + let keys = old_db.keys(); - compare_dbs(&old_db, new_db.as_hashdb()); + for key in keys.keys() { + assert_eq!(old_db.get(&key).unwrap(), new_db.as_hash_db().get(&key).unwrap()); + } } #[test] @@ -100,7 +103,7 @@ fn get_code_from_prev_chunk() { use std::collections::HashSet; use rlp::RlpStream; use ethereum_types::{H256, U256}; - use hashdb::HashDB; + use hash_db::HashDB; use account_db::{AccountDBMut, AccountDB}; @@ -121,10 +124,10 @@ fn get_code_from_prev_chunk() { let acc: BasicAccount = ::rlp::decode(&thin_rlp).expect("error decoding basic account"); let mut make_chunk = |acc, hash| { - let mut db = MemoryDB::new(); + let mut db = journaldb::new_memory_db(); AccountDBMut::from_hash(&mut db, hash).insert(&code[..]); - - let fat_rlp = account::to_fat_rlps(&hash, &acc, &AccountDB::from_hash(&db, hash), &mut used_code, usize::max_value(), usize::max_value()).unwrap(); + let p = Progress::default(); + let fat_rlp = account::to_fat_rlps(&hash, &acc, &AccountDB::from_hash(&db, hash), &mut used_code, usize::max_value(), usize::max_value(), &p).unwrap(); let mut stream = RlpStream::new_list(1); stream.append_raw(&fat_rlp[0], 1); stream.out() @@ -155,7 +158,7 @@ fn get_code_from_prev_chunk() { fn checks_flag() { let mut producer = StateProducer::new(); let mut rng = XorShiftRng::from_seed([5, 6, 7, 8]); - let mut old_db = MemoryDB::new(); + let mut old_db = journaldb::new_memory_db(); let db_cfg = DatabaseConfig::with_columns(::db::NUM_COLUMNS); for _ in 0..10 { @@ -168,13 +171,13 @@ fn checks_flag() { let state_root = producer.state_root(); let writer = Mutex::new(PackedWriter::new(&snap_file).unwrap()); - let state_hashes = chunk_state(&old_db, &state_root, &writer, &Progress::default(), None).unwrap(); + let state_hashes = chunk_state(&old_db, &state_root, &writer, &Progress::default(), None, 0).unwrap(); writer.into_inner().finish(::snapshot::ManifestData { version: 2, - state_hashes: state_hashes, + state_hashes, block_hashes: Vec::new(), - state_root: state_root, + state_root, block_number: 0, block_hash: H256::default(), }).unwrap(); diff --git a/ethcore/src/snapshot/traits.rs b/ethcore/src/snapshot/traits.rs index bb4ab3b396..aa61b595bf 100644 --- a/ethcore/src/snapshot/traits.rs +++ b/ethcore/src/snapshot/traits.rs @@ -55,6 +55,9 @@ pub trait SnapshotService : Sync + Send { /// no-op if currently restoring. fn restore_block_chunk(&self, hash: H256, chunk: Bytes); + /// Abort in-progress snapshotting if there is one. + fn abort_snapshot(&self); + /// Shutdown the Snapshot Service by aborting any ongoing restore fn shutdown(&self); } diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 517b69e751..ec3a8f4aba 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -25,7 +25,6 @@ use bytes::Bytes; use ethereum_types::{H256, Bloom, U256, Address}; use ethjson; use hash::{KECCAK_NULL_RLP, keccak}; -use memorydb::MemoryDB; use parking_lot::RwLock; use rlp::{Rlp, RlpStream}; use rustc_hex::{FromHex, ToHex}; @@ -36,7 +35,7 @@ use vm::{EnvInfo, CallType, ActionValue, ActionParams, ParamsType}; use builtin::Builtin; use engines::{ - EthEngine, NullEngine, InstantSeal, InstantSealParams, BasicAuthority, + EthEngine, NullEngine, InstantSeal, InstantSealParams, BasicAuthority, Clique, AuthorityRound, DEFAULT_BLOCKHASH_CONTRACT }; use error::Error; @@ -66,7 +65,7 @@ fn fmt_err(f: F) -> String { /// we define a "bugfix" hard fork as any hard fork which /// you would put on-by-default in a new chain. #[derive(Debug, PartialEq, Default)] -#[cfg_attr(test, derive(Clone))] +#[cfg_attr(any(test, feature = "test-helpers"), derive(Clone))] pub struct CommonParams { /// Account start nonce. pub account_start_nonce: U256, @@ -100,9 +99,9 @@ pub struct CommonParams { pub validate_receipts_transition: BlockNumber, /// Validate transaction chain id. pub validate_chain_id_transition: BlockNumber, - /// Number of first block where EIP-140 (Metropolis: REVERT opcode) rules begin. + /// Number of first block where EIP-140 rules begin. pub eip140_transition: BlockNumber, - /// Number of first block where EIP-210 (Metropolis: BLOCKHASH changes) rules begin. + /// Number of first block where EIP-210 rules begin. pub eip210_transition: BlockNumber, /// EIP-210 Blockhash contract address. pub eip210_contract_address: Address, @@ -110,8 +109,7 @@ pub struct CommonParams { pub eip210_contract_code: Bytes, /// Gas allocated for EIP-210 blockhash update. pub eip210_contract_gas: U256, - /// Number of first block where EIP-211 (Metropolis: RETURNDATASIZE/RETURNDATACOPY) rules - /// begin. + /// Number of first block where EIP-211 rules begin. pub eip211_transition: BlockNumber, /// Number of first block where EIP-214 rules begin. pub eip214_transition: BlockNumber, @@ -123,8 +121,18 @@ pub struct CommonParams { pub eip1283_transition: BlockNumber, /// Number of first block where EIP-1283 rules end. pub eip1283_disable_transition: BlockNumber, + /// Number of first block where EIP-1283 rules re-enabled. + pub eip1283_reenable_transition: BlockNumber, /// Number of first block where EIP-1014 rules begin. pub eip1014_transition: BlockNumber, + /// Number of first block where EIP-1706 rules begin. + pub eip1706_transition: BlockNumber, + /// Number of first block where EIP-1344 rules begin: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1344.md + pub eip1344_transition: BlockNumber, + /// Number of first block where EIP-1884 rules begin:https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1884.md + pub eip1884_transition: BlockNumber, + /// Number of first block where EIP-2028 rules begin. + pub eip2028_transition: BlockNumber, /// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin. pub dust_protection_transition: BlockNumber, /// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled. @@ -191,7 +199,22 @@ impl CommonParams { schedule.have_return_data = block_number >= self.eip211_transition; schedule.have_bitwise_shifting = block_number >= self.eip145_transition; schedule.have_extcodehash = block_number >= self.eip1052_transition; - schedule.eip1283 = block_number >= self.eip1283_transition && !(block_number >= self.eip1283_disable_transition); + schedule.have_chain_id = block_number >= self.eip1344_transition; + schedule.eip1283 = + (block_number >= self.eip1283_transition && + !(block_number >= self.eip1283_disable_transition)) || + block_number >= self.eip1283_reenable_transition; + schedule.eip1706 = block_number >= self.eip1706_transition; + + if block_number >= self.eip1884_transition { + schedule.have_selfbalance = true; + schedule.sload_gas = 800; + schedule.balance_gas = 700; + schedule.extcodehash_gas = 700; + } + if block_number >= self.eip2028_transition { + schedule.tx_data_non_zero_gas = 16; + } if block_number >= self.eip210_transition { schedule.blockhash_gas = 800; } @@ -306,10 +329,30 @@ impl From for CommonParams { BlockNumber::max_value, Into::into, ), + eip1283_reenable_transition: p.eip1283_reenable_transition.map_or_else( + BlockNumber::max_value, + Into::into, + ), + eip1706_transition: p.eip1706_transition.map_or_else( + BlockNumber::max_value, + Into::into, + ), eip1014_transition: p.eip1014_transition.map_or_else( BlockNumber::max_value, Into::into, ), + eip1344_transition: p.eip1344_transition.map_or_else( + BlockNumber::max_value, + Into::into, + ), + eip1884_transition: p.eip1884_transition.map_or_else( + BlockNumber::max_value, + Into::into, + ), + eip2028_transition: p.eip2028_transition.map_or_else( + BlockNumber::max_value, + Into::into, + ), dust_protection_transition: p.dust_protection_transition.map_or_else( BlockNumber::max_value, Into::into, @@ -516,7 +559,7 @@ fn load_from(spec_params: SpecParams, s: ethjson::spec::Spec) -> Result Result { let _ = s.run_constructors( &Default::default(), - BasicBackend(MemoryDB::new()), + BasicBackend(journaldb::new_memory_db()), )?; } } @@ -612,6 +655,8 @@ impl Spec { ethjson::spec::Engine::InstantSeal(Some(instant_seal)) => Arc::new(InstantSeal::new(instant_seal.params.into(), machine)), ethjson::spec::Engine::InstantSeal(None) => Arc::new(InstantSeal::new(InstantSealParams::default(), machine)), ethjson::spec::Engine::BasicAuthority(basic_authority) => Arc::new(BasicAuthority::new(basic_authority.params.into(), machine)), + ethjson::spec::Engine::Clique(clique) => Clique::new(clique.params.into(), machine) + .expect("Failed to start Clique consensus engine."), ethjson::spec::Engine::AuthorityRound(authority_round) => AuthorityRound::new(authority_round.params.into(), machine) .expect("Failed to start AuthorityRound consensus engine."), } @@ -624,7 +669,7 @@ impl Spec { // basic accounts in spec. { - let mut t = factories.trie.create(db.as_hashdb_mut(), &mut root); + let mut t = factories.trie.create(db.as_hash_db_mut(), &mut root); for (address, account) in self.genesis_state.get().iter() { t.insert(&**address, &account.rlp())?; @@ -635,7 +680,7 @@ impl Spec { db.note_non_null_account(address); account.insert_additional( &mut *factories.accountdb.create( - db.as_hashdb_mut(), + db.as_hash_db_mut(), keccak(address), ), &factories.trie, @@ -792,7 +837,7 @@ impl Spec { self.genesis_state = s; let _ = self.run_constructors( &Default::default(), - BasicBackend(MemoryDB::new()), + BasicBackend(journaldb::new_memory_db()), )?; Ok(()) @@ -813,7 +858,7 @@ impl Spec { /// Ensure that the given state DB has the trie nodes in for the genesis state. pub fn ensure_db_good(&self, db: T, factories: &Factories) -> Result { - if db.as_hashdb().contains(&self.state_root()) { + if db.as_hash_db().contains(&self.state_root()) { return Ok(db); } @@ -828,7 +873,6 @@ impl Spec { ethjson::spec::Spec::load(reader) .map_err(fmt_err) .map(load_machine_from) - } /// Loads spec from json file. Provide factories for executing contracts and ensuring @@ -860,7 +904,7 @@ impl Spec { None, ); - self.ensure_db_good(BasicBackend(db.as_hashdb_mut()), &factories) + self.ensure_db_good(BasicBackend(db.as_hash_db_mut()), &factories) .map_err(|e| format!("Unable to initialize genesis state: {}", e))?; let call = |a, d| { @@ -886,7 +930,7 @@ impl Spec { }.fake_sign(from); let res = ::state::prove_transaction_virtual( - db.as_hashdb_mut(), + db.as_hash_db_mut(), *genesis.state_root(), &tx, self.engine.machine(), @@ -1000,7 +1044,6 @@ mod tests { use types::view; use types::views::BlockView; - // https://github.com/paritytech/parity-ethereum/issues/1840 #[test] fn test_load_empty() { let tempdir = TempDir::new("").unwrap(); diff --git a/ethcore/src/state/account.rs b/ethcore/src/state/account.rs index 483df7ba19..fea9444b1c 100644 --- a/ethcore/src/state/account.rs +++ b/ethcore/src/state/account.rs @@ -22,7 +22,7 @@ use std::collections::{HashMap, BTreeMap}; use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP, keccak}; use ethereum_types::{H256, U256, Address}; use error::Error; -use hashdb::HashDB; +use hash_db::HashDB; use keccak_hasher::KeccakHasher; use kvdb::DBValue; use bytes::{Bytes, ToPretty}; @@ -253,7 +253,7 @@ impl Account { } fn get_and_cache_storage(storage_root: &H256, storage_cache: &mut LruCache, db: &HashDB, key: &H256) -> TrieResult { - let db = SecTrieDB::new(db, storage_root)?; + let db = SecTrieDB::new(&db, storage_root)?; let panicky_decoder = |bytes:&[u8]| ::rlp::decode(&bytes).expect("decoding db value failed"); let item: U256 = db.get_with(key, panicky_decoder)?.unwrap_or_else(U256::zero); let value: H256 = item.into(); @@ -591,7 +591,7 @@ impl Account { pub fn prove_storage(&self, db: &HashDB, storage_key: H256) -> TrieResult<(Vec, H256)> { let mut recorder = Recorder::new(); - let trie = TrieDB::new(db, &self.storage_root)?; + let trie = TrieDB::new(&db, &self.storage_root)?; let item: U256 = { let panicky_decoder = |bytes:&[u8]| ::rlp::decode(bytes).expect("decoding db value failed"); let query = (&mut recorder, panicky_decoder); @@ -617,7 +617,7 @@ impl fmt::Debug for Account { mod tests { use rlp_compress::{compress, decompress, snapshot_swapper}; use ethereum_types::{H256, Address}; - use memorydb::MemoryDB; + use journaldb::new_memory_db; use bytes::Bytes; use super::*; use account_db::*; @@ -633,7 +633,7 @@ mod tests { #[test] fn storage_at() { - let mut db = MemoryDB::new(); + let mut db = new_memory_db(); let mut db = AccountDBMut::new(&mut db, &Address::new()); let rlp = { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); @@ -652,7 +652,7 @@ mod tests { #[test] fn note_code() { - let mut db = MemoryDB::new(); + let mut db = new_memory_db(); let mut db = AccountDBMut::new(&mut db, &Address::new()); let rlp = { @@ -672,7 +672,7 @@ mod tests { #[test] fn commit_storage() { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); - let mut db = MemoryDB::new(); + let mut db = new_memory_db(); let mut db = AccountDBMut::new(&mut db, &Address::new()); a.set_storage(0.into(), 0x1234.into()); assert_eq!(a.storage_root(), None); @@ -683,7 +683,7 @@ mod tests { #[test] fn commit_remove_commit_storage() { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); - let mut db = MemoryDB::new(); + let mut db = new_memory_db(); let mut db = AccountDBMut::new(&mut db, &Address::new()); a.set_storage(0.into(), 0x1234.into()); a.commit_storage(&Default::default(), &mut db).unwrap(); @@ -697,7 +697,7 @@ mod tests { #[test] fn commit_code() { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); - let mut db = MemoryDB::new(); + let mut db = new_memory_db(); let mut db = AccountDBMut::new(&mut db, &Address::new()); a.init_code(vec![0x55, 0x44, 0xffu8]); assert_eq!(a.code_filth, Filth::Dirty); @@ -709,7 +709,7 @@ mod tests { #[test] fn reset_code() { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); - let mut db = MemoryDB::new(); + let mut db = new_memory_db(); let mut db = AccountDBMut::new(&mut db, &Address::new()); a.init_code(vec![0x55, 0x44, 0xffu8]); assert_eq!(a.code_filth, Filth::Dirty); @@ -741,11 +741,4 @@ mod tests { assert_eq!(a.code_hash(), KECCAK_EMPTY); assert_eq!(a.storage_root().unwrap(), KECCAK_NULL_RLP); } - - #[test] - fn create_account() { - let a = Account::new(69u8.into(), 0u8.into(), HashMap::new(), Bytes::new()); - assert_eq!(a.rlp().to_hex(), "f8448045a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); - } - } diff --git a/ethcore/src/state/backend.rs b/ethcore/src/state/backend.rs index 2593f9a5d7..11e73edb3a 100644 --- a/ethcore/src/state/backend.rs +++ b/ethcore/src/state/backend.rs @@ -27,18 +27,19 @@ use std::sync::Arc; use state::Account; use parking_lot::Mutex; use ethereum_types::{Address, H256}; -use memorydb::MemoryDB; -use hashdb::{AsHashDB, HashDB}; +use memory_db::MemoryDB; +use hash_db::{AsHashDB, HashDB}; use kvdb::DBValue; use keccak_hasher::KeccakHasher; +use journaldb::AsKeyedHashDB; /// State backend. See module docs for more details. pub trait Backend: Send { /// Treat the backend as a read-only hashdb. - fn as_hashdb(&self) -> &HashDB; + fn as_hash_db(&self) -> &HashDB; /// Treat the backend as a writeable hashdb. - fn as_hashdb_mut(&mut self) -> &mut HashDB; + fn as_hash_db_mut(&mut self) -> &mut HashDB; /// Add an account entry to the cache. fn add_to_account_cache(&mut self, addr: Address, data: Option, modified: bool); @@ -82,14 +83,17 @@ pub struct ProofCheck(MemoryDB); impl ProofCheck { /// Create a new `ProofCheck` backend from the given state items. pub fn new(proof: &[DBValue]) -> Self { - let mut db = MemoryDB::::new(); + let mut db = journaldb::new_memory_db(); for item in proof { db.insert(item); } ProofCheck(db) } } -impl HashDB for ProofCheck { +impl journaldb::KeyedHashDB for ProofCheck { fn keys(&self) -> HashMap { self.0.keys() } +} + +impl HashDB for ProofCheck { fn get(&self, key: &H256) -> Option { self.0.get(key) } @@ -110,13 +114,13 @@ impl HashDB for ProofCheck { } impl AsHashDB for ProofCheck { - fn as_hashdb(&self) -> &HashDB { self } - fn as_hashdb_mut(&mut self) -> &mut HashDB { self } + fn as_hash_db(&self) -> &HashDB { self } + fn as_hash_db_mut(&mut self) -> &mut HashDB { self } } impl Backend for ProofCheck { - fn as_hashdb(&self) -> &HashDB { self } - fn as_hashdb_mut(&mut self) -> &mut HashDB { self } + fn as_hash_db(&self) -> &HashDB { self } + fn as_hash_db_mut(&mut self) -> &mut HashDB { self } fn add_to_account_cache(&mut self, _addr: Address, _data: Option, _modified: bool) {} fn cache_code(&self, _hash: H256, _code: Arc>) {} fn get_cached_account(&self, _addr: &Address) -> Option> { None } @@ -135,26 +139,32 @@ impl Backend for ProofCheck { /// The proof-of-execution can be extracted with `extract_proof`. /// /// This doesn't cache anything or rely on the canonical state caches. -pub struct Proving> { +pub struct Proving { base: H, // state we're proving values from. changed: MemoryDB, // changed state via insertions. proof: Mutex>, } +impl AsKeyedHashDB for Proving { + fn as_keyed_hash_db(&self) -> &journaldb::KeyedHashDB { self } +} + impl + Send + Sync> AsHashDB for Proving { - fn as_hashdb(&self) -> &HashDB { self } - fn as_hashdb_mut(&mut self) -> &mut HashDB { self } + fn as_hash_db(&self) -> &HashDB { self } + fn as_hash_db_mut(&mut self) -> &mut HashDB { self } } -impl + Send + Sync> HashDB for Proving { +impl journaldb::KeyedHashDB for Proving { fn keys(&self) -> HashMap { - let mut keys = self.base.as_hashdb().keys(); + let mut keys = self.base.as_keyed_hash_db().keys(); keys.extend(self.changed.keys()); keys } +} +impl + Send + Sync> HashDB for Proving { fn get(&self, key: &H256) -> Option { - match self.base.as_hashdb().get(key) { + match self.base.as_hash_db().get(key) { Some(val) => { self.proof.lock().insert(val.clone()); Some(val) @@ -184,9 +194,9 @@ impl + Send + Sync> HashDB + Send + Sync> Backend for Proving { - fn as_hashdb(&self) -> &HashDB { self } + fn as_hash_db(&self) -> &HashDB { self } - fn as_hashdb_mut(&mut self) -> &mut HashDB { self } + fn as_hash_db_mut(&mut self) -> &mut HashDB { self } fn add_to_account_cache(&mut self, _: Address, _: Option, _: bool) { } @@ -211,7 +221,7 @@ impl> Proving { pub fn new(base: H) -> Self { Proving { base: base, - changed: MemoryDB::::new(), + changed: journaldb::new_memory_db(), proof: Mutex::new(HashSet::new()), } } @@ -238,12 +248,12 @@ impl + Clone> Clone for Proving { pub struct Basic(pub H); impl + Send + Sync> Backend for Basic { - fn as_hashdb(&self) -> &HashDB { - self.0.as_hashdb() + fn as_hash_db(&self) -> &HashDB { + self.0.as_hash_db() } - fn as_hashdb_mut(&mut self) -> &mut HashDB { - self.0.as_hashdb_mut() + fn as_hash_db_mut(&mut self) -> &mut HashDB { + self.0.as_hash_db_mut() } fn add_to_account_cache(&mut self, _: Address, _: Option, _: bool) { } diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 9c99b541ae..ddad10c40d 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -43,7 +43,7 @@ use state_db::StateDB; use factory::VmFactory; use ethereum_types::{H256, U256, Address}; -use hashdb::{HashDB, AsHashDB}; +use hash_db::{HashDB, AsHashDB}; use keccak_hasher::KeccakHasher; use kvdb::DBValue; use bytes::Bytes; @@ -82,8 +82,8 @@ pub enum ProvedExecution { BadProof, /// The transaction failed, but not due to a bad proof. Failed(ExecutionError), - /// The transaction successfully completd with the given proof. - Complete(Executed), + /// The transaction successfully completed with the given proof. + Complete(Box), } #[derive(Eq, PartialEq, Clone, Copy, Debug)] @@ -218,7 +218,7 @@ pub fn check_proof( let options = TransactOptions::with_no_tracing().save_output_from_contract(); match state.execute(env_info, machine, transaction, options, true) { - Ok(executed) => ProvedExecution::Complete(executed), + Ok(executed) => ProvedExecution::Complete(Box::new(executed)), Err(ExecutionError::Internal(_)) => ProvedExecution::BadProof, Err(e) => ProvedExecution::Failed(e), } @@ -366,7 +366,7 @@ impl State { let mut root = H256::new(); { // init trie and reset root to null - let _ = factories.trie.create(db.as_hashdb_mut(), &mut root); + let _ = factories.trie.create(db.as_hash_db_mut(), &mut root); } State { @@ -381,7 +381,7 @@ impl State { /// Creates new state with existing state root pub fn from_existing(db: B, root: H256, account_start_nonce: U256, factories: Factories) -> TrieResult> { - if !db.as_hashdb().contains(&root) { + if !db.as_hash_db().contains(&root) { return Err(Box::new(TrieError::InvalidStateRoot(root))); } @@ -665,8 +665,8 @@ impl State { let trie_res = self.db.get_cached(address, |acc| match acc { None => Ok(H256::new()), Some(a) => { - let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address)); - f_at(a, account_db.as_hashdb(), key) + let account_db = self.factories.accountdb.readonly(self.db.as_hash_db(), a.address_hash(address)); + f_at(a, account_db.as_hash_db(), key) } }); @@ -677,8 +677,8 @@ impl State { // otherwise cache the account localy and cache storage key there. if let Some(ref mut acc) = local_account { if let Some(ref account) = acc.account { - let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(address)); - return f_at(account, account_db.as_hashdb(), key) + let account_db = self.factories.accountdb.readonly(self.db.as_hash_db(), account.address_hash(address)); + return f_at(account, account_db.as_hash_db(), key) } else { return Ok(H256::new()) } @@ -689,12 +689,13 @@ impl State { if self.db.is_known_null(address) { return Ok(H256::zero()) } // account is not found in the global cache, get from the DB and insert into local - let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR); + let db = &self.db.as_hash_db(); + let db = self.factories.trie.readonly(db, &self.root).expect(SEC_TRIE_DB_UNWRAP_STR); let from_rlp = |b: &[u8]| Account::from_rlp(b).expect("decoding db value failed"); let maybe_acc = db.get_with(address, from_rlp)?; let r = maybe_acc.as_ref().map_or(Ok(H256::new()), |a| { - let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address)); - f_at(a, account_db.as_hashdb(), key) + let account_db = self.factories.accountdb.readonly(self.db.as_hash_db(), a.address_hash(address)); + f_at(a, account_db.as_hash_db(), key) }); self.insert_cache(address, AccountEntry::new_clean(maybe_acc)); r @@ -887,9 +888,9 @@ impl State { if let Some(ref mut account) = a.account { let addr_hash = account.address_hash(address); { - let mut account_db = self.factories.accountdb.create(self.db.as_hashdb_mut(), addr_hash); - account.commit_storage(&self.factories.trie, account_db.as_hashdb_mut())?; - account.commit_code(account_db.as_hashdb_mut()); + let mut account_db = self.factories.accountdb.create(self.db.as_hash_db_mut(), addr_hash); + account.commit_storage(&self.factories.trie, account_db.as_hash_db_mut())?; + account.commit_code(account_db.as_hash_db_mut()); } if !account.is_empty() { self.db.note_non_null_account(address); @@ -898,7 +899,7 @@ impl State { } { - let mut trie = self.factories.trie.from_existing(self.db.as_hashdb_mut(), &mut self.root)?; + let mut trie = self.factories.trie.from_existing(self.db.as_hash_db_mut(), &mut self.root)?; for (address, ref mut a) in accounts.iter_mut().filter(|&(_, ref a)| a.is_dirty()) { a.state = AccountState::Committed; match a.account { @@ -981,7 +982,8 @@ impl State { let mut result = BTreeMap::new(); - let trie = self.factories.trie.readonly(self.db.as_hashdb(), &self.root)?; + let db = &self.db.as_hash_db(); + let trie = self.factories.trie.readonly(db, &self.root)?; // put trie in cache for item in trie.iter()? { @@ -1011,10 +1013,11 @@ impl State { fn account_to_pod_account(&self, account: &Account, address: &Address) -> Result { let mut pod_storage = BTreeMap::new(); let addr_hash = account.address_hash(address); - let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), addr_hash); + let accountdb = self.factories.accountdb.readonly(self.db.as_hash_db(), addr_hash); let root = account.base_storage_root(); - let trie = self.factories.trie.readonly(accountdb.as_hashdb(), &root)?; + let accountdb = &accountdb.as_hash_db(); + let trie = self.factories.trie.readonly(accountdb, &root)?; for o_kv in trie.iter()? { if let Ok((key, val)) = o_kv { pod_storage.insert(key[..].into(), rlp::decode::(&val[..]).expect("Decoded from trie which was encoded from the same type; qed").into()); @@ -1134,8 +1137,8 @@ impl State { // check local cache first if let Some(ref mut maybe_acc) = self.cache.borrow_mut().get_mut(a) { if let Some(ref mut account) = maybe_acc.account { - let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a)); - if Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()) { + let accountdb = self.factories.accountdb.readonly(self.db.as_hash_db(), account.address_hash(a)); + if Self::update_account_cache(require, account, &self.db, accountdb.as_hash_db()) { return Ok(f(Some(account))); } else { return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a)))); @@ -1146,8 +1149,8 @@ impl State { // check global cache let result = self.db.get_cached(a, |mut acc| { if let Some(ref mut account) = acc { - let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a)); - if !Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()) { + let accountdb = self.factories.accountdb.readonly(self.db.as_hash_db(), account.address_hash(a)); + if !Self::update_account_cache(require, account, &self.db, accountdb.as_hash_db()) { return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a)))); } } @@ -1160,12 +1163,13 @@ impl State { if check_null && self.db.is_known_null(a) { return Ok(f(None)); } // not found in the global cache, get from the DB and insert into local - let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root)?; + let db = &self.db.as_hash_db(); + let db = self.factories.trie.readonly(db, &self.root)?; let from_rlp = |b: &[u8]| Account::from_rlp(b).expect("decoding db value failed"); let mut maybe_acc = db.get_with(a, from_rlp)?; if let Some(ref mut account) = maybe_acc.as_mut() { - let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a)); - if !Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()) { + let accountdb = self.factories.accountdb.readonly(self.db.as_hash_db(), account.address_hash(a)); + if !Self::update_account_cache(require, account, &self.db, accountdb.as_hash_db()) { return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a)))); } } @@ -1192,7 +1196,8 @@ impl State { Some(acc) => self.insert_cache(a, AccountEntry::new_clean_cached(acc)), None => { let maybe_acc = if !self.db.is_known_null(a) { - let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root)?; + let db = &self.db.as_hash_db(); + let db = self.factories.trie.readonly(db, &self.root)?; let from_rlp = |b:&[u8]| { Account::from_rlp(b).expect("decoding db value failed") }; AccountEntry::new_clean(db.get_with(a, from_rlp)?) } else { @@ -1220,9 +1225,9 @@ impl State { if require_code { let addr_hash = account.address_hash(a); - let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), addr_hash); + let accountdb = self.factories.accountdb.readonly(self.db.as_hash_db(), addr_hash); - if !Self::update_account_cache(RequireCache::Code, &mut account, &self.db, accountdb.as_hashdb()) { + if !Self::update_account_cache(RequireCache::Code, &mut account, &self.db, accountdb.as_hash_db()) { return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a)))) } } @@ -1245,10 +1250,11 @@ impl State { /// `account_key` == keccak(address) pub fn prove_account(&self, account_key: H256) -> TrieResult<(Vec, BasicAccount)> { let mut recorder = Recorder::new(); - let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?; + let db = &self.db.as_hash_db(); + let trie = TrieDB::new(db, &self.root)?; let maybe_account: Option = { let panicky_decoder = |bytes: &[u8]| { - ::rlp::decode(bytes).expect(&format!("prove_account, could not query trie for account key={}", &account_key)) + ::rlp::decode(bytes).unwrap_or_else(|_| panic!("prove_account, could not query trie for account key={}", &account_key)) }; let query = (&mut recorder, panicky_decoder); trie.get_with(&account_key, query)? @@ -1271,15 +1277,16 @@ impl State { pub fn prove_storage(&self, account_key: H256, storage_key: H256) -> TrieResult<(Vec, H256)> { // TODO: probably could look into cache somehow but it's keyed by // address, not keccak(address). - let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?; + let db = &self.db.as_hash_db(); + let trie = TrieDB::new(db, &self.root)?; let from_rlp = |b: &[u8]| Account::from_rlp(b).expect("decoding db value failed"); let acc = match trie.get_with(&account_key, from_rlp)? { Some(acc) => acc, None => return Ok((Vec::new(), H256::new())), }; - let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), account_key); - acc.prove_storage(account_db.as_hashdb(), storage_key) + let account_db = self.factories.accountdb.readonly(self.db.as_hash_db(), account_key); + acc.prove_storage(account_db.as_hash_db(), storage_key) } } diff --git a/ethcore/src/state_db.rs b/ethcore/src/state_db.rs index 6b31864526..066a4f6162 100644 --- a/ethcore/src/state_db.rs +++ b/ethcore/src/state_db.rs @@ -25,7 +25,7 @@ use byteorder::{LittleEndian, ByteOrder}; use db::COL_ACCOUNT_BLOOM; use ethereum_types::{H256, Address}; use hash::keccak; -use hashdb::HashDB; +use hash_db::HashDB; use journaldb::JournalDB; use keccak_hasher::KeccakHasher; use kvdb::{KeyValueDB, DBTransaction, DBValue}; @@ -313,13 +313,13 @@ impl StateDB { } /// Conversion method to interpret self as `HashDB` reference - pub fn as_hashdb(&self) -> &HashDB { - self.db.as_hashdb() + pub fn as_hash_db(&self) -> &HashDB { + self.db.as_hash_db() } /// Conversion method to interpret self as mutable `HashDB` reference - pub fn as_hashdb_mut(&mut self) -> &mut HashDB { - self.db.as_hashdb_mut() + pub fn as_hash_db_mut(&mut self) -> &mut HashDB { + self.db.as_hash_db_mut() } /// Clone the database. @@ -379,14 +379,7 @@ impl StateDB { /// Check if the account can be returned from cache by matching current block parent hash against canonical /// state and filtering out account modified in later blocks. - fn is_allowed(addr: &Address, parent_hash: &Option, modifications: &VecDeque) -> bool { - let mut parent = match *parent_hash { - None => { - trace!("Cache lookup skipped for {:?}: no parent hash", addr); - return false; - } - Some(ref parent) => parent, - }; + fn is_allowed(addr: &Address, parent_hash: &H256, modifications: &VecDeque) -> bool { if modifications.is_empty() { return true; } @@ -395,6 +388,7 @@ impl StateDB { // We search for our parent in that list first and then for // all its parent until we hit the canonical block, // checking against all the intermediate modifications. + let mut parent = parent_hash; for m in modifications { if &m.hash == parent { if m.is_canon { @@ -413,10 +407,10 @@ impl StateDB { } impl state::Backend for StateDB { - fn as_hashdb(&self) -> &HashDB { self.db.as_hashdb() } + fn as_hash_db(&self) -> &HashDB { self.db.as_hash_db() } - fn as_hashdb_mut(&mut self) -> &mut HashDB { - self.db.as_hashdb_mut() + fn as_hash_db_mut(&mut self) -> &mut HashDB { + self.db.as_hash_db_mut() } fn add_to_account_cache(&mut self, addr: Address, data: Option, modified: bool) { @@ -434,20 +428,25 @@ impl state::Backend for StateDB { } fn get_cached_account(&self, addr: &Address) -> Option> { - let mut cache = self.account_cache.lock(); - if !Self::is_allowed(addr, &self.parent_hash, &cache.modifications) { - return None; - } - cache.accounts.get_mut(addr).map(|a| a.as_ref().map(|a| a.clone_basic())) + self.parent_hash.as_ref().and_then(|parent_hash| { + let mut cache = self.account_cache.lock(); + if !Self::is_allowed(addr, parent_hash, &cache.modifications) { + return None; + } + cache.accounts.get_mut(addr).map(|a| a.as_ref().map(|a| a.clone_basic())) + }) } fn get_cached(&self, a: &Address, f: F) -> Option - where F: FnOnce(Option<&mut Account>) -> U { - let mut cache = self.account_cache.lock(); - if !Self::is_allowed(a, &self.parent_hash, &cache.modifications) { - return None; - } - cache.accounts.get_mut(a).map(|c| f(c.as_mut())) + where F: FnOnce(Option<&mut Account>) -> U + { + self.parent_hash.as_ref().and_then(|parent_hash| { + let mut cache = self.account_cache.lock(); + if !Self::is_allowed(a, parent_hash, &cache.modifications) { + return None; + } + cache.accounts.get_mut(a).map(|c| f(c.as_mut())) + }) } fn get_cached_code(&self, hash: &H256) -> Option>> { diff --git a/ethcore/src/test_helpers.rs b/ethcore/src/test_helpers.rs index 939c4e5e1d..b5575f36cd 100644 --- a/ethcore/src/test_helpers.rs +++ b/ethcore/src/test_helpers.rs @@ -39,7 +39,6 @@ use types::header::Header; use types::view; use types::views::BlockView; -use account_provider::AccountProvider; use block::{OpenBlock, Drain}; use client::{Client, ClientConfig, ChainInfo, ImportBlock, ChainNotify, ChainMessageType, PrepareOpenBlock}; use factory::Factories; @@ -109,18 +108,15 @@ pub fn generate_dummy_client_with_data(block_number: u32, txs_per_block: usize, generate_dummy_client_with_spec_and_data(Spec::new_null, block_number, txs_per_block, tx_gas_prices) } -/// Generates dummy client (not test client) with corresponding amount of blocks, txs per block and spec -pub fn generate_dummy_client_with_spec_and_data(test_spec: F, block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> Arc where F: Fn()->Spec { - generate_dummy_client_with_spec_accounts_and_data(test_spec, None, block_number, txs_per_block, tx_gas_prices) -} - /// Generates dummy client (not test client) with corresponding spec and accounts -pub fn generate_dummy_client_with_spec_and_accounts(test_spec: F, accounts: Option>) -> Arc where F: Fn()->Spec { - generate_dummy_client_with_spec_accounts_and_data(test_spec, accounts, 0, 0, &[]) +pub fn generate_dummy_client_with_spec(test_spec: F) -> Arc where F: Fn()->Spec { + generate_dummy_client_with_spec_and_data(test_spec, 0, 0, &[]) } -/// Generates dummy client (not test client) with corresponding blocks, accounts and spec -pub fn generate_dummy_client_with_spec_accounts_and_data(test_spec: F, accounts: Option>, block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> Arc where F: Fn()->Spec { +/// Generates dummy client (not test client) with corresponding amount of blocks, txs per block and spec +pub fn generate_dummy_client_with_spec_and_data(test_spec: F, block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> Arc where + F: Fn() -> Spec +{ let test_spec = test_spec(); let client_db = new_db(); @@ -128,7 +124,7 @@ pub fn generate_dummy_client_with_spec_accounts_and_data(test_spec: F, accoun ClientConfig::default(), &test_spec, client_db, - Arc::new(Miner::new_for_tests(&test_spec, accounts)), + Arc::new(Miner::new_for_tests(&test_spec, None)), IoChannel::disconnected(), ).unwrap(); let test_engine = &*test_spec.engine; @@ -159,7 +155,7 @@ pub fn generate_dummy_client_with_spec_accounts_and_data(test_spec: F, accoun (3141562.into(), 31415620.into()), vec![], false, - &mut Vec::new().into_iter(), + None, ).unwrap(); rolling_timestamp += 10; b.set_timestamp(rolling_timestamp); diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 60ea5e1f0e..9086d07e08 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -27,8 +27,7 @@ use types::filter::Filter; use types::view; use types::views::BlockView; -use block::IsBlock; -use client::{BlockChainClient, Client, ClientConfig, BlockId, ChainInfo, BlockInfo, PrepareOpenBlock, ImportSealedBlock, ImportBlock}; +use client::{BlockChainClient, BlockChainReset, Client, ClientConfig, BlockId, ChainInfo, BlockInfo, PrepareOpenBlock, ImportSealedBlock, ImportBlock}; use ethereum; use executive::{Executive, TransactOptions}; use miner::{Miner, PendingOrdering, MinerService}; @@ -254,7 +253,7 @@ fn can_mine() { let b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]).unwrap().close().unwrap(); - assert_eq!(*b.block().header().parent_hash(), view!(BlockView, &dummy_blocks[0]).header_view().hash()); + assert_eq!(*b.header.parent_hash(), view!(BlockView, &dummy_blocks[0]).header_view().hash()); } #[test] @@ -367,3 +366,23 @@ fn transaction_proof() { assert_eq!(state.balance(&Address::default()).unwrap(), 5.into()); assert_eq!(state.balance(&address).unwrap(), 95.into()); } + +#[test] +fn reset_blockchain() { + let client = get_test_client_with_blocks(get_good_dummy_block_seq(19)); + // 19 + genesis block + assert!(client.block_header(BlockId::Number(20)).is_some()); + assert_eq!(client.block_header(BlockId::Number(20)).unwrap().hash(), client.best_block_header().hash()); + + assert!(client.reset(5).is_ok()); + + client.chain().clear_cache(); + + assert!(client.block_header(BlockId::Number(20)).is_none()); + assert!(client.block_header(BlockId::Number(19)).is_none()); + assert!(client.block_header(BlockId::Number(18)).is_none()); + assert!(client.block_header(BlockId::Number(17)).is_none()); + assert!(client.block_header(BlockId::Number(16)).is_none()); + + assert!(client.block_header(BlockId::Number(15)).is_some()); +} diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index f687aac127..c14f13cf59 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -86,7 +86,7 @@ fn can_trace_block_and_uncle_reward() { (3141562.into(), 31415620.into()), vec![], false, - &mut Vec::new().into_iter(), + None, ).unwrap(); rolling_timestamp += 10; root_block.set_timestamp(rolling_timestamp); @@ -115,7 +115,7 @@ fn can_trace_block_and_uncle_reward() { (3141562.into(), 31415620.into()), vec![], false, - &mut Vec::new().into_iter(), + None, ).unwrap(); rolling_timestamp += 10; parent_block.set_timestamp(rolling_timestamp); @@ -143,7 +143,7 @@ fn can_trace_block_and_uncle_reward() { (3141562.into(), 31415620.into()), vec![], false, - &mut Vec::new().into_iter(), + None, ).unwrap(); rolling_timestamp += 10; block.set_timestamp(rolling_timestamp); diff --git a/ethcore/src/trace/executive_tracer.rs b/ethcore/src/trace/executive_tracer.rs index 015deaea03..1653011c32 100644 --- a/ethcore/src/trace/executive_tracer.rs +++ b/ethcore/src/trace/executive_tracer.rs @@ -16,8 +16,10 @@ //! Simple executive tracer. +use std::cmp::min; use ethereum_types::{U256, Address}; use vm::{Error as VmError, ActionParams}; +use log::{debug, warn}; use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide, Reward, RewardType}; use trace::{Tracer, VMTracer, FlatTrace}; @@ -193,12 +195,16 @@ impl Tracer for ExecutiveTracer { } } +struct TraceData { + mem_written: Option<(usize, usize)>, + store_written: Option<(U256, U256)>, +} + /// Simple VM tracer. Traces all operations. pub struct ExecutiveVMTracer { data: VMTrace, depth: usize, - last_mem_written: Option<(usize, usize)>, - last_store_written: Option<(U256, U256)>, + trace_stack: Vec, } impl ExecutiveVMTracer { @@ -212,8 +218,7 @@ impl ExecutiveVMTracer { subs: vec![], }, depth: 0, - last_mem_written: None, - last_store_written: None, + trace_stack: vec![], } } @@ -240,18 +245,27 @@ impl VMTracer for ExecutiveVMTracer { executed: None, }); }); - self.last_mem_written = mem_written; - self.last_store_written = store_written; + self.trace_stack.push(TraceData { mem_written, store_written }); + } + + fn trace_failed(&mut self) { + let _ = self.trace_stack.pop().expect("pushed in trace_prepare_execute; qed"); } fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem: &[u8]) { - let mem_diff = self.last_mem_written.take().map(|(o, s)| (o, &(mem[o..o+s]))); - let store_diff = self.last_store_written.take(); + let TraceData { mem_written, store_written } = self.trace_stack.pop().expect("pushed in trace_prepare_execute; qed"); + let mem_diff = mem_written.map(|(o, s)| { + if o + s > mem.len() { + warn!(target: "trace", "mem_written is out of bounds"); + } + (o, &mem[min(mem.len(), o)..min(o + s, mem.len())]) + }); + let store_diff = store_written; Self::with_trace_in_depth(&mut self.data, self.depth, move |trace| { let ex = VMExecutedOperation { gas_used: gas_used, - stack_push: stack_push.iter().cloned().collect(), - mem_diff: mem_diff.map(|(s, r)| MemoryDiff { offset: s, data: r.iter().cloned().collect() }), + stack_push: stack_push.to_vec(), + mem_diff: mem_diff.map(|(s, r)| MemoryDiff { offset: s, data: r.to_vec() }), store_diff: store_diff.map(|(l, v)| StorageDiff { location: l, value: v }), }; trace.operations.last_mut().expect("trace_executed is always called after a trace_prepare_execute; trace.operations cannot be empty; qed").executed = Some(ex); diff --git a/ethcore/src/trace/mod.rs b/ethcore/src/trace/mod.rs index d358661475..98521dbb0c 100644 --- a/ethcore/src/trace/mod.rs +++ b/ethcore/src/trace/mod.rs @@ -85,6 +85,9 @@ pub trait VMTracer: Send { /// Trace the preparation to execute a single valid instruction. fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: U256, _mem_written: Option<(usize, usize)>, _store_written: Option<(U256, U256)>) {} + /// Trace the execution failure of a single instruction. + fn trace_failed(&mut self) {} + /// Trace the finalised execution of a single valid instruction. fn trace_executed(&mut self, _gas_used: U256, _stack_push: &[U256], _mem: &[u8]) {} diff --git a/ethcore/src/trace/types/filter.rs b/ethcore/src/trace/types/filter.rs index 00fe38e484..d7b8fcc180 100644 --- a/ethcore/src/trace/types/filter.rs +++ b/ethcore/src/trace/types/filter.rs @@ -106,7 +106,7 @@ impl Filter { let to_matches = match trace.result { Res::Create(ref create_result) => self.to_address.matches(&create_result.address), - _ => false + _ => self.to_address.matches_all(), }; from_matches && to_matches @@ -385,4 +385,44 @@ mod tests { assert!(f1.matches(&trace)); assert!(f2.matches(&trace)); } + + #[test] + fn filter_match_failed_contract_creation_fix_9822() { + + let f0 = Filter { + range: (0..0), + from_address: vec![1.into()].into(), + to_address: vec![].into(), + }; + + let f1 = Filter { + range: (0..0), + from_address: vec![].into(), + to_address: vec![].into(), + }; + + let f2 = Filter { + range: (0..0), + from_address: vec![].into(), + to_address: vec![2.into()].into(), + }; + + let trace = FlatTrace { + action: Action::Create(Create { + from: 1.into(), + gas: 4.into(), + init: vec![0x5], + value: 3.into(), + }), + result: Res::FailedCall(TraceError::BadInstruction), + trace_address: vec![].into_iter().collect(), + subtraces: 0 + }; + + assert!(f0.matches(&trace)); + assert!(f1.matches(&trace)); + assert!(!f2.matches(&trace)); + } + } + diff --git a/ethcore/src/trace/types/trace.rs b/ethcore/src/trace/types/trace.rs index 18ec24a84f..16084e94cb 100644 --- a/ethcore/src/trace/types/trace.rs +++ b/ethcore/src/trace/types/trace.rs @@ -135,7 +135,7 @@ impl Create { } /// Reward type. -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, Copy)] pub enum RewardType { /// Block Block, diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 3f5008a2b8..61d7119249 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -34,30 +34,13 @@ use unexpected::{Mismatch, OutOfBounds}; use blockchain::*; use call_contract::CallContract; use client::BlockInfo; -use engines::EthEngine; +use engines::{EthEngine, MAX_UNCLE_AGE}; use error::{BlockError, Error}; use types::{BlockNumber, header::Header}; use types::transaction::SignedTransaction; use verification::queue::kind::blocks::Unverified; - -/// Returns `Ok` when the result less or equal to `i32::max_value` to prevent `SystemTime` to panic because -/// it is platform specific, may be i32 or i64. -/// -/// `Err Result { - let d1 = sys.duration_since(UNIX_EPOCH).map_err(|_| BlockError::TimestampOverflow)?; - let total_time = d1.checked_add(d2).ok_or(BlockError::TimestampOverflow)?; - - if total_time.as_secs() <= i32::max_value() as u64 { - Ok(sys + d2) - } else { - Err(BlockError::TimestampOverflow) - } -} +use time_utils::CheckedSystemTime; /// Preprocessed block data gathered in `verify_block_unordered` call pub struct PreverifiedBlock { @@ -192,7 +175,7 @@ fn verify_uncles(block: &PreverifiedBlock, bc: &BlockProvider, engine: &EthEngin excluded.insert(header.hash()); let mut hash = header.parent_hash().clone(); excluded.insert(hash.clone()); - for _ in 0..engine.maximum_uncle_age() { + for _ in 0..MAX_UNCLE_AGE { match bc.block_details(&hash) { Some(details) => { excluded.insert(details.parent); @@ -225,7 +208,7 @@ fn verify_uncles(block: &PreverifiedBlock, bc: &BlockProvider, engine: &EthEngin // (8 Invalid) let depth = if header.number() > uncle.number() { header.number() - uncle.number() } else { 0 }; - if depth > engine.maximum_uncle_age() as u64 { + if depth > MAX_UNCLE_AGE as u64 { return Err(From::from(BlockError::UncleTooOld(OutOfBounds { min: Some(header.number() - depth), max: Some(header.number() - 1), found: uncle.number() }))); } else if depth < 1 { @@ -274,7 +257,7 @@ pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> return Err(From::from(BlockError::InvalidGasUsed(Mismatch { expected: *expected.gas_used(), found: *got.gas_used() }))) } if expected.log_bloom() != got.log_bloom() { - return Err(From::from(BlockError::InvalidLogBloom(Mismatch { expected: *expected.log_bloom(), found: *got.log_bloom() }))) + return Err(From::from(BlockError::InvalidLogBloom(Box::new(Mismatch { expected: *expected.log_bloom(), found: *got.log_bloom() })))) } if expected.receipts_root() != got.receipts_root() { return Err(From::from(BlockError::InvalidReceiptsRoot(Mismatch { expected: *expected.receipts_root(), found: *got.receipts_root() }))) @@ -323,9 +306,11 @@ pub fn verify_header_params(header: &Header, engine: &EthEngine, is_full: bool, if is_full { const ACCEPTABLE_DRIFT: Duration = Duration::from_secs(15); + // this will resist overflow until `year 2037` let max_time = SystemTime::now() + ACCEPTABLE_DRIFT; let invalid_threshold = max_time + ACCEPTABLE_DRIFT * 9; - let timestamp = timestamp_checked_add(UNIX_EPOCH, Duration::from_secs(header.timestamp()))?; + let timestamp = CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::from_secs(header.timestamp())) + .ok_or(BlockError::TimestampOverflow)?; if timestamp > invalid_threshold { return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: Some(max_time), min: None, found: timestamp }))) @@ -347,8 +332,11 @@ fn verify_parent(header: &Header, parent: &Header, engine: &EthEngine) -> Result let gas_limit_divisor = engine.params().gas_limit_bound_divisor; if !engine.is_timestamp_valid(header.timestamp(), parent.timestamp()) { - let min = timestamp_checked_add(SystemTime::now(), Duration::from_secs(parent.timestamp().saturating_add(1)))?; - let found = timestamp_checked_add(SystemTime::now(), Duration::from_secs(header.timestamp()))?; + let now = SystemTime::now(); + let min = CheckedSystemTime::checked_add(now, Duration::from_secs(parent.timestamp().saturating_add(1))) + .ok_or(BlockError::TimestampOverflow)?; + let found = CheckedSystemTime::checked_add(now, Duration::from_secs(header.timestamp())) + .ok_or(BlockError::TimestampOverflow)?; return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: None, min: Some(min), found }))) } if header.number() != parent.number() + 1 { @@ -835,11 +823,4 @@ mod tests { check_fail(unordered_test(&create_test_block_with_data(&header, &bad_transactions, &[]), &engine), TooManyTransactions(keypair.address())); unordered_test(&create_test_block_with_data(&header, &good_transactions, &[]), &engine).unwrap(); } - - #[test] - fn checked_add_systime_dur() { - assert!(timestamp_checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64 + 1, 0)).is_err()); - assert!(timestamp_checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64, 0)).is_ok()); - assert!(timestamp_checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64 - 1, 1_000_000_000)).is_ok()); - } } diff --git a/ethcore/sync/Cargo.toml b/ethcore/sync/Cargo.toml index c8545c00f0..66515ef3ba 100644 --- a/ethcore/sync/Cargo.toml +++ b/ethcore/sync/Cargo.toml @@ -1,5 +1,5 @@ [package] -description = "Ethcore blockchain sync" +description = "Parity Ethereum (EthCore) Blockchain Synchronization (Strategy, Blockchain Downloader, Blockchain Synchronization Implementation of Ethereum Protocol, Propagating Data to Peers, Requesting Data from Peers, Supplying Data in Response to Peer Requests, Handling Peer Responses, Matching Packet IDs and Protocol, Light Client Synchronization of Header Chain, Header Download State Machine, Light Decoding & Verifying Header Responses, Private Transaction Handling, Synchronization Snapshot Service to Download & Verify Block Chunks, Peer Connection Management and Blockchain Client I/O Interface for Synchronization Handler, Transaction Statistics)" name = "ethcore-sync" version = "1.12.0" license = "GPL-3.0" @@ -9,16 +9,17 @@ authors = ["Parity Technologies "] [dependencies] common-types = { path = "../types" } -env_logger = "0.5" +enum_primitive = "0.1.1" ethcore = { path = ".." } ethcore-io = { path = "../../util/io" } ethcore-light = { path = "../light" } ethcore-network = { path = "../../util/network" } ethcore-network-devp2p = { path = "../../util/network-devp2p" } ethereum-types = "0.4" +ethkey = { path = "../../accounts/ethkey" } ethstore = { path = "../../accounts/ethstore" } fastmap = { path = "../../util/fastmap" } -hashdb = "0.3.0" +hash-db = "0.11.0" heapsize = "0.4" keccak-hash = "0.1" keccak-hasher = { path = "../../util/keccak-hasher" } @@ -34,9 +35,8 @@ triehash-ethereum = {version = "0.2", path = "../../util/triehash-ethereum" } [dev-dependencies] env_logger = "0.5" +ethcore = { path = "..", features = ["test-helpers"] } ethcore-io = { path = "../../util/io", features = ["mio"] } -ethkey = { path = "../../accounts/ethkey" } -kvdb-memorydb = "0.1" ethcore-private-tx = { path = "../private-tx" } -ethcore = { path = "..", features = ["test-helpers"] } +kvdb-memorydb = "0.1" rustc-hex = "1.0" diff --git a/ethcore/sync/src/api.rs b/ethcore/sync/src/api.rs index 253f7fe838..4a66f468d5 100644 --- a/ethcore/sync/src/api.rs +++ b/ethcore/sync/src/api.rs @@ -17,18 +17,19 @@ use std::sync::{Arc, mpsc, atomic}; use std::collections::{HashMap, BTreeMap}; use std::io; -use std::ops::Range; +use std::ops::RangeInclusive; use std::time::Duration; use bytes::Bytes; use devp2p::NetworkService; use network::{NetworkProtocolHandler, NetworkContext, PeerId, ProtocolId, NetworkConfiguration as BasicNetworkConfiguration, NonReservedPeerMode, Error, ErrorKind, ConnectionFilter}; +use network::client_version::ClientVersion; use types::pruning_info::PruningInfo; use ethereum_types::{H256, H512, U256}; use io::{TimerToken}; -use ethstore::ethkey::Secret; +use ethkey::Secret; use ethcore::client::{BlockChainClient, ChainNotify, NewBlocks, ChainMessageType}; use ethcore::snapshot::SnapshotService; use types::BlockNumber; @@ -38,8 +39,8 @@ use std::net::{SocketAddr, AddrParseError}; use std::str::FromStr; use parking_lot::{RwLock, Mutex}; use chain::{ETH_PROTOCOL_VERSION_63, ETH_PROTOCOL_VERSION_62, - PAR_PROTOCOL_VERSION_1, PAR_PROTOCOL_VERSION_2, PAR_PROTOCOL_VERSION_3, - PRIVATE_TRANSACTION_PACKET, SIGNED_PRIVATE_TRANSACTION_PACKET}; + PAR_PROTOCOL_VERSION_1, PAR_PROTOCOL_VERSION_2, PAR_PROTOCOL_VERSION_3}; +use chain::sync_packet::SyncPacket::{PrivateTransactionPacket, SignedPrivateTransactionPacket}; use light::client::AsLightClient; use light::Provider; use light::net::{ @@ -50,6 +51,8 @@ use network::IpFilter; use private_tx::PrivateTxHandler; use types::transaction::UnverifiedTransaction; +use super::light_sync::SyncInfo; + /// Parity sync protocol pub const WARP_SYNC_PROTOCOL_ID: ProtocolId = *b"par"; /// Ethereum sync protocol @@ -158,7 +161,7 @@ pub struct PeerInfo { /// Public node id pub id: Option, /// Node client ID - pub client_version: String, + pub client_version: ClientVersion, /// Capabilities pub capabilities: Vec, /// Remote endpoint address @@ -576,9 +579,9 @@ impl ChainNotify for EthSync { match message_type { ChainMessageType::Consensus(message) => self.eth_handler.sync.write().propagate_consensus_packet(&mut sync_io, message), ChainMessageType::PrivateTransaction(transaction_hash, message) => - self.eth_handler.sync.write().propagate_private_transaction(&mut sync_io, transaction_hash, PRIVATE_TRANSACTION_PACKET, message), + self.eth_handler.sync.write().propagate_private_transaction(&mut sync_io, transaction_hash, PrivateTransactionPacket, message), ChainMessageType::SignedPrivateTransaction(transaction_hash, message) => - self.eth_handler.sync.write().propagate_private_transaction(&mut sync_io, transaction_hash, SIGNED_PRIVATE_TRANSACTION_PACKET, message), + self.eth_handler.sync.write().propagate_private_transaction(&mut sync_io, transaction_hash, SignedPrivateTransactionPacket, message), } }); } @@ -615,9 +618,7 @@ pub trait ManageNetwork : Send + Sync { /// Stop network fn stop_network(&self); /// Returns the minimum and maximum peers. - /// Note that `range.end` is *exclusive*. - // TODO: Range should be changed to RangeInclusive once stable (https://github.com/rust-lang/rust/pull/50758) - fn num_peers_range(&self) -> Range; + fn num_peers_range(&self) -> RangeInclusive; /// Get network context for protocol. fn with_proto_context(&self, proto: ProtocolId, f: &mut FnMut(&NetworkContext)); } @@ -656,7 +657,7 @@ impl ManageNetwork for EthSync { self.stop(); } - fn num_peers_range(&self) -> Range { + fn num_peers_range(&self) -> RangeInclusive { self.network.num_peers_range() } @@ -805,6 +806,24 @@ pub trait LightSyncProvider { fn transactions_stats(&self) -> BTreeMap; } +/// Wrapper around `light_sync::SyncInfo` to expose those methods without the concrete type `LightSync` +pub trait LightSyncInfo: Send + Sync { + /// Get the highest block advertised on the network. + fn highest_block(&self) -> Option; + + /// Get the block number at the time of sync start. + fn start_block(&self) -> u64; + + /// Whether major sync is underway. + fn is_major_importing(&self) -> bool; +} + +/// Execute a closure with a protocol context. +pub trait LightNetworkDispatcher { + /// Execute a closure with a protocol context. + fn with_context(&self, f: F) -> Option where F: FnOnce(&::light::net::BasicContext) -> T; +} + /// Configuration for the light sync. pub struct LightSyncParams { /// Network configuration. @@ -824,7 +843,7 @@ pub struct LightSyncParams { /// Service for light synchronization. pub struct LightSync { proto: Arc, - sync: Arc<::light_sync::SyncInfo + Sync + Send>, + sync: Arc, attached_protos: Vec, network: NetworkService, subprotocol_name: [u8; 3], @@ -875,15 +894,6 @@ impl LightSync { }) } - /// Execute a closure with a protocol context. - pub fn with_context(&self, f: F) -> Option - where F: FnOnce(&::light::net::BasicContext) -> T - { - self.network.with_context_eval( - self.subprotocol_name, - move |ctx| self.proto.with_context(&ctx, f), - ) - } } impl ::std::ops::Deref for LightSync { @@ -892,6 +902,16 @@ impl ::std::ops::Deref for LightSync { fn deref(&self) -> &Self::Target { &*self.sync } } + +impl LightNetworkDispatcher for LightSync { + fn with_context(&self, f: F) -> Option where F: FnOnce(&::light::net::BasicContext) -> T { + self.network.with_context_eval( + self.subprotocol_name, + move |ctx| self.proto.with_context(&ctx, f), + ) + } +} + impl ManageNetwork for LightSync { fn accept_unreserved_peers(&self) { self.network.set_non_reserved_mode(NonReservedPeerMode::Accept); @@ -935,7 +955,7 @@ impl ManageNetwork for LightSync { self.network.stop(); } - fn num_peers_range(&self) -> Range { + fn num_peers_range(&self) -> RangeInclusive { self.network.num_peers_range() } @@ -948,12 +968,12 @@ impl LightSyncProvider for LightSync { fn peer_numbers(&self) -> PeerNumbers { let (connected, active) = self.proto.peer_count(); let peers_range = self.num_peers_range(); - debug_assert!(peers_range.end > peers_range.start); + debug_assert!(peers_range.end() >= peers_range.start()); PeerNumbers { connected: connected, active: active, - max: peers_range.end as usize - 1, - min: peers_range.start as usize, + max: *peers_range.end() as usize, + min: *peers_range.start() as usize, } } @@ -992,3 +1012,17 @@ impl LightSyncProvider for LightSync { Default::default() // TODO } } + +impl LightSyncInfo for LightSync { + fn highest_block(&self) -> Option { + (*self.sync).highest_block() + } + + fn start_block(&self) -> u64 { + (*self.sync).start_block() + } + + fn is_major_importing(&self) -> bool { + (*self.sync).is_major_importing() + } +} diff --git a/ethcore/sync/src/block_sync.rs b/ethcore/sync/src/block_sync.rs index 2331e214c5..04ffa5f18d 100644 --- a/ethcore/sync/src/block_sync.rs +++ b/ethcore/sync/src/block_sync.rs @@ -29,10 +29,13 @@ use ethcore::error::{ImportErrorKind, QueueErrorKind, BlockError, Error as Ethco use sync_io::SyncIo; use blocks::{BlockCollection, SyncBody, SyncHeader}; use chain::BlockSet; +use network::PeerId; +use network::client_version::ClientCapabilities; const MAX_HEADERS_TO_REQUEST: usize = 128; -const MAX_BODIES_TO_REQUEST: usize = 32; -const MAX_RECEPITS_TO_REQUEST: usize = 128; +const MAX_BODIES_TO_REQUEST_LARGE: usize = 128; +const MAX_BODIES_TO_REQUEST_SMALL: usize = 32; // Size request for parity clients prior to 2.4.0 +const MAX_RECEPITS_TO_REQUEST: usize = 256; const SUBCHAIN_SIZE: u64 = 256; const MAX_ROUND_PARENTS: usize = 16; const MAX_PARALLEL_SUBCHAIN_DOWNLOAD: usize = 5; @@ -464,12 +467,12 @@ impl BlockDownloader { } /// Find some headers or blocks to download for a peer. - pub fn request_blocks(&mut self, io: &mut SyncIo, num_active_peers: usize) -> Option { + pub fn request_blocks(&mut self, peer_id: PeerId, io: &mut SyncIo, num_active_peers: usize) -> Option { match self.state { State::Idle => { self.start_sync_round(io); if self.state == State::ChainHead { - return self.request_blocks(io, num_active_peers); + return self.request_blocks(peer_id, io, num_active_peers); } }, State::ChainHead => { @@ -487,7 +490,15 @@ impl BlockDownloader { }, State::Blocks => { // check to see if we need to download any block bodies first - let needed_bodies = self.blocks.needed_bodies(MAX_BODIES_TO_REQUEST, false); + let client_version = io.peer_version(peer_id); + + let number_of_bodies_to_request = if client_version.can_handle_large_requests() { + MAX_BODIES_TO_REQUEST_LARGE + } else { + MAX_BODIES_TO_REQUEST_SMALL + }; + + let needed_bodies = self.blocks.needed_bodies(number_of_bodies_to_request, false); if !needed_bodies.is_empty() { return Some(BlockRequest::Bodies { hashes: needed_bodies, diff --git a/ethcore/sync/src/chain/handler.rs b/ethcore/sync/src/chain/handler.rs index 5630ea2563..63ab891613 100644 --- a/ethcore/sync/src/chain/handler.rs +++ b/ethcore/sync/src/chain/handler.rs @@ -17,12 +17,14 @@ use api::WARP_SYNC_PROTOCOL_ID; use block_sync::{BlockDownloaderImportError as DownloaderImportError, DownloadAction}; use bytes::Bytes; +use enum_primitive::FromPrimitive; use ethcore::error::{Error as EthcoreError, ErrorKind as EthcoreErrorKind, ImportErrorKind, BlockError}; use ethcore::snapshot::{ManifestData, RestorationStatus}; use ethcore::verification::queue::kind::blocks::Unverified; use ethereum_types::{H256, U256}; use hash::keccak; use network::PeerId; +use network::client_version::ClientVersion; use rlp::Rlp; use snapshot::ChunkType; use std::time::Instant; @@ -32,6 +34,20 @@ use types::BlockNumber; use types::block_status::BlockStatus; use types::ids::BlockId; +use super::sync_packet::{PacketInfo, SyncPacket}; +use super::sync_packet::SyncPacket::{ + StatusPacket, + NewBlockHashesPacket, + BlockHeadersPacket, + BlockBodiesPacket, + NewBlockPacket, + ReceiptsPacket, + SnapshotManifestPacket, + SnapshotDataPacket, + PrivateTransactionPacket, + SignedPrivateTransactionPacket, +}; + use super::{ BlockSet, ChainSync, @@ -47,16 +63,6 @@ use super::{ MAX_NEW_HASHES, PAR_PROTOCOL_VERSION_1, PAR_PROTOCOL_VERSION_3, - BLOCK_BODIES_PACKET, - BLOCK_HEADERS_PACKET, - NEW_BLOCK_HASHES_PACKET, - NEW_BLOCK_PACKET, - PRIVATE_TRANSACTION_PACKET, - RECEIPTS_PACKET, - SIGNED_PRIVATE_TRANSACTION_PACKET, - SNAPSHOT_DATA_PACKET, - SNAPSHOT_MANIFEST_PACKET, - STATUS_PACKET, }; /// The Chain Sync Handler: handles responses from peers @@ -66,36 +72,40 @@ impl SyncHandler { /// Handle incoming packet from peer pub fn on_packet(sync: &mut ChainSync, io: &mut SyncIo, peer: PeerId, packet_id: u8, data: &[u8]) { let rlp = Rlp::new(data); - let result = match packet_id { - STATUS_PACKET => SyncHandler::on_peer_status(sync, io, peer, &rlp), - BLOCK_HEADERS_PACKET => SyncHandler::on_peer_block_headers(sync, io, peer, &rlp), - BLOCK_BODIES_PACKET => SyncHandler::on_peer_block_bodies(sync, io, peer, &rlp), - RECEIPTS_PACKET => SyncHandler::on_peer_block_receipts(sync, io, peer, &rlp), - NEW_BLOCK_PACKET => SyncHandler::on_peer_new_block(sync, io, peer, &rlp), - NEW_BLOCK_HASHES_PACKET => SyncHandler::on_peer_new_hashes(sync, io, peer, &rlp), - SNAPSHOT_MANIFEST_PACKET => SyncHandler::on_snapshot_manifest(sync, io, peer, &rlp), - SNAPSHOT_DATA_PACKET => SyncHandler::on_snapshot_data(sync, io, peer, &rlp), - PRIVATE_TRANSACTION_PACKET => SyncHandler::on_private_transaction(sync, io, peer, &rlp), - SIGNED_PRIVATE_TRANSACTION_PACKET => SyncHandler::on_signed_private_transaction(sync, io, peer, &rlp), - _ => { - debug!(target: "sync", "{}: Unknown packet {}", peer, packet_id); - Ok(()) - } - }; + if let Some(packet_id) = SyncPacket::from_u8(packet_id) { + let result = match packet_id { + StatusPacket => SyncHandler::on_peer_status(sync, io, peer, &rlp), + BlockHeadersPacket => SyncHandler::on_peer_block_headers(sync, io, peer, &rlp), + BlockBodiesPacket => SyncHandler::on_peer_block_bodies(sync, io, peer, &rlp), + ReceiptsPacket => SyncHandler::on_peer_block_receipts(sync, io, peer, &rlp), + NewBlockPacket => SyncHandler::on_peer_new_block(sync, io, peer, &rlp), + NewBlockHashesPacket => SyncHandler::on_peer_new_hashes(sync, io, peer, &rlp), + SnapshotManifestPacket => SyncHandler::on_snapshot_manifest(sync, io, peer, &rlp), + SnapshotDataPacket => SyncHandler::on_snapshot_data(sync, io, peer, &rlp), + PrivateTransactionPacket => SyncHandler::on_private_transaction(sync, io, peer, &rlp), + SignedPrivateTransactionPacket => SyncHandler::on_signed_private_transaction(sync, io, peer, &rlp), + _ => { + debug!(target: "sync", "{}: Unknown packet {}", peer, packet_id.id()); + Ok(()) + } + }; - match result { - Err(DownloaderImportError::Invalid) => { - debug!(target:"sync", "{} -> Invalid packet {}", peer, packet_id); - io.disable_peer(peer); - sync.deactivate_peer(io, peer); - }, - Err(DownloaderImportError::Useless) => { - sync.deactivate_peer(io, peer); - }, - Ok(()) => { - // give a task to the same peer first - sync.sync_peer(io, peer, false); - }, + match result { + Err(DownloaderImportError::Invalid) => { + debug!(target:"sync", "{} -> Invalid packet {}", peer, packet_id.id()); + io.disable_peer(peer); + sync.deactivate_peer(io, peer); + }, + Err(DownloaderImportError::Useless) => { + sync.deactivate_peer(io, peer); + }, + Ok(()) => { + // give a task to the same peer first + sync.sync_peer(io, peer, false); + }, + } + } else { + debug!(target: "sync", "{}: Unknown packet {}", peer, packet_id); } } @@ -107,7 +117,7 @@ impl SyncHandler { /// Called by peer when it is disconnecting pub fn on_peer_aborting(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId) { - trace!(target: "sync", "== Disconnecting {}: {}", peer_id, io.peer_info(peer_id)); + trace!(target: "sync", "== Disconnecting {}: {}", peer_id, io.peer_version(peer_id)); sync.handshaking_peers.remove(&peer_id); if sync.peers.contains_key(&peer_id) { debug!(target: "sync", "Disconnected {}", peer_id); @@ -133,7 +143,7 @@ impl SyncHandler { /// Called when a new peer is connected pub fn on_peer_connected(sync: &mut ChainSync, io: &mut SyncIo, peer: PeerId) { - trace!(target: "sync", "== Connected {}: {}", peer, io.peer_info(peer)); + trace!(target: "sync", "== Connected {}: {}", peer, io.peer_version(peer)); if let Err(e) = sync.send_status(io, peer) { debug!(target:"sync", "Error sending status request: {:?}", e); io.disconnect_peer(peer); @@ -579,6 +589,7 @@ impl SyncHandler { snapshot_number: if warp_protocol { Some(r.val_at(6)?) } else { None }, block_set: None, private_tx_enabled: if private_tx_protocol { r.val_at(7).unwrap_or(false) } else { false }, + client_version: ClientVersion::from(io.peer_version(peer_id)), }; trace!(target: "sync", "New peer {} (\ @@ -599,12 +610,12 @@ impl SyncHandler { peer.private_tx_enabled ); if io.is_expired() { - trace!(target: "sync", "Status packet from expired session {}:{}", peer_id, io.peer_info(peer_id)); + trace!(target: "sync", "Status packet from expired session {}:{}", peer_id, io.peer_version(peer_id)); return Ok(()); } if sync.peers.contains_key(&peer_id) { - debug!(target: "sync", "Unexpected status packet from {}:{}", peer_id, io.peer_info(peer_id)); + debug!(target: "sync", "Unexpected status packet from {}:{}", peer_id, io.peer_version(peer_id)); return Ok(()); } let chain_info = io.chain().chain_info(); @@ -633,7 +644,7 @@ impl SyncHandler { // Don't activate peer immediatelly when searching for common block. // Let the current sync round complete first. sync.active_peers.insert(peer_id.clone()); - debug!(target: "sync", "Connected {}:{}", peer_id, io.peer_info(peer_id)); + debug!(target: "sync", "Connected {}:{}", peer_id, io.peer_version(peer_id)); if let Some((fork_block, _)) = sync.fork_block { SyncRequester::request_fork_header(sync, io, peer_id, fork_block); diff --git a/ethcore/sync/src/chain/mod.rs b/ethcore/sync/src/chain/mod.rs index 669ddeefd4..4b918bd00c 100644 --- a/ethcore/sync/src/chain/mod.rs +++ b/ethcore/sync/src/chain/mod.rs @@ -88,6 +88,7 @@ //! All other messages are ignored. mod handler; +pub mod sync_packet; mod propagator; mod requester; mod supplier; @@ -104,6 +105,7 @@ use parking_lot::{Mutex, RwLock, RwLockWriteGuard}; use bytes::Bytes; use rlp::{RlpStream, DecoderError}; use network::{self, PeerId, PacketId}; +use network::client_version::ClientVersion; use ethcore::client::{BlockChainClient, BlockStatus, BlockId, BlockChainInfo, BlockQueueInfo}; use ethcore::snapshot::{RestorationStatus}; use sync_io::SyncIo; @@ -118,6 +120,12 @@ use types::transaction::UnverifiedTransaction; use types::BlockNumber; use self::handler::SyncHandler; +use self::sync_packet::{PacketInfo, SyncPacket}; +use self::sync_packet::SyncPacket::{ + NewBlockPacket, + StatusPacket, +}; + use self::propagator::SyncPropagator; use self::requester::SyncRequester; pub(crate) use self::supplier::SyncSupplier; @@ -153,28 +161,6 @@ const MAX_TRANSACTION_PACKET_SIZE: usize = 5 * 1024 * 1024; const SNAPSHOT_RESTORE_THRESHOLD: BlockNumber = 30000; const SNAPSHOT_MIN_PEERS: usize = 3; -const STATUS_PACKET: u8 = 0x00; -const NEW_BLOCK_HASHES_PACKET: u8 = 0x01; -const TRANSACTIONS_PACKET: u8 = 0x02; -pub const GET_BLOCK_HEADERS_PACKET: u8 = 0x03; -pub const BLOCK_HEADERS_PACKET: u8 = 0x04; -pub const GET_BLOCK_BODIES_PACKET: u8 = 0x05; -const BLOCK_BODIES_PACKET: u8 = 0x06; -const NEW_BLOCK_PACKET: u8 = 0x07; - -pub const GET_NODE_DATA_PACKET: u8 = 0x0d; -pub const NODE_DATA_PACKET: u8 = 0x0e; -pub const GET_RECEIPTS_PACKET: u8 = 0x0f; -pub const RECEIPTS_PACKET: u8 = 0x10; - -pub const GET_SNAPSHOT_MANIFEST_PACKET: u8 = 0x11; -pub const SNAPSHOT_MANIFEST_PACKET: u8 = 0x12; -pub const GET_SNAPSHOT_DATA_PACKET: u8 = 0x13; -pub const SNAPSHOT_DATA_PACKET: u8 = 0x14; -pub const CONSENSUS_DATA_PACKET: u8 = 0x15; -pub const PRIVATE_TRANSACTION_PACKET: u8 = 0x16; -pub const SIGNED_PRIVATE_TRANSACTION_PACKET: u8 = 0x17; - const MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD: usize = 3; const WAIT_PEERS_TIMEOUT: Duration = Duration::from_secs(5); @@ -342,6 +328,8 @@ pub struct PeerInfo { snapshot_number: Option, /// Block set requested block_set: Option, + /// Version of the software the peer is running + client_version: ClientVersion, } impl PeerInfo { @@ -481,7 +469,7 @@ impl ChainSyncApi { for peers in sync.get_peers(&chain_info, PeerState::SameBlock).chunks(10) { check_deadline(deadline)?; for peer in peers { - SyncPropagator::send_packet(io, *peer, NEW_BLOCK_PACKET, rlp.clone()); + SyncPropagator::send_packet(io, *peer, NewBlockPacket, rlp.clone()); if let Some(ref mut peer) = sync.peers.get_mut(peer) { peer.latest_hash = hash; } @@ -964,7 +952,7 @@ impl ChainSync { if !have_latest && (higher_difficulty || force || self.state == SyncState::NewBlocks) { // check if got new blocks to download trace!(target: "sync", "Syncing with peer {}, force={}, td={:?}, our td={}, state={:?}", peer_id, force, peer_difficulty, syncing_difficulty, self.state); - if let Some(request) = self.new_blocks.request_blocks(io, num_active_peers) { + if let Some(request) = self.new_blocks.request_blocks(peer_id, io, num_active_peers) { SyncRequester::request_blocks(self, io, peer_id, request, BlockSet::NewBlocks); if self.state == SyncState::Idle { self.state = SyncState::Blocks; @@ -974,10 +962,10 @@ impl ChainSync { } // Only ask for old blocks if the peer has an equal or higher difficulty - let equal_or_higher_difficulty = peer_difficulty.map_or(false, |pd| pd >= syncing_difficulty); + let equal_or_higher_difficulty = peer_difficulty.map_or(true, |pd| pd >= syncing_difficulty); if force || equal_or_higher_difficulty { - if let Some(request) = self.old_blocks.as_mut().and_then(|d| d.request_blocks(io, num_active_peers)) { + if let Some(request) = self.old_blocks.as_mut().and_then(|d| d.request_blocks(peer_id, io, num_active_peers)) { SyncRequester::request_blocks(self, io, peer_id, request, BlockSet::OldBlocks); return; } @@ -1143,7 +1131,7 @@ impl ChainSync { } } packet.complete_unbounded_list(); - io.respond(STATUS_PACKET, packet.out()) + io.respond(StatusPacket.id(), packet.out()) } pub fn maintain_peers(&mut self, io: &mut SyncIo) { @@ -1328,7 +1316,7 @@ impl ChainSync { } /// Broadcast private transaction message to peers. - pub fn propagate_private_transaction(&mut self, io: &mut SyncIo, transaction_hash: H256, packet_id: PacketId, packet: Bytes) { + pub fn propagate_private_transaction(&mut self, io: &mut SyncIo, transaction_hash: H256, packet_id: SyncPacket, packet: Bytes) { SyncPropagator::propagate_private_transaction(self, io, transaction_hash, packet_id, packet); } } @@ -1459,6 +1447,7 @@ pub mod tests { snapshot_hash: None, asking_snapshot_data: None, block_set: None, + client_version: ClientVersion::from(""), }); } diff --git a/ethcore/sync/src/chain/propagator.rs b/ethcore/sync/src/chain/propagator.rs index 74ef27e887..c3654553ff 100644 --- a/ethcore/sync/src/chain/propagator.rs +++ b/ethcore/sync/src/chain/propagator.rs @@ -20,7 +20,8 @@ use std::collections::HashSet; use bytes::Bytes; use ethereum_types::H256; use fastmap::H256FastSet; -use network::{PeerId, PacketId}; +use network::client_version::ClientCapabilities; +use network::PeerId; use rand::Rng; use rlp::{Encodable, RlpStream}; use sync_io::SyncIo; @@ -28,6 +29,14 @@ use types::transaction::SignedTransaction; use types::BlockNumber; use types::blockchain_info::BlockChainInfo; +use super::sync_packet::SyncPacket; +use super::sync_packet::SyncPacket::{ + NewBlockHashesPacket, + TransactionsPacket, + NewBlockPacket, + ConsensusDataPacket, +}; + use super::{ random, ChainSync, @@ -35,35 +44,8 @@ use super::{ MAX_PEER_LAG_PROPAGATION, MAX_PEERS_PROPAGATION, MIN_PEERS_PROPAGATION, - CONSENSUS_DATA_PACKET, - NEW_BLOCK_HASHES_PACKET, - NEW_BLOCK_PACKET, - TRANSACTIONS_PACKET, }; -/// Checks if peer is able to process service transactions -fn accepts_service_transaction(client_id: &str) -> bool { - // Parity versions starting from this will accept service-transactions - const SERVICE_TRANSACTIONS_VERSION: (u32, u32) = (1u32, 6u32); - // Parity client string prefix - const LEGACY_CLIENT_ID_PREFIX: &'static str = "Parity/"; - const PARITY_CLIENT_ID_PREFIX: &'static str = "Parity-Ethereum/"; - const VERSION_PREFIX: &'static str = "/v"; - - let idx = client_id.rfind(VERSION_PREFIX).map(|idx| idx + VERSION_PREFIX.len()).unwrap_or(client_id.len()); - let splitted = if client_id.starts_with(LEGACY_CLIENT_ID_PREFIX) || client_id.starts_with(PARITY_CLIENT_ID_PREFIX) { - client_id[idx..].split('.') - } else { - return false; - }; - - let ver: Vec = splitted - .take(2) - .filter_map(|s| s.parse().ok()) - .collect(); - ver.len() == 2 && (ver[0] > SERVICE_TRANSACTIONS_VERSION.0 || (ver[0] == SERVICE_TRANSACTIONS_VERSION.0 && ver[1] >= SERVICE_TRANSACTIONS_VERSION.1)) -} - /// The Chain Sync Propagator: propagates data to peers pub struct SyncPropagator; @@ -74,7 +56,8 @@ impl SyncPropagator { let sent = peers.len(); let mut send_packet = |io: &mut SyncIo, rlp: Bytes| { for peer_id in peers { - SyncPropagator::send_packet(io, *peer_id, NEW_BLOCK_PACKET, rlp.clone()); + SyncPropagator::send_packet(io, *peer_id, NewBlockPacket, rlp.clone()); + if let Some(ref mut peer) = sync.peers.get_mut(peer_id) { peer.latest_hash = chain_info.best_block_hash.clone(); } @@ -109,7 +92,7 @@ impl SyncPropagator { if let Some(ref mut peer) = sync.peers.get_mut(peer_id) { peer.latest_hash = best_block_hash; } - SyncPropagator::send_packet(io, *peer_id, NEW_BLOCK_HASHES_PACKET, rlp.clone()); + SyncPropagator::send_packet(io, *peer_id, NewBlockHashesPacket, rlp.clone()); } sent } @@ -146,7 +129,7 @@ impl SyncPropagator { // most of times service_transactions will be empty // => there's no need to merge packets if !service_transactions.is_empty() { - let service_transactions_peers = SyncPropagator::select_peers_for_transactions(sync, |peer_id| accepts_service_transaction(&io.peer_info(*peer_id))); + let service_transactions_peers = SyncPropagator::select_peers_for_transactions(sync, |peer_id| io.peer_version(*peer_id).accepts_service_transaction()); let service_transactions_affected_peers = SyncPropagator::propagate_transactions_to_peers( sync, io, service_transactions_peers, service_transactions, &mut should_continue ); @@ -177,7 +160,7 @@ impl SyncPropagator { let send_packet = |io: &mut SyncIo, peer_id: PeerId, sent: usize, rlp: Bytes| { let size = rlp.len(); - SyncPropagator::send_packet(io, peer_id, TRANSACTIONS_PACKET, rlp); + SyncPropagator::send_packet(io, peer_id, TransactionsPacket, rlp); trace!(target: "sync", "{:02} <- Transactions ({} entries; {} bytes)", peer_id, sent, size); }; @@ -296,7 +279,7 @@ impl SyncPropagator { io.chain().chain_info().total_difficulty ); for peer_id in &peers { - SyncPropagator::send_packet(io, *peer_id, NEW_BLOCK_PACKET, rlp.clone()); + SyncPropagator::send_packet(io, *peer_id, NewBlockPacket, rlp.clone()); } } } @@ -306,12 +289,12 @@ impl SyncPropagator { let lucky_peers = ChainSync::select_random_peers(&sync.get_consensus_peers()); trace!(target: "sync", "Sending consensus packet to {:?}", lucky_peers); for peer_id in lucky_peers { - SyncPropagator::send_packet(io, peer_id, CONSENSUS_DATA_PACKET, packet.clone()); + SyncPropagator::send_packet(io, peer_id, ConsensusDataPacket, packet.clone()); } } /// Broadcast private transaction message to peers. - pub fn propagate_private_transaction(sync: &mut ChainSync, io: &mut SyncIo, transaction_hash: H256, packet_id: PacketId, packet: Bytes) { + pub fn propagate_private_transaction(sync: &mut ChainSync, io: &mut SyncIo, transaction_hash: H256, packet_id: SyncPacket, packet: Bytes) { let lucky_peers = ChainSync::select_random_peers(&sync.get_private_transaction_peers(&transaction_hash)); if lucky_peers.is_empty() { error!(target: "privatetx", "Cannot propagate the packet, no peers with private tx enabled connected"); @@ -342,7 +325,7 @@ impl SyncPropagator { } /// Generic packet sender - pub fn send_packet(sync: &mut SyncIo, peer_id: PeerId, packet_id: PacketId, packet: Bytes) { + pub fn send_packet(sync: &mut SyncIo, peer_id: PeerId, packet_id: SyncPacket, packet: Bytes) { if let Err(e) = sync.send(peer_id, packet_id, packet) { debug!(target:"sync", "Error sending packet: {:?}", e); sync.disconnect_peer(peer_id); @@ -451,6 +434,7 @@ mod tests { snapshot_hash: None, asking_snapshot_data: None, block_set: None, + client_version: ClientVersion::from(""), }); let ss = TestSnapshotService::new(); let mut io = TestIo::new(&mut client, &ss, &queue, None); @@ -598,20 +582,17 @@ mod tests { io.peers_info.insert(1, "Geth".to_owned()); // and peer#2 is Parity, accepting service transactions insert_dummy_peer(&mut sync, 2, block_hash); - io.peers_info.insert(2, "Parity-Ethereum/v2.6".to_owned()); - // and peer#3 is Parity, discarding service transactions + io.peers_info.insert(2, "Parity-Ethereum/v2.6.0/linux/rustc".to_owned()); + // and peer#3 is Parity, accepting service transactions insert_dummy_peer(&mut sync, 3, block_hash); - io.peers_info.insert(3, "Parity/v1.5".to_owned()); - // and peer#4 is Parity, accepting service transactions - insert_dummy_peer(&mut sync, 4, block_hash); - io.peers_info.insert(4, "Parity-Ethereum/ABCDEFGH/v2.7.3".to_owned()); + io.peers_info.insert(3, "Parity-Ethereum/ABCDEFGH/v2.7.3/linux/rustc".to_owned()); // and new service transaction is propagated to peers SyncPropagator::propagate_new_transactions(&mut sync, &mut io, || true); - // peer#2 && peer#4 are receiving service transaction + // peer#2 && peer#3 are receiving service transaction assert!(io.packets.iter().any(|p| p.packet_id == 0x02 && p.recipient == 2)); // TRANSACTIONS_PACKET - assert!(io.packets.iter().any(|p| p.packet_id == 0x02 && p.recipient == 4)); // TRANSACTIONS_PACKET + assert!(io.packets.iter().any(|p| p.packet_id == 0x02 && p.recipient == 3)); // TRANSACTIONS_PACKET assert_eq!(io.packets.len(), 2); } @@ -628,7 +609,7 @@ mod tests { // when peer#1 is Parity, accepting service transactions insert_dummy_peer(&mut sync, 1, block_hash); - io.peers_info.insert(1, "Parity-Ethereum/v2.6".to_owned()); + io.peers_info.insert(1, "Parity-Ethereum/v2.6.0/linux/rustc".to_owned()); // and service + non-service transactions are propagated to peers SyncPropagator::propagate_new_transactions(&mut sync, &mut io, || true); diff --git a/ethcore/sync/src/chain/requester.rs b/ethcore/sync/src/chain/requester.rs index 7307ffc448..31d3ce5900 100644 --- a/ethcore/sync/src/chain/requester.rs +++ b/ethcore/sync/src/chain/requester.rs @@ -14,26 +14,28 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use api::WARP_SYNC_PROTOCOL_ID; use block_sync::BlockRequest; use bytes::Bytes; use ethereum_types::H256; -use network::{PeerId, PacketId}; +use network::{PeerId}; use rlp::RlpStream; use std::time::Instant; use sync_io::SyncIo; use types::BlockNumber; +use super::sync_packet::SyncPacket; +use super::sync_packet::SyncPacket::{ + GetBlockHeadersPacket, + GetBlockBodiesPacket, + GetReceiptsPacket, + GetSnapshotManifestPacket, + GetSnapshotDataPacket, +}; + use super::{ BlockSet, ChainSync, PeerAsking, - ETH_PROTOCOL_VERSION_63, - GET_BLOCK_BODIES_PACKET, - GET_BLOCK_HEADERS_PACKET, - GET_RECEIPTS_PACKET, - GET_SNAPSHOT_DATA_PACKET, - GET_SNAPSHOT_MANIFEST_PACKET, }; /// The Chain Sync Requester: requesting data to other peers @@ -62,7 +64,7 @@ impl SyncRequester { for h in &hashes { rlp.append(&h.clone()); } - SyncRequester::send_request(sync, io, peer_id, PeerAsking::BlockBodies, GET_BLOCK_BODIES_PACKET, rlp.out()); + SyncRequester::send_request(sync, io, peer_id, PeerAsking::BlockBodies, GetBlockBodiesPacket, rlp.out()); let peer = sync.peers.get_mut(&peer_id).expect("peer_id may originate either from on_packet, where it is already validated or from enumerating self.peers. qed"); peer.asking_blocks = hashes; peer.block_set = Some(set); @@ -76,7 +78,7 @@ impl SyncRequester { rlp.append(&1u32); rlp.append(&0u32); rlp.append(&0u32); - SyncRequester::send_request(sync, io, peer_id, PeerAsking::ForkHeader, GET_BLOCK_HEADERS_PACKET, rlp.out()); + SyncRequester::send_request(sync, io, peer_id, PeerAsking::ForkHeader, GetBlockHeadersPacket, rlp.out()); } /// Find some headers or blocks to download for a peer. @@ -94,7 +96,7 @@ impl SyncRequester { pub fn request_snapshot_manifest(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId) { trace!(target: "sync", "{} <- GetSnapshotManifest", peer_id); let rlp = RlpStream::new_list(0); - SyncRequester::send_request(sync, io, peer_id, PeerAsking::SnapshotManifest, GET_SNAPSHOT_MANIFEST_PACKET, rlp.out()); + SyncRequester::send_request(sync, io, peer_id, PeerAsking::SnapshotManifest, GetSnapshotManifestPacket, rlp.out()); } /// Request headers from a peer by block hash @@ -105,7 +107,7 @@ impl SyncRequester { rlp.append(&count); rlp.append(&skip); rlp.append(&if reverse {1u32} else {0u32}); - SyncRequester::send_request(sync, io, peer_id, PeerAsking::BlockHeaders, GET_BLOCK_HEADERS_PACKET, rlp.out()); + SyncRequester::send_request(sync, io, peer_id, PeerAsking::BlockHeaders, GetBlockHeadersPacket, rlp.out()); let peer = sync.peers.get_mut(&peer_id).expect("peer_id may originate either from on_packet, where it is already validated or from enumerating self.peers. qed"); peer.asking_hash = Some(h.clone()); peer.block_set = Some(set); @@ -118,7 +120,7 @@ impl SyncRequester { for h in &hashes { rlp.append(&h.clone()); } - SyncRequester::send_request(sync, io, peer_id, PeerAsking::BlockReceipts, GET_RECEIPTS_PACKET, rlp.out()); + SyncRequester::send_request(sync, io, peer_id, PeerAsking::BlockReceipts, GetReceiptsPacket, rlp.out()); let peer = sync.peers.get_mut(&peer_id).expect("peer_id may originate either from on_packet, where it is already validated or from enumerating self.peers. qed"); peer.asking_blocks = hashes; peer.block_set = Some(set); @@ -129,23 +131,20 @@ impl SyncRequester { trace!(target: "sync", "{} <- GetSnapshotData {:?}", peer_id, chunk); let mut rlp = RlpStream::new_list(1); rlp.append(chunk); - SyncRequester::send_request(sync, io, peer_id, PeerAsking::SnapshotData, GET_SNAPSHOT_DATA_PACKET, rlp.out()); + SyncRequester::send_request(sync, io, peer_id, PeerAsking::SnapshotData, GetSnapshotDataPacket, rlp.out()); } /// Generic request sender - fn send_request(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, asking: PeerAsking, packet_id: PacketId, packet: Bytes) { + fn send_request(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, asking: PeerAsking, packet_id: SyncPacket, packet: Bytes) { if let Some(ref mut peer) = sync.peers.get_mut(&peer_id) { if peer.asking != PeerAsking::Nothing { warn!(target:"sync", "Asking {:?} while requesting {:?}", peer.asking, asking); } peer.asking = asking; peer.ask_time = Instant::now(); - // TODO [ToDr] This seems quite fragile. Be careful when protocol is updated. - let result = if packet_id >= ETH_PROTOCOL_VERSION_63.1 { - io.send_protocol(WARP_SYNC_PROTOCOL_ID, peer_id, packet_id, packet) - } else { - io.send(peer_id, packet_id, packet) - }; + + let result = io.send(peer_id, packet_id, packet); + if let Err(e) = result { debug!(target:"sync", "Error sending request: {:?}", e); io.disconnect_peer(peer_id); diff --git a/ethcore/sync/src/chain/supplier.rs b/ethcore/sync/src/chain/supplier.rs index 8656abcffd..7e71e6aeec 100644 --- a/ethcore/sync/src/chain/supplier.rs +++ b/ethcore/sync/src/chain/supplier.rs @@ -15,6 +15,7 @@ // along with Parity Ethereum. If not, see . use bytes::Bytes; +use enum_primitive::FromPrimitive; use ethereum_types::H256; use network::{self, PeerId}; use parking_lot::RwLock; @@ -25,30 +26,34 @@ use types::ids::BlockId; use sync_io::SyncIo; +use super::sync_packet::{PacketInfo, SyncPacket}; +use super::sync_packet::SyncPacket::{ + StatusPacket, + TransactionsPacket, + GetBlockHeadersPacket, + BlockHeadersPacket, + GetBlockBodiesPacket, + BlockBodiesPacket, + GetNodeDataPacket, + NodeDataPacket, + GetReceiptsPacket, + ReceiptsPacket, + GetSnapshotManifestPacket, + SnapshotManifestPacket, + GetSnapshotDataPacket, + SnapshotDataPacket, + ConsensusDataPacket, +}; + use super::{ ChainSync, SyncHandler, RlpResponseResult, PacketDecodeError, - BLOCK_BODIES_PACKET, - BLOCK_HEADERS_PACKET, - CONSENSUS_DATA_PACKET, - GET_BLOCK_BODIES_PACKET, - GET_BLOCK_HEADERS_PACKET, - GET_NODE_DATA_PACKET, - GET_RECEIPTS_PACKET, - GET_SNAPSHOT_DATA_PACKET, - GET_SNAPSHOT_MANIFEST_PACKET, MAX_BODIES_TO_SEND, MAX_HEADERS_TO_SEND, MAX_NODE_DATA_TO_SEND, MAX_RECEIPTS_HEADERS_TO_SEND, - NODE_DATA_PACKET, - RECEIPTS_PACKET, - SNAPSHOT_DATA_PACKET, - SNAPSHOT_MANIFEST_PACKET, - STATUS_PACKET, - TRANSACTIONS_PACKET, }; /// The Chain Sync Supplier: answers requests from peers with available data @@ -56,72 +61,83 @@ pub struct SyncSupplier; impl SyncSupplier { /// Dispatch incoming requests and responses + // Take a u8 and not a SyncPacketId because this is the entry point + // to chain sync from the outside world. pub fn dispatch_packet(sync: &RwLock, io: &mut SyncIo, peer: PeerId, packet_id: u8, data: &[u8]) { let rlp = Rlp::new(data); - let result = match packet_id { - GET_BLOCK_BODIES_PACKET => SyncSupplier::return_rlp(io, &rlp, peer, - SyncSupplier::return_block_bodies, - |e| format!("Error sending block bodies: {:?}", e)), - - GET_BLOCK_HEADERS_PACKET => SyncSupplier::return_rlp(io, &rlp, peer, - SyncSupplier::return_block_headers, - |e| format!("Error sending block headers: {:?}", e)), - - GET_RECEIPTS_PACKET => SyncSupplier::return_rlp(io, &rlp, peer, - SyncSupplier::return_receipts, - |e| format!("Error sending receipts: {:?}", e)), - - GET_NODE_DATA_PACKET => SyncSupplier::return_rlp(io, &rlp, peer, - SyncSupplier::return_node_data, - |e| format!("Error sending nodes: {:?}", e)), - - GET_SNAPSHOT_MANIFEST_PACKET => SyncSupplier::return_rlp(io, &rlp, peer, - SyncSupplier::return_snapshot_manifest, - |e| format!("Error sending snapshot manifest: {:?}", e)), - - GET_SNAPSHOT_DATA_PACKET => SyncSupplier::return_rlp(io, &rlp, peer, - SyncSupplier::return_snapshot_data, - |e| format!("Error sending snapshot data: {:?}", e)), - - STATUS_PACKET => { - sync.write().on_packet(io, peer, packet_id, data); - Ok(()) - }, - // Packets that require the peer to be confirmed - _ => { - if !sync.read().peers.contains_key(&peer) { - debug!(target:"sync", "Unexpected packet {} from unregistered peer: {}:{}", packet_id, peer, io.peer_info(peer)); - return; - } - debug!(target: "sync", "{} -> Dispatching packet: {}", peer, packet_id); - - match packet_id { - CONSENSUS_DATA_PACKET => { - SyncHandler::on_consensus_packet(io, peer, &rlp) - }, - TRANSACTIONS_PACKET => { - let res = { - let sync_ro = sync.read(); - SyncHandler::on_peer_transactions(&*sync_ro, io, peer, &rlp) - }; - if res.is_err() { - // peer sent invalid data, disconnect. - io.disable_peer(peer); - sync.write().deactivate_peer(io, peer); + if let Some(id) = SyncPacket::from_u8(packet_id) { + let result = match id { + GetBlockBodiesPacket => SyncSupplier::return_rlp( + io, &rlp, peer, + SyncSupplier::return_block_bodies, + |e| format!("Error sending block bodies: {:?}", e)), + + GetBlockHeadersPacket => SyncSupplier::return_rlp( + io, &rlp, peer, + SyncSupplier::return_block_headers, + |e| format!("Error sending block headers: {:?}", e)), + + GetReceiptsPacket => SyncSupplier::return_rlp( + io, &rlp, peer, + SyncSupplier::return_receipts, + |e| format!("Error sending receipts: {:?}", e)), + + GetNodeDataPacket => SyncSupplier::return_rlp( + io, &rlp, peer, + SyncSupplier::return_node_data, + |e| format!("Error sending nodes: {:?}", e)), + + GetSnapshotManifestPacket => SyncSupplier::return_rlp( + io, &rlp, peer, + SyncSupplier::return_snapshot_manifest, + |e| format!("Error sending snapshot manifest: {:?}", e)), + + GetSnapshotDataPacket => SyncSupplier::return_rlp( + io, &rlp, peer, + SyncSupplier::return_snapshot_data, + |e| format!("Error sending snapshot data: {:?}", e)), + + StatusPacket => { + sync.write().on_packet(io, peer, packet_id, data); + Ok(()) + }, + // Packets that require the peer to be confirmed + _ => { + if !sync.read().peers.contains_key(&peer) { + debug!(target:"sync", "Unexpected packet {} from unregistered peer: {}:{}", packet_id, peer, io.peer_version(peer)); + return; + } + debug!(target: "sync", "{} -> Dispatching packet: {}", peer, packet_id); + + match id { + ConsensusDataPacket => { + SyncHandler::on_consensus_packet(io, peer, &rlp) + }, + TransactionsPacket => { + let res = { + let sync_ro = sync.read(); + SyncHandler::on_peer_transactions(&*sync_ro, io, peer, &rlp) + }; + if res.is_err() { + // peer sent invalid data, disconnect. + io.disable_peer(peer); + sync.write().deactivate_peer(io, peer); + } + }, + _ => { + sync.write().on_packet(io, peer, packet_id, data); } - }, - _ => { - sync.write().on_packet(io, peer, packet_id, data); } + + Ok(()) } + }; - Ok(()) - } - }; - result.unwrap_or_else(|e| { - debug!(target:"sync", "{} -> Malformed packet {} : {}", peer, packet_id, e); - }) + result.unwrap_or_else(|e| { + debug!(target:"sync", "{} -> Malformed packet {} : {}", peer, packet_id, e); + }) + } } /// Respond to GetBlockHeaders request @@ -148,11 +164,11 @@ impl SyncSupplier { trace!(target:"sync", "Returning single header: {:?}", hash); let mut rlp = RlpStream::new_list(1); rlp.append_raw(&hdr.into_inner(), 1); - return Ok(Some((BLOCK_HEADERS_PACKET, rlp))); + return Ok(Some((BlockHeadersPacket.id(), rlp))); } number } - None => return Ok(Some((BLOCK_HEADERS_PACKET, RlpStream::new_list(0)))) //no such header, return nothing + None => return Ok(Some((BlockHeadersPacket.id(), RlpStream::new_list(0)))) //no such header, return nothing } } else { let number = r.val_at::(0)?; @@ -202,7 +218,7 @@ impl SyncSupplier { let mut rlp = RlpStream::new_list(count as usize); rlp.append_raw(&data, count as usize); trace!(target: "sync", "{} -> GetBlockHeaders: returned {} entries", peer_id, count); - Ok(Some((BLOCK_HEADERS_PACKET, rlp))) + Ok(Some((BlockHeadersPacket.id(), rlp))) } /// Respond to GetBlockBodies request @@ -229,7 +245,7 @@ impl SyncSupplier { let mut rlp = RlpStream::new_list(added); rlp.append_raw(&data, added); trace!(target: "sync", "{} -> GetBlockBodies: returned {} entries", peer_id, added); - Ok(Some((BLOCK_BODIES_PACKET, rlp))) + Ok(Some((BlockBodiesPacket.id(), rlp))) } /// Respond to GetNodeData request @@ -261,7 +277,7 @@ impl SyncSupplier { for d in data { rlp.append(&d); } - Ok(Some((NODE_DATA_PACKET, rlp))) + Ok(Some((NodeDataPacket.id(), rlp))) } fn return_receipts(io: &SyncIo, rlp: &Rlp, peer_id: PeerId) -> RlpResponseResult { @@ -287,7 +303,7 @@ impl SyncSupplier { } let mut rlp_result = RlpStream::new_list(added_headers); rlp_result.append_raw(&data, added_headers); - Ok(Some((RECEIPTS_PACKET, rlp_result))) + Ok(Some((ReceiptsPacket.id(), rlp_result))) } /// Respond to GetSnapshotManifest request @@ -310,7 +326,7 @@ impl SyncSupplier { RlpStream::new_list(0) } }; - Ok(Some((SNAPSHOT_MANIFEST_PACKET, rlp))) + Ok(Some((SnapshotManifestPacket.id(), rlp))) } /// Respond to GetSnapshotData request @@ -329,7 +345,7 @@ impl SyncSupplier { RlpStream::new_list(0) } }; - Ok(Some((SNAPSHOT_DATA_PACKET, rlp))) + Ok(Some((SnapshotDataPacket.id(), rlp))) } fn return_rlp(io: &mut SyncIo, rlp: &Rlp, peer: PeerId, rlp_func: FRlp, error_func: FError) -> Result<(), PacketDecodeError> @@ -491,7 +507,7 @@ mod test { io.sender = Some(2usize); - SyncSupplier::dispatch_packet(&RwLock::new(sync), &mut io, 0usize, GET_NODE_DATA_PACKET, &node_request); + SyncSupplier::dispatch_packet(&RwLock::new(sync), &mut io, 0usize, GetNodeDataPacket.id(), &node_request); assert_eq!(1, io.packets.len()); } @@ -533,7 +549,7 @@ mod test { assert_eq!(603, rlp_result.unwrap().1.out().len()); io.sender = Some(2usize); - SyncSupplier::dispatch_packet(&RwLock::new(sync), &mut io, 0usize, GET_RECEIPTS_PACKET, &receipts_request); + SyncSupplier::dispatch_packet(&RwLock::new(sync), &mut io, 0usize, GetReceiptsPacket.id(), &receipts_request); assert_eq!(1, io.packets.len()); } } diff --git a/ethcore/sync/src/chain/sync_packet.rs b/ethcore/sync/src/chain/sync_packet.rs new file mode 100644 index 0000000000..3891090f65 --- /dev/null +++ b/ethcore/sync/src/chain/sync_packet.rs @@ -0,0 +1,141 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +//! When sending packets over p2p we specify both which subprotocol +//! to use and what kind of packet we are sending (through a packet id). +//! Likewise when receiving packets from other peers we decode the +//! subprotocol and the packet id. This module helps coupling both +//! pieces of information together and provides an easy mechanism +//! to convert to/from the packet id values transmitted over the +//! wire. + +use api::{ETH_PROTOCOL, WARP_SYNC_PROTOCOL_ID}; +use network::{PacketId, ProtocolId}; + +/// An enum that defines all known packet ids in the context of +/// synchronization and provides a mechanism to convert from +/// packet ids (of type PacketId or u8) directly read from the network +/// to enum variants. This implicitly provides a mechanism to +/// check whether a given packet id is known, and to prevent +/// packet id clashes when defining new ids. +enum_from_primitive! { +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum SyncPacket { + StatusPacket = 0x00, + NewBlockHashesPacket = 0x01, + TransactionsPacket = 0x02, + GetBlockHeadersPacket = 0x03, + BlockHeadersPacket = 0x04, + GetBlockBodiesPacket = 0x05, + BlockBodiesPacket = 0x06, + NewBlockPacket = 0x07, + + GetNodeDataPacket = 0x0d, + NodeDataPacket = 0x0e, + GetReceiptsPacket = 0x0f, + ReceiptsPacket = 0x10, + + GetSnapshotManifestPacket = 0x11, + SnapshotManifestPacket = 0x12, + GetSnapshotDataPacket = 0x13, + SnapshotDataPacket = 0x14, + ConsensusDataPacket = 0x15, + PrivateTransactionPacket = 0x16, + SignedPrivateTransactionPacket = 0x17, +} +} + +use self::SyncPacket::*; + +/// Provide both subprotocol and packet id information within the +/// same object. +pub trait PacketInfo { + fn id(&self) -> PacketId; + fn protocol(&self) -> ProtocolId; +} + +// The mechanism to match packet ids and protocol may be improved +// through some macro magic, but for now this works. +impl PacketInfo for SyncPacket { + fn protocol(&self) -> ProtocolId { + match self { + StatusPacket | + NewBlockHashesPacket | + TransactionsPacket | + GetBlockHeadersPacket | + BlockHeadersPacket | + GetBlockBodiesPacket | + BlockBodiesPacket | + NewBlockPacket | + + GetNodeDataPacket| + NodeDataPacket | + GetReceiptsPacket | + ReceiptsPacket + + => ETH_PROTOCOL, + + GetSnapshotManifestPacket| + SnapshotManifestPacket | + GetSnapshotDataPacket | + SnapshotDataPacket | + ConsensusDataPacket | + PrivateTransactionPacket | + SignedPrivateTransactionPacket + + => WARP_SYNC_PROTOCOL_ID, + } + } + + fn id(&self) -> PacketId { + (*self) as PacketId + } +} + + +#[cfg(test)] +mod tests { + use super::*; + + use enum_primitive::FromPrimitive; + + #[test] + fn packet_ids_from_u8_when_from_primitive_zero_then_equals_status_packet() { + assert_eq!(SyncPacket::from_u8(0x00), Some(StatusPacket)); + } + + #[test] + fn packet_ids_from_u8_when_from_primitive_eleven_then_equals_get_snapshot_manifest_packet() { + assert_eq!(SyncPacket::from_u8(0x11), Some(GetSnapshotManifestPacket)); + } + + #[test] + fn packet_ids_from_u8_when_invalid_packet_id_then_none() { + assert!(SyncPacket::from_u8(0x99).is_none()); + } + + #[test] + fn when_status_packet_then_id_and_protocol_match() { + assert_eq!(StatusPacket.id(), StatusPacket as PacketId); + assert_eq!(StatusPacket.protocol(), ETH_PROTOCOL); + } + + #[test] + fn when_consensus_data_packet_then_id_and_protocol_match() { + assert_eq!(ConsensusDataPacket.id(), ConsensusDataPacket as PacketId); + assert_eq!(ConsensusDataPacket.protocol(), WARP_SYNC_PROTOCOL_ID); + } +} diff --git a/ethcore/sync/src/lib.rs b/ethcore/sync/src/lib.rs index 72fc11cd7a..8a1e19569a 100644 --- a/ethcore/sync/src/lib.rs +++ b/ethcore/sync/src/lib.rs @@ -27,6 +27,7 @@ extern crate ethcore_io as io; extern crate ethcore_network as network; extern crate ethcore_network_devp2p as devp2p; extern crate ethereum_types; +extern crate ethkey; extern crate ethstore; extern crate fastmap; extern crate keccak_hash as hash; @@ -40,10 +41,11 @@ extern crate ethcore_light as light; #[cfg(test)] extern crate env_logger; #[cfg(test)] extern crate ethcore_private_tx; -#[cfg(test)] extern crate ethkey; #[cfg(test)] extern crate kvdb_memorydb; #[cfg(test)] extern crate rustc_hex; +#[macro_use] +extern crate enum_primitive; #[macro_use] extern crate macros; #[macro_use] diff --git a/ethcore/sync/src/sync_io.rs b/ethcore/sync/src/sync_io.rs index 81dc9cf90c..56bf98ab2e 100644 --- a/ethcore/sync/src/sync_io.rs +++ b/ethcore/sync/src/sync_io.rs @@ -15,7 +15,9 @@ // along with Parity Ethereum. If not, see . use std::collections::HashMap; +use chain::sync_packet::{PacketInfo, SyncPacket}; use network::{NetworkContext, PeerId, PacketId, Error, SessionInfo, ProtocolId}; +use network::client_version::ClientVersion; use bytes::Bytes; use ethcore::client::BlockChainClient; use types::BlockNumber; @@ -32,17 +34,15 @@ pub trait SyncIo { fn disconnect_peer(&mut self, peer_id: PeerId); /// Respond to current request with a packet. Can be called from an IO handler for incoming packet. fn respond(&mut self, packet_id: PacketId, data: Vec) -> Result<(), Error>; - /// Send a packet to a peer. - fn send(&mut self, peer_id: PeerId, packet_id: PacketId, data: Vec) -> Result<(), Error>; /// Send a packet to a peer using specified protocol. - fn send_protocol(&mut self, protocol: ProtocolId, peer_id: PeerId, packet_id: PacketId, data: Vec) -> Result<(), Error>; + fn send(&mut self, peer_id: PeerId, packet_id: SyncPacket, data: Vec) -> Result<(), Error>; /// Get the blockchain fn chain(&self) -> &BlockChainClient; /// Get the snapshot service. fn snapshot_service(&self) -> &SnapshotService; - /// Returns peer identifier string - fn peer_info(&self, peer_id: PeerId) -> String { - peer_id.to_string() + /// Returns peer version identifier + fn peer_version(&self, peer_id: PeerId) -> ClientVersion { + ClientVersion::from(peer_id.to_string()) } /// Returns information on p2p session fn peer_session_info(&self, peer_id: PeerId) -> Option; @@ -98,12 +98,8 @@ impl<'s> SyncIo for NetSyncIo<'s> { self.network.respond(packet_id, data) } - fn send(&mut self, peer_id: PeerId, packet_id: PacketId, data: Vec) -> Result<(), Error>{ - self.network.send(peer_id, packet_id, data) - } - - fn send_protocol(&mut self, protocol: ProtocolId, peer_id: PeerId, packet_id: PacketId, data: Vec) -> Result<(), Error>{ - self.network.send_protocol(protocol, peer_id, packet_id, data) + fn send(&mut self, peer_id: PeerId, packet_id: SyncPacket, data: Vec) -> Result<(), Error>{ + self.network.send_protocol(packet_id.protocol(), peer_id, packet_id.id(), data) } fn chain(&self) -> &BlockChainClient { @@ -134,7 +130,7 @@ impl<'s> SyncIo for NetSyncIo<'s> { self.network.protocol_version(*protocol, peer_id).unwrap_or(0) } - fn peer_info(&self, peer_id: PeerId) -> String { + fn peer_version(&self, peer_id: PeerId) -> ClientVersion { self.network.peer_client_version(peer_id) } diff --git a/ethcore/sync/src/tests/consensus.rs b/ethcore/sync/src/tests/consensus.rs index 6545652961..df09366338 100644 --- a/ethcore/sync/src/tests/consensus.rs +++ b/ethcore/sync/src/tests/consensus.rs @@ -19,9 +19,9 @@ use hash::keccak; use ethereum_types::{U256, Address}; use io::{IoHandler, IoChannel}; use ethcore::client::{ChainInfo, ClientIoMessage}; +use ethcore::engines; use ethcore::spec::Spec; -use ethcore::miner::MinerService; -use ethcore::account_provider::AccountProvider; +use ethcore::miner::{self, MinerService}; use ethkey::{KeyPair, Secret}; use types::transaction::{Action, PendingTransaction, Transaction}; use super::helpers::*; @@ -43,17 +43,14 @@ fn new_tx(secret: &Secret, nonce: U256, chain_id: u64) -> PendingTransaction { fn authority_round() { let s0 = KeyPair::from_secret_slice(&keccak("1")).unwrap(); let s1 = KeyPair::from_secret_slice(&keccak("0")).unwrap(); - let ap = Arc::new(AccountProvider::transient_provider()); - ap.insert_account(s0.secret().clone(), &"".into()).unwrap(); - ap.insert_account(s1.secret().clone(), &"".into()).unwrap(); let chain_id = Spec::new_test_round().chain_id(); - let mut net = TestNet::with_spec_and_accounts(2, SyncConfig::default(), Spec::new_test_round, Some(ap)); + let mut net = TestNet::with_spec(2, SyncConfig::default(), Spec::new_test_round); let io_handler0: Arc> = Arc::new(TestIoHandler::new(net.peer(0).chain.clone())); let io_handler1: Arc> = Arc::new(TestIoHandler::new(net.peer(1).chain.clone())); // Push transaction to both clients. Only one of them gets lucky to produce a block. - net.peer(0).miner.set_author(s0.address(), Some("".into())).unwrap(); - net.peer(1).miner.set_author(s1.address(), Some("".into())).unwrap(); + net.peer(0).miner.set_author(miner::Author::Sealer(engines::signer::from_keypair(s0.clone()))); + net.peer(1).miner.set_author(miner::Author::Sealer(engines::signer::from_keypair(s1.clone()))); net.peer(0).chain.engine().register_client(Arc::downgrade(&net.peer(0).chain) as _); net.peer(1).chain.engine().register_client(Arc::downgrade(&net.peer(1).chain) as _); net.peer(0).chain.set_io_channel(IoChannel::to_handler(Arc::downgrade(&io_handler1))); diff --git a/ethcore/sync/src/tests/helpers.rs b/ethcore/sync/src/tests/helpers.rs index 85c2038457..8bc4b542e2 100644 --- a/ethcore/sync/src/tests/helpers.rs +++ b/ethcore/sync/src/tests/helpers.rs @@ -20,18 +20,21 @@ use ethereum_types::H256; use parking_lot::{RwLock, Mutex}; use bytes::Bytes; use network::{self, PeerId, ProtocolId, PacketId, SessionInfo}; +use network::client_version::ClientVersion; use tests::snapshot::*; use ethcore::client::{TestBlockChainClient, BlockChainClient, Client as EthcoreClient, ClientConfig, ChainNotify, NewBlocks, ChainMessageType, ClientIoMessage}; 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; -use chain::{ChainSync, ETH_PROTOCOL_VERSION_63, PAR_PROTOCOL_VERSION_3, PRIVATE_TRANSACTION_PACKET, SIGNED_PRIVATE_TRANSACTION_PACKET, SyncSupplier}; +use chain::{ChainSync, SyncSupplier, ETH_PROTOCOL_VERSION_63, PAR_PROTOCOL_VERSION_3}; +use chain::sync_packet::{PacketInfo, SyncPacket}; +use chain::sync_packet::SyncPacket::{PrivateTransactionPacket, SignedPrivateTransactionPacket}; + use SyncConfig; use private_tx::SimplePrivateTxHandler; use types::BlockNumber; @@ -102,27 +105,25 @@ impl<'p, C> SyncIo for TestIo<'p, C> where C: FlushingBlockChainClient, C: 'p { Ok(()) } - fn send(&mut self, peer_id: PeerId, packet_id: PacketId, data: Vec) -> Result<(), network::Error> { + fn send(&mut self,peer_id: PeerId, packet_id: SyncPacket, data: Vec) -> Result<(), network::Error> { self.packets.push(TestPacket { data: data, - packet_id: packet_id, + packet_id: packet_id.id(), recipient: peer_id, }); Ok(()) } - fn send_protocol(&mut self, _protocol: ProtocolId, peer_id: PeerId, packet_id: PacketId, data: Vec) -> Result<(), network::Error> { - self.send(peer_id, packet_id, data) - } - fn chain(&self) -> &BlockChainClient { &*self.chain } - fn peer_info(&self, peer_id: PeerId) -> String { - self.peers_info.get(&peer_id) + fn peer_version(&self, peer_id: PeerId) -> ClientVersion { + let client_id = self.peers_info.get(&peer_id) .cloned() - .unwrap_or_else(|| peer_id.to_string()) + .unwrap_or_else(|| peer_id.to_string()); + + ClientVersion::from(client_id) } fn snapshot_service(&self) -> &SnapshotService { @@ -234,9 +235,9 @@ impl EthPeer where C: FlushingBlockChainClient { match message { ChainMessageType::Consensus(data) => self.sync.write().propagate_consensus_packet(&mut io, data), ChainMessageType::PrivateTransaction(transaction_hash, data) => - self.sync.write().propagate_private_transaction(&mut io, transaction_hash, PRIVATE_TRANSACTION_PACKET, data), + self.sync.write().propagate_private_transaction(&mut io, transaction_hash, PrivateTransactionPacket, data), ChainMessageType::SignedPrivateTransaction(transaction_hash, data) => - self.sync.write().propagate_private_transaction(&mut io, transaction_hash, SIGNED_PRIVATE_TRANSACTION_PACKET, data), + self.sync.write().propagate_private_transaction(&mut io, transaction_hash, SignedPrivateTransactionPacket, data), } } @@ -367,11 +368,10 @@ impl TestNet> { } impl TestNet> { - pub fn with_spec_and_accounts( + pub fn with_spec( n: usize, config: SyncConfig, spec_factory: F, - accounts: Option> ) -> Self where F: Fn() -> Spec { @@ -381,14 +381,14 @@ impl TestNet> { disconnect_events: Vec::new(), }; for _ in 0..n { - net.add_peer_with_private_config(config.clone(), spec_factory(), accounts.clone()); + net.add_peer_with_private_config(config.clone(), spec_factory()); } net } - pub fn add_peer_with_private_config(&mut self, config: SyncConfig, spec: Spec, accounts: Option>) { + pub fn add_peer_with_private_config(&mut self, config: SyncConfig, spec: Spec) { let channel = IoChannel::disconnected(); - let miner = Arc::new(Miner::new_for_tests(&spec, accounts.clone())); + let miner = Arc::new(Miner::new_for_tests(&spec, None)); let client = EthcoreClient::new( ClientConfig::default(), &spec, diff --git a/ethcore/sync/src/tests/private.rs b/ethcore/sync/src/tests/private.rs index 10bd7d1f3d..24de14d936 100644 --- a/ethcore/sync/src/tests/private.rs +++ b/ethcore/sync/src/tests/private.rs @@ -17,16 +17,17 @@ use std::sync::Arc; use hash::keccak; use io::{IoHandler, IoChannel}; -use ethcore::client::{BlockChainClient, BlockId, ClientIoMessage}; -use ethcore::spec::Spec; -use ethcore::miner::MinerService; -use ethcore::CreateContractAddress; use types::transaction::{Transaction, Action}; +use types::ids::BlockId; +use ethcore::CreateContractAddress; +use ethcore::client::{ClientIoMessage, BlockChainClient}; use ethcore::executive::{contract_address}; +use ethcore::engines; +use ethcore::miner::{self, MinerService}; +use ethcore::spec::Spec; use ethcore::test_helpers::{push_block_with_transactions}; -use ethcore_private_tx::{Provider, ProviderConfig, NoopEncryptor, Importer, SignedPrivateTransaction}; -use ethcore::account_provider::AccountProvider; -use ethkey::{KeyPair}; +use ethcore_private_tx::{Provider, ProviderConfig, NoopEncryptor, Importer, SignedPrivateTransaction, StoringKeyProvider}; +use ethkey::KeyPair; use tests::helpers::{TestNet, TestIoHandler}; use rustc_hex::FromHex; use rlp::Rlp; @@ -42,18 +43,17 @@ fn send_private_transaction() { // Setup two clients let s0 = KeyPair::from_secret_slice(&keccak("1")).unwrap(); let s1 = KeyPair::from_secret_slice(&keccak("0")).unwrap(); - let ap = Arc::new(AccountProvider::transient_provider()); - ap.insert_account(s0.secret().clone(), &"".into()).unwrap(); - ap.insert_account(s1.secret().clone(), &"".into()).unwrap(); - let mut net = TestNet::with_spec_and_accounts(2, SyncConfig::default(), seal_spec, Some(ap.clone())); + let signer = Arc::new(ethcore_private_tx::KeyPairSigner(vec![s0.clone(), s1.clone()])); + + let mut net = TestNet::with_spec(2, SyncConfig::default(), seal_spec); let client0 = net.peer(0).chain.clone(); let client1 = net.peer(1).chain.clone(); let io_handler0: Arc> = Arc::new(TestIoHandler::new(net.peer(0).chain.clone())); let io_handler1: Arc> = Arc::new(TestIoHandler::new(net.peer(1).chain.clone())); - net.peer(0).miner.set_author(s0.address(), Some("".into())).unwrap(); - net.peer(1).miner.set_author(s1.address(), Some("".into())).unwrap(); + net.peer(0).miner.set_author(miner::Author::Sealer(engines::signer::from_keypair(s0.clone()))); + net.peer(1).miner.set_author(miner::Author::Sealer(engines::signer::from_keypair(s1.clone()))); net.peer(0).chain.engine().register_client(Arc::downgrade(&net.peer(0).chain) as _); net.peer(1).chain.engine().register_client(Arc::downgrade(&net.peer(1).chain) as _); net.peer(0).chain.set_io_channel(IoChannel::to_handler(Arc::downgrade(&io_handler0))); @@ -69,32 +69,34 @@ fn send_private_transaction() { let validator_config = ProviderConfig{ validator_accounts: vec![s1.address()], signer_account: None, - passwords: vec!["".into()], }; let signer_config = ProviderConfig{ validator_accounts: Vec::new(), signer_account: Some(s0.address()), - passwords: vec!["".into()], }; + let private_keys = Arc::new(StoringKeyProvider::default()); + let pm0 = Arc::new(Provider::new( client0.clone(), net.peer(0).miner.clone(), - ap.clone(), + signer.clone(), Box::new(NoopEncryptor::default()), signer_config, IoChannel::to_handler(Arc::downgrade(&io_handler0)), + private_keys.clone(), )); pm0.add_notify(net.peers[0].clone()); let pm1 = Arc::new(Provider::new( client1.clone(), net.peer(1).miner.clone(), - ap.clone(), + signer.clone(), Box::new(NoopEncryptor::default()), validator_config, IoChannel::to_handler(Arc::downgrade(&io_handler1)), + private_keys.clone(), )); pm1.add_notify(net.peers[1].clone()); diff --git a/ethcore/sync/src/tests/snapshot.rs b/ethcore/sync/src/tests/snapshot.rs index a3aa77d36d..d865adc2ad 100644 --- a/ethcore/sync/src/tests/snapshot.rs +++ b/ethcore/sync/src/tests/snapshot.rs @@ -122,6 +122,8 @@ impl SnapshotService for TestSnapshotService { self.block_restoration_chunks.lock().clear(); } + fn abort_snapshot(&self) {} + fn restore_state_chunk(&self, hash: H256, chunk: Bytes) { if self.restoration_manifest.lock().as_ref().map_or(false, |m| m.state_hashes.iter().any(|h| h == &hash)) { self.state_restoration_chunks.lock().insert(hash, chunk); diff --git a/ethcore/types/Cargo.toml b/ethcore/types/Cargo.toml index 855fd71728..1d831278f8 100644 --- a/ethcore/types/Cargo.toml +++ b/ethcore/types/Cargo.toml @@ -1,6 +1,6 @@ [package] +description = "Parity Ethereum Common Types" name = "common-types" -description = "Common types used throughout the codebase" version = "0.1.0" authors = ["Parity Technologies "] @@ -11,10 +11,12 @@ ethkey = { path = "../../accounts/ethkey" } heapsize = "0.4" keccak-hash = "0.1" parity-bytes = "0.1" -parity-machine = { path = "../../machine" } rlp = { version = "0.3.0", features = ["ethereum"] } rlp_derive = { path = "../../util/rlp-derive" } unexpected = { path = "../../util/unexpected" } [dev-dependencies] -rustc-hex= "1.0" +rustc-hex = "1.0" + +[features] +test-helpers = [] diff --git a/ethcore/types/src/engines/epoch.rs b/ethcore/types/src/engines/epoch.rs index 34054a193f..2a43b47755 100644 --- a/ethcore/types/src/engines/epoch.rs +++ b/ethcore/types/src/engines/epoch.rs @@ -71,28 +71,3 @@ impl Decodable for PendingTransition { } } -/// Verifier for all blocks within an epoch with self-contained state. -pub trait EpochVerifier: Send + Sync { - /// Lightly verify the next block header. - /// This may not be a header belonging to a different epoch. - fn verify_light(&self, header: &M::Header) -> Result<(), M::Error>; - - /// Perform potentially heavier checks on the next block header. - fn verify_heavy(&self, header: &M::Header) -> Result<(), M::Error> { - self.verify_light(header) - } - - /// Check a finality proof against this epoch verifier. - /// Returns `Some(hashes)` if the proof proves finality of these hashes. - /// Returns `None` if the proof doesn't prove anything. - fn check_finality_proof(&self, _proof: &[u8]) -> Option> { - None - } -} - -/// Special "no-op" verifier for stateless, epoch-less engines. -pub struct NoOp; - -impl EpochVerifier for NoOp { - fn verify_light(&self, _header: &M::Header) -> Result<(), M::Error> { Ok(()) } -} diff --git a/ethcore/types/src/header.rs b/ethcore/types/src/header.rs index 829776f013..cfe8f5bb65 100644 --- a/ethcore/types/src/header.rs +++ b/ethcore/types/src/header.rs @@ -16,7 +16,6 @@ //! Block header. -use std::cmp; use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY_LIST_RLP, keccak}; use heapsize::HeapSizeOf; use ethereum_types::{H256, U256, Address, Bloom}; @@ -342,7 +341,7 @@ impl Decodable for Header { number: r.val_at(8)?, gas_limit: r.val_at(9)?, gas_used: r.val_at(10)?, - timestamp: cmp::min(r.val_at::(11)?, u64::max_value().into()).as_u64(), + timestamp: r.val_at(11)?, extra_data: r.val_at(12)?, seal: vec![], hash: keccak(r.as_raw()).into(), @@ -368,44 +367,11 @@ impl HeapSizeOf for Header { } } -impl ::parity_machine::Header for Header { - fn bare_hash(&self) -> H256 { Header::bare_hash(self) } - fn hash(&self) -> H256 { Header::hash(self) } - fn seal(&self) -> &[Vec] { Header::seal(self) } - fn author(&self) -> &Address { Header::author(self) } - fn number(&self) -> BlockNumber { Header::number(self) } -} - -impl ::parity_machine::ScoredHeader for Header { - type Value = U256; - - fn score(&self) -> &U256 { self.difficulty() } - fn set_score(&mut self, score: U256) { self.set_difficulty(score) } -} - -impl ::parity_machine::Header for ExtendedHeader { - fn bare_hash(&self) -> H256 { self.header.bare_hash() } - fn hash(&self) -> H256 { self.header.hash() } - fn seal(&self) -> &[Vec] { self.header.seal() } - fn author(&self) -> &Address { self.header.author() } - fn number(&self) -> BlockNumber { self.header.number() } -} - -impl ::parity_machine::ScoredHeader for ExtendedHeader { - type Value = U256; - - fn score(&self) -> &U256 { self.header.difficulty() } - fn set_score(&mut self, score: U256) { self.header.set_difficulty(score) } -} - -impl ::parity_machine::TotalScoredHeader for ExtendedHeader { - type Value = U256; - - fn total_score(&self) -> U256 { self.parent_total_difficulty + *self.header.difficulty() } -} - -impl ::parity_machine::FinalizableHeader for ExtendedHeader { - fn is_finalized(&self) -> bool { self.is_finalized } +impl ExtendedHeader { + /// Returns combined difficulty of all ancestors together with the difficulty of this header. + pub fn total_score(&self) -> U256 { + self.parent_total_difficulty + *self.header.difficulty() + } } #[cfg(test)] @@ -445,4 +411,15 @@ mod tests { assert_eq!(header_rlp, encoded_header); } + + #[test] + fn reject_header_with_large_timestamp() { + // that's rlp of block header created with ethash engine. + // The encoding contains a large timestamp (295147905179352825856) + let header_rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d891000000000000000000080a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap(); + + // This should fail decoding timestamp + let header: Result = rlp::decode(&header_rlp); + assert_eq!(header.unwrap_err(), rlp::DecoderError::RlpIsTooBig); + } } diff --git a/ethcore/types/src/ids.rs b/ethcore/types/src/ids.rs index dccb240d94..1f099be57d 100644 --- a/ethcore/types/src/ids.rs +++ b/ethcore/types/src/ids.rs @@ -17,7 +17,7 @@ //! Unique identifiers. use ethereum_types::H256; -use {BlockNumber}; +use BlockNumber; /// Uniquely identifies block. #[derive(Debug, PartialEq, Copy, Clone, Hash, Eq)] diff --git a/ethcore/types/src/lib.rs b/ethcore/types/src/lib.rs index 4ca5c80dcf..3223db7220 100644 --- a/ethcore/types/src/lib.rs +++ b/ethcore/types/src/lib.rs @@ -39,7 +39,6 @@ extern crate ethkey; extern crate heapsize; extern crate keccak_hash as hash; extern crate parity_bytes as bytes; -extern crate parity_machine; extern crate rlp; extern crate unexpected; diff --git a/ethcore/types/src/restoration_status.rs b/ethcore/types/src/restoration_status.rs index dea342a310..b36ec7ef4a 100644 --- a/ethcore/types/src/restoration_status.rs +++ b/ethcore/types/src/restoration_status.rs @@ -21,7 +21,7 @@ pub enum RestorationStatus { /// No restoration. Inactive, - /// Restoration is initalizing + /// Restoration is initializing Initializing { /// Number of chunks done/imported chunks_done: u32, diff --git a/ethcore/types/src/transaction/error.rs b/ethcore/types/src/transaction/error.rs index ab10636643..68c0b2c0fe 100644 --- a/ethcore/types/src/transaction/error.rs +++ b/ethcore/types/src/transaction/error.rs @@ -28,9 +28,6 @@ pub enum Error { AlreadyImported, /// Transaction is not valid anymore (state already has higher nonce) Old, - /// Transaction has too low fee - /// (there is already a transaction with the same sender-nonce but higher gas price) - TooCheapToReplace, /// Transaction was not imported to the queue because limit has been reached. LimitReached, /// Transaction's gas price is below threshold. @@ -40,6 +37,14 @@ pub enum Error { /// Transaction gas price got: U256, }, + /// Transaction has too low fee + /// (there is already a transaction with the same sender-nonce but higher gas price) + TooCheapToReplace { + /// previous transaction's gas price + prev: Option, + /// new transaction's gas price + new: Option, + }, /// Transaction's gas is below currently set minimal gas requirement. InsufficientGas { /// Minimal expected gas @@ -99,7 +104,10 @@ impl fmt::Display for Error { let msg = match *self { AlreadyImported => "Already imported".into(), Old => "No longer valid".into(), - TooCheapToReplace => "Gas price too low to replace".into(), + TooCheapToReplace { prev, new } => + format!("Gas price too low to replace, previous tx gas: {:?}, new tx gas: {:?}", + prev, new + ), LimitReached => "Transaction limit reached".into(), InsufficientGasPrice { minimal, got } => format!("Insufficient gas price. Min={}, Given={}", minimal, got), diff --git a/ethcore/types/src/transaction/transaction.rs b/ethcore/types/src/transaction/transaction.rs index 248bc26462..439880089e 100644 --- a/ethcore/types/src/transaction/transaction.rs +++ b/ethcore/types/src/transaction/transaction.rs @@ -53,7 +53,11 @@ impl Default for Action { impl rlp::Decodable for Action { fn decode(rlp: &Rlp) -> Result { if rlp.is_empty() { - Ok(Action::Create) + if rlp.is_data() { + Ok(Action::Create) + } else { + Err(DecoderError::RlpExpectedToBeData) + } } else { Ok(Action::Call(rlp.as_val()?)) } @@ -572,6 +576,20 @@ mod tests { assert_eq!(t.chain_id(), None); } + #[test] + fn empty_atom_as_create_action() { + let empty_atom = [0x80]; + let action: Action = rlp::decode(&empty_atom).unwrap(); + assert_eq!(action, Action::Create); + } + + #[test] + fn empty_list_as_create_action_rejected() { + let empty_list = [0xc0]; + let action: Result = rlp::decode(&empty_list); + assert_eq!(action, Err(DecoderError::RlpExpectedToBeData)); + } + #[test] fn signing_eip155_zero_chainid() { use ethkey::{Random, Generator}; diff --git a/ethcore/vm/Cargo.toml b/ethcore/vm/Cargo.toml index bd5fb238fb..34b086bce0 100644 --- a/ethcore/vm/Cargo.toml +++ b/ethcore/vm/Cargo.toml @@ -1,15 +1,13 @@ [package] +description = "Virtual Machines (VM) Support Library" name = "vm" version = "0.1.0" authors = ["Parity Technologies "] [dependencies] -byteorder = "1.0" parity-bytes = "0.1" ethereum-types = "0.4" -patricia-trie = "0.3.0" patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" } -log = "0.4" ethjson = { path = "../../json" } rlp = { version = "0.3.0", features = ["ethereum"] } keccak-hash = "0.1" diff --git a/ethcore/vm/src/env_info.rs b/ethcore/vm/src/env_info.rs index e5bd3f64e3..addfa62898 100644 --- a/ethcore/vm/src/env_info.rs +++ b/ethcore/vm/src/env_info.rs @@ -65,7 +65,7 @@ impl From for EnvInfo { fn from(e: ethjson::vm::Env) -> Self { let number = e.number.into(); EnvInfo { - number: number, + number, author: e.author.into(), difficulty: e.difficulty.into(), gas_limit: e.gas_limit.into(), diff --git a/ethcore/vm/src/ext.rs b/ethcore/vm/src/ext.rs index 9b499fcab4..247758c1e5 100644 --- a/ethcore/vm/src/ext.rs +++ b/ethcore/vm/src/ext.rs @@ -91,7 +91,7 @@ pub trait Ext { /// Creates new contract. /// - /// Returns gas_left and contract address if contract creation was succesfull. + /// Returns gas_left and contract address if contract creation was successful. fn create( &mut self, gas: &U256, @@ -144,6 +144,9 @@ pub trait Ext { /// Returns environment info. fn env_info(&self) -> &EnvInfo; + /// Returns the chain ID of the blockchain + fn chain_id(&self) -> u64; + /// Returns current depth of execution. /// /// If contract A calls contract B, and contract B calls C, @@ -160,8 +163,12 @@ pub trait Ext { fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8, _current_gas: U256) -> bool { false } /// Prepare to trace an operation. Passthrough for the VM trace. + /// For each call of `trace_prepare_execute` either `trace_failed` or `trace_executed` MUST be called. fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: U256, _mem_written: Option<(usize, usize)>, _store_written: Option<(U256, U256)>) {} + /// Trace the execution failure of a single instruction. + fn trace_failed(&mut self) {} + /// Trace the finalised execution of a single instruction. fn trace_executed(&mut self, _gas_used: U256, _stack_push: &[U256], _mem: &[u8]) {} diff --git a/ethcore/vm/src/lib.rs b/ethcore/vm/src/lib.rs index a8bb440412..4204ff92dc 100644 --- a/ethcore/vm/src/lib.rs +++ b/ethcore/vm/src/lib.rs @@ -22,7 +22,6 @@ extern crate ethjson; extern crate rlp; extern crate keccak_hash as hash; extern crate patricia_trie_ethereum as ethtrie; -extern crate patricia_trie as trie; mod action_params; mod call_type; diff --git a/ethcore/vm/src/return_data.rs b/ethcore/vm/src/return_data.rs index 85fdb361db..38ac23ffdc 100644 --- a/ethcore/vm/src/return_data.rs +++ b/ethcore/vm/src/return_data.rs @@ -44,11 +44,7 @@ impl ReturnData { } /// Create `ReturnData` from give buffer and slice. pub fn new(mem: Vec, offset: usize, size: usize) -> Self { - ReturnData { - mem: mem, - offset: offset, - size: size, - } + ReturnData { mem, offset, size } } } diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index d1dc3b5aad..6fad8351e6 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -15,8 +15,17 @@ // along with Parity Ethereum. If not, see . //! Cost schedule and other parameterisations for the EVM. +use std::collections::HashMap; +use ethereum_types::U256; + +/// Definition of schedules that can be applied to a version. +#[derive(Debug)] +pub enum VersionedSchedule { + PWasm, +} /// Definition of the cost schedule and other parameterisations for the EVM. +#[derive(Debug)] pub struct Schedule { /// Does it support exceptional failed code deposit pub exceptional_failed_code_deposit: bool, @@ -84,7 +93,7 @@ pub struct Schedule { pub tx_create_gas: usize, /// Additional cost for empty data transaction pub tx_data_zero_gas: usize, - /// Aditional cost for non-empty data transaction + /// Additional cost for non-empty data transaction pub tx_data_non_zero_gas: usize, /// Gas price for copying memory pub copy_gas: usize, @@ -115,10 +124,16 @@ pub struct Schedule { pub have_return_data: bool, /// SHL, SHR, SAR opcodes enabled. pub have_bitwise_shifting: bool, + /// CHAINID opcode enabled. + pub have_chain_id: bool, + /// SELFBALANCE opcode enabled. + pub have_selfbalance: bool, /// Kill basic accounts below this balance if touched. pub kill_dust: CleanDustMode, /// Enable EIP-1283 rules pub eip1283: bool, + /// Enable EIP-1706 rules + pub eip1706: bool, /// VM execution does not increase null signed address nonce if this field is true. pub keep_unsigned_nonce: bool, /// Wasm extra schedule settings, if wasm activated @@ -126,6 +141,7 @@ pub struct Schedule { } /// Wasm cost table +#[derive(Debug)] pub struct WasmCosts { /// Default opcode cost pub regular: u32, @@ -179,7 +195,7 @@ impl Default for WasmCosts { } /// Dust accounts cleanup mode. -#[derive(PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq)] pub enum CleanDustMode { /// Dust cleanup is disabled. Off, @@ -209,6 +225,8 @@ impl Schedule { have_revert: false, have_return_data: false, have_bitwise_shifting: false, + have_chain_id: false, + have_selfbalance: false, have_extcodehash: false, stack_limit: 1024, max_depth: 1024, @@ -253,6 +271,7 @@ impl Schedule { have_static_call: false, kill_dust: CleanDustMode::Off, eip1283: false, + eip1706: false, keep_unsigned_nonce: false, wasm: None, } @@ -275,6 +294,18 @@ impl Schedule { schedule } + /// Schedule for the Istanbul fork of the Ethereum main net. + pub fn new_istanbul() -> Schedule { + let mut schedule = Self::new_constantinople(); + schedule.have_chain_id = true; // EIP 1344 + schedule.tx_data_non_zero_gas = 16; // EIP 2028 + schedule.sload_gas = 800; // EIP 1884 + schedule.balance_gas = 700; // EIP 1884 + schedule.extcodehash_gas = 700; // EIP 1884 + schedule.have_selfbalance = true; // EIP 1884 + schedule + } + fn new(efcd: bool, hdc: bool, tcg: usize) -> Schedule { Schedule { exceptional_failed_code_deposit: efcd, @@ -283,6 +314,8 @@ impl Schedule { have_revert: false, have_return_data: false, have_bitwise_shifting: false, + have_chain_id: false, + have_selfbalance: false, have_extcodehash: false, stack_limit: 1024, max_depth: 1024, @@ -327,6 +360,7 @@ impl Schedule { have_static_call: false, kill_dust: CleanDustMode::Off, eip1283: false, + eip1706: false, keep_unsigned_nonce: false, wasm: None, } diff --git a/ethcore/vm/src/tests.rs b/ethcore/vm/src/tests.rs index 306ad871da..5684a234ac 100644 --- a/ethcore/vm/src/tests.rs +++ b/ethcore/vm/src/tests.rs @@ -67,6 +67,8 @@ pub struct FakeExt { pub balances: HashMap, pub tracing: bool, pub is_static: bool, + + chain_id: u64, } // similar to the normal `finalize` function, but ignoring NeedsReturn. @@ -98,11 +100,24 @@ impl FakeExt { ext } + /// New fake externalities with Istanbul schedule rules + pub fn new_istanbul() -> Self { + let mut ext = FakeExt::default(); + ext.schedule = Schedule::new_istanbul(); + ext + } + /// Alter fake externalities to allow wasm pub fn with_wasm(mut self) -> Self { self.schedule.wasm = Some(Default::default()); self } + + /// Set chain ID + pub fn with_chain_id(mut self, chain_id: u64) -> Self { + self.chain_id = chain_id; + self + } } impl Ext for FakeExt { @@ -200,7 +215,7 @@ impl Ext for FakeExt { fn log(&mut self, topics: Vec, data: &[u8]) -> Result<()> { self.logs.push(FakeLogEntry { - topics: topics, + topics, data: data.to_vec() }); Ok(()) @@ -223,6 +238,10 @@ impl Ext for FakeExt { &self.info } + fn chain_id(&self) -> u64 { + self.chain_id + } + fn depth(&self) -> usize { self.depth } diff --git a/ethcore/wasm/Cargo.toml b/ethcore/wasm/Cargo.toml index 02aa978d7b..e724a6a4cf 100644 --- a/ethcore/wasm/Cargo.toml +++ b/ethcore/wasm/Cargo.toml @@ -1,4 +1,5 @@ [package] +description = "WASM Interpreter" name = "wasm" version = "0.1.0" authors = ["Parity Technologies "] diff --git a/ethcore/wasm/run/Cargo.toml b/ethcore/wasm/run/Cargo.toml index 9260d1eee8..eee0d5fa32 100644 --- a/ethcore/wasm/run/Cargo.toml +++ b/ethcore/wasm/run/Cargo.toml @@ -1,4 +1,5 @@ [package] +description = "Parity WASM Test Run" name = "pwasm-run-test" version = "0.1.0" authors = ["Parity Technologies "] diff --git a/evmbin/Cargo.toml b/evmbin/Cargo.toml index 95b532366c..dd6a3aad04 100644 --- a/evmbin/Cargo.toml +++ b/evmbin/Cargo.toml @@ -1,6 +1,6 @@ [package] +description = "Parity EVM Implementation" name = "evmbin" -description = "Parity's EVM implementation" version = "0.1.0" authors = ["Parity Technologies "] diff --git a/evmbin/README.md b/evmbin/README.md index 696a84436f..e0a8c9d966 100644 --- a/evmbin/README.md +++ b/evmbin/README.md @@ -6,7 +6,7 @@ EVM implementation for Parity. ``` EVM implementation for Parity. - Copyright 2015-2018 Parity Technologies (UK) Ltd. + Copyright 2015-2019 Parity Technologies (UK) Ltd. Usage: parity-evm state-test [--json --std-json --std-dump-json --only NAME --chain CHAIN --std-out-only --std-err-only] diff --git a/evmbin/src/info.rs b/evmbin/src/info.rs index a12cdb16bd..74ea3175a6 100644 --- a/evmbin/src/info.rs +++ b/evmbin/src/info.rs @@ -18,7 +18,7 @@ use std::time::{Instant, Duration}; use ethereum_types::{H256, U256}; -use ethcore::client::{self, EvmTestClient, EvmTestError, TransactResult}; +use ethcore::client::{self, EvmTestClient, EvmTestError, TransactErr, TransactSuccess}; use ethcore::{state, state_db, trace, spec, pod_state, TrieSpec}; use ethjson; use types::transaction; @@ -130,7 +130,7 @@ pub fn run_transaction( let result = run(&spec, trie_spec, transaction.gas, pre_state, |mut client| { let result = client.transact(env_info, transaction, trace::NoopTracer, informant); match result { - TransactResult::Ok { state_root, gas_left, output, vm_trace, end_state, .. } => { + Ok(TransactSuccess { state_root, gas_left, output, vm_trace, end_state, .. }) => { if state_root != post_root { (Err(EvmTestError::PostCondition(format!( "State root mismatch (got: {:#x}, expected: {:#x})", @@ -141,7 +141,7 @@ pub fn run_transaction( (Ok(output), state_root, end_state, Some(gas_left), vm_trace) } }, - TransactResult::Err { state_root, error, end_state } => { + Err(TransactErr { state_root, error, end_state }) => { (Err(EvmTestError::PostCondition(format!( "Unexpected execution error: {:?}", error ))), state_root, end_state, None, None) diff --git a/evmbin/src/main.rs b/evmbin/src/main.rs index 91e38e2546..48c1e85817 100644 --- a/evmbin/src/main.rs +++ b/evmbin/src/main.rs @@ -59,7 +59,7 @@ use info::Informant; const USAGE: &'static str = r#" EVM implementation for Parity. - Copyright 2015-2018 Parity Technologies (UK) Ltd. + Copyright 2015-2019 Parity Technologies (UK) Ltd. Usage: parity-evm state-test [--json --std-json --std-dump-json --only NAME --chain CHAIN --std-out-only --std-err-only] @@ -83,8 +83,11 @@ Transaction options: --gas-price WEI Supplied gas price as hex (without 0x). State test options: + --chain CHAIN Run only from specific chain name (i.e. one of EIP150, EIP158, + Frontier, Homestead, Byzantium, Constantinople, + ConstantinopleFix, Istanbul, EIP158ToByzantiumAt5, FrontierToHomesteadAt5, + HomesteadToDaoAt5, HomesteadToEIP150At5). --only NAME Runs only a single test matching the name. - --chain CHAIN Run only tests from specific chain. General options: --json Display verbose results in JSON. diff --git a/ipfs/Cargo.toml b/ipfs/Cargo.toml index 23ada21ea1..3c0fcd7947 100644 --- a/ipfs/Cargo.toml +++ b/ipfs/Cargo.toml @@ -1,5 +1,5 @@ [package] -description = "Parity IPFS-compatible API" +description = "Parity Ethereum IPFS-compatible API" name = "parity-ipfs-api" version = "1.12.0" license = "GPL-3.0" @@ -9,8 +9,8 @@ authors = ["Parity Technologies "] ethcore = { path = "../ethcore" } parity-bytes = "0.1" ethereum-types = "0.4" -jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } -jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } +jsonrpc-core = "10.0.1" +jsonrpc-http-server = "10.0.1" rlp = { version = "0.3.0", features = ["ethereum"] } cid = "0.3" multihash = "0.8" diff --git a/ipfs/src/lib.rs b/ipfs/src/lib.rs index 0ba6a86d02..0a3d83432a 100644 --- a/ipfs/src/lib.rs +++ b/ipfs/src/lib.rs @@ -22,7 +22,7 @@ extern crate rlp; extern crate ethcore; extern crate parity_bytes as bytes; extern crate ethereum_types; -extern crate jsonrpc_core as core; +extern crate jsonrpc_core; extern crate jsonrpc_http_server as http; pub mod error; @@ -32,8 +32,8 @@ use std::thread; use std::sync::{mpsc, Arc}; use std::net::{SocketAddr, IpAddr}; -use core::futures::future::{self, FutureResult}; -use core::futures::{self, Future}; +use jsonrpc_core::futures::future::{self, FutureResult}; +use jsonrpc_core::futures::{self, Future}; use ethcore::client::BlockChainClient; use http::hyper::{self, server, Method, StatusCode, Body, header::{self, HeaderValue}, @@ -51,19 +51,19 @@ pub struct IpfsHandler { /// Hostnames allowed in the `Host` request header allowed_hosts: Option>, /// Reference to the Blockchain Client - client: Arc, + client: Arc, } impl IpfsHandler { - pub fn client(&self) -> &BlockChainClient { + pub fn client(&self) -> &dyn BlockChainClient { &*self.client } - pub fn new(cors: DomainsValidation, hosts: DomainsValidation, client: Arc) -> Self { + pub fn new(cors: DomainsValidation, hosts: DomainsValidation, client: Arc) -> Self { IpfsHandler { cors_domains: cors.into(), allowed_hosts: hosts.into(), - client: client, + client, } } pub fn on_request(&self, req: hyper::Request) -> (Option, Out) { @@ -154,7 +154,7 @@ pub fn start_server( interface: String, cors: DomainsValidation, hosts: DomainsValidation, - client: Arc + client: Arc ) -> Result { let ip: IpAddr = interface.parse().map_err(|_| ServerError::InvalidInterface)?; @@ -182,12 +182,12 @@ pub fn start_server( }; let server = server_bldr - .serve(new_service) - .map_err(|_| ()) - .select(shutdown_signal.map_err(|_| ())) - .then(|_| Ok(())); + .serve(new_service) + .map_err(|_| ()) + .select(shutdown_signal.map_err(|_| ())) + .then(|_| Ok(())); - hyper::rt::run(server); + hyper::rt::run(server); send(Ok(())); }); diff --git a/json/Cargo.toml b/json/Cargo.toml index 2a6d8c7f36..164ee6bce4 100644 --- a/json/Cargo.toml +++ b/json/Cargo.toml @@ -1,4 +1,5 @@ [package] +description = "Parity Ethereum JSON Deserialization" name = "ethjson" version = "0.1.0" authors = ["Parity Technologies "] diff --git a/json/src/lib.rs b/json/src/lib.rs index b8fa463d42..af5d93edfa 100644 --- a/json/src/lib.rs +++ b/json/src/lib.rs @@ -30,5 +30,4 @@ pub mod vm; pub mod maybe; pub mod state; pub mod transaction; -pub mod misc; pub mod test; diff --git a/json/src/misc/mod.rs b/json/src/misc/mod.rs deleted file mode 100644 index 52bbfc03af..0000000000 --- a/json/src/misc/mod.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -//! Misc deserialization. - -macro_rules! impl_serialization { - ($key: ty => $name: ty) => { - impl $name { - /// Read a hash map of DappId -> $name - pub fn read(reader: R) -> Result<::std::collections::HashMap, ::serde_json::Error> where - R: ::std::io::Read, - D: From<$key> + ::std::hash::Hash + Eq, - S: From<$name> + Clone, - { - ::serde_json::from_reader(reader).map(|ok: ::std::collections::HashMap<$key, $name>| - ok.into_iter().map(|(a, m)| (a.into(), m.into())).collect() - ) - } - - /// Write a hash map of DappId -> $name - pub fn write(m: &::std::collections::HashMap, writer: &mut W) -> Result<(), ::serde_json::Error> where - W: ::std::io::Write, - D: Into<$key> + ::std::hash::Hash + Eq + Clone, - S: Into<$name> + Clone, - { - ::serde_json::to_writer( - writer, - &m.iter() - .map(|(a, m)| (a.clone().into(), m.clone().into())) - .collect::<::std::collections::HashMap<$key, $name>>() - ) - } - } - } -} - -mod account_meta; - -pub use self::account_meta::AccountMeta; diff --git a/json/src/spec/builtin.rs b/json/src/spec/builtin.rs index 930e0bc9a1..c4f9f4e1ec 100644 --- a/json/src/spec/builtin.rs +++ b/json/src/spec/builtin.rs @@ -18,6 +18,7 @@ use uint::Uint; + /// Linear pricing. #[derive(Debug, PartialEq, Deserialize, Clone)] #[serde(deny_unknown_fields)] @@ -36,6 +37,16 @@ pub struct Modexp { pub divisor: usize, } +/// Pricing for constant alt_bn128 operations (ECADD and ECMUL) +#[derive(Debug, PartialEq, Deserialize, Clone)] +#[serde(deny_unknown_fields)] +pub struct AltBn128ConstOperations { + /// price + pub price: usize, + /// EIP 1108 transition price + pub eip1108_transition_price: usize, +} + /// Pricing for alt_bn128_pairing. #[derive(Debug, PartialEq, Deserialize, Clone)] #[serde(deny_unknown_fields)] @@ -44,6 +55,10 @@ pub struct AltBn128Pairing { pub base: usize, /// Price per point pair. pub pair: usize, + /// EIP 1108 transition base price + pub eip1108_transition_base: usize, + /// EIP 1108 transition price per point pair + pub eip1108_transition_pair: usize, } /// Pricing variants. @@ -51,12 +66,19 @@ pub struct AltBn128Pairing { #[serde(deny_unknown_fields)] #[serde(rename_all = "snake_case")] pub enum Pricing { + /// Pricing for Blake2 compression function: each call costs the same amount per round. + Blake2F { + /// Price per round of Blake2 compression function. + gas_per_round: u64, + }, /// Linear pricing. Linear(Linear), /// Pricing for modular exponentiation. Modexp(Modexp), /// Pricing for alt_bn128_pairing exponentiation. AltBn128Pairing(AltBn128Pairing), + /// Pricing for constant alt_bn128 operations + AltBn128ConstOperations(AltBn128ConstOperations), } /// Spec builtin. @@ -69,6 +91,8 @@ pub struct Builtin { pub pricing: Pricing, /// Activation block. pub activate_at: Option, + /// EIP 1108 + pub eip1108_transition: Option, } #[cfg(test)] @@ -89,6 +113,19 @@ mod tests { assert!(deserialized.activate_at.is_none()); } + #[test] + fn deserialization_blake2_f_builtin() { + let s = r#"{ + "name": "blake2_f", + "activate_at": "0xffffff", + "pricing": { "blake2_f": { "gas_per_round": 123 } } + }"#; + let deserialized: Builtin = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized.name, "blake2_f"); + assert_eq!(deserialized.pricing, Pricing::Blake2F { gas_per_round: 123 }); + assert!(deserialized.activate_at.is_some()); + } + #[test] fn activate_at() { let s = r#"{ diff --git a/json/src/spec/clique.rs b/json/src/spec/clique.rs new file mode 100644 index 0000000000..64be9c569a --- /dev/null +++ b/json/src/spec/clique.rs @@ -0,0 +1,57 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +//! Clique params deserialization. + +use std::num::NonZeroU64; + +/// Clique params deserialization. +#[derive(Debug, PartialEq, Deserialize)] +pub struct CliqueParams { + /// period as defined in EIP + pub period: Option, + /// epoch length as defined in EIP + pub epoch: Option +} + +/// Clique engine deserialization. +#[derive(Debug, PartialEq, Deserialize)] +pub struct Clique { + /// CliqueEngine params + pub params: CliqueParams, +} + +#[cfg(test)] +mod tests { + use serde_json; + use uint::Uint; + use ethereum_types::U256; + use super::*; + + #[test] + fn clique_deserialization() { + let s = r#"{ + "params": { + "period": 5, + "epoch": 30000 + } + }"#; + + let deserialized: Clique = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized.params.period, Some(5u64)); + assert_eq!(deserialized.params.epoch, NonZeroU64::new(30000)); + } +} diff --git a/json/src/spec/engine.rs b/json/src/spec/engine.rs index 8941f89e14..cfa1d8cafd 100644 --- a/json/src/spec/engine.rs +++ b/json/src/spec/engine.rs @@ -16,7 +16,7 @@ //! Engine deserialization. -use super::{Ethash, BasicAuthority, AuthorityRound, NullEngine, InstantSeal}; +use super::{Ethash, BasicAuthority, AuthorityRound, NullEngine, InstantSeal, Clique}; /// Engine deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -34,6 +34,8 @@ pub enum Engine { BasicAuthority(BasicAuthority), /// AuthorityRound engine. AuthorityRound(AuthorityRound), + /// Clique engine. + Clique(Clique) } #[cfg(test)] @@ -130,5 +132,19 @@ mod tests { Engine::AuthorityRound(_) => {}, // AuthorityRound is unit tested in its own file. _ => panic!(), }; + + let s = r#"{ + "clique": { + "params": { + "period": 15, + "epoch": 30000 + } + } + }"#; + let deserialized: Engine = serde_json::from_str(s).unwrap(); + match deserialized { + Engine::Clique(_) => {}, // Clique is unit tested in its own file. + _ => panic!(), + }; } } diff --git a/json/src/spec/ethash.rs b/json/src/spec/ethash.rs index 6f9dd77068..6051ac90d8 100644 --- a/json/src/spec/ethash.rs +++ b/json/src/spec/ethash.rs @@ -95,6 +95,9 @@ pub struct EthashParams { pub expip2_transition: Option, /// EXPIP-2 duration limit pub expip2_duration_limit: Option, + /// Block to transition to progpow + #[serde(rename="progpowTransition")] + pub progpow_transition: Option, } /// Ethash engine deserialization. @@ -200,6 +203,7 @@ mod tests { ecip1017_era_rounds: None, expip2_transition: None, expip2_duration_limit: None, + progpow_transition: None, difficulty_bomb_delays: None, } }); @@ -239,6 +243,7 @@ mod tests { ecip1017_era_rounds: None, expip2_transition: None, expip2_duration_limit: None, + progpow_transition: None, difficulty_bomb_delays: None, } }); diff --git a/json/src/spec/mod.rs b/json/src/spec/mod.rs index 1d6815d37c..f1145be2e9 100644 --- a/json/src/spec/mod.rs +++ b/json/src/spec/mod.rs @@ -31,6 +31,7 @@ pub mod authority_round; pub mod null_engine; pub mod instant_seal; pub mod hardcoded_sync; +pub mod clique; pub use self::account::Account; pub use self::builtin::{Builtin, Pricing, Linear}; @@ -44,6 +45,7 @@ pub use self::ethash::{Ethash, EthashParams, BlockReward}; pub use self::validator_set::ValidatorSet; pub use self::basic_authority::{BasicAuthority, BasicAuthorityParams}; pub use self::authority_round::{AuthorityRound, AuthorityRoundParams}; +pub use self::clique::{Clique, CliqueParams}; pub use self::null_engine::{NullEngine, NullEngineParams}; pub use self::instant_seal::{InstantSeal, InstantSealParams}; pub use self::hardcoded_sync::HardcodedSync; diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index 765384a6b9..e8b3ded8a9 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -92,8 +92,18 @@ pub struct Params { /// See `CommonParams` docs. pub eip1283_disable_transition: Option, /// See `CommonParams` docs. + pub eip1283_reenable_transition: Option, + /// See `CommonParams` docs. pub eip1014_transition: Option, /// See `CommonParams` docs. + pub eip1706_transition: Option, + /// See `CommonParams` docs. + pub eip1344_transition: Option, + /// See `CommonParams` docs. + pub eip1884_transition: Option, + /// See `CommonParams` docs. + pub eip2028_transition: Option, + /// See `CommonParams` docs. pub dust_protection_transition: Option, /// See `CommonParams` docs. pub nonce_cap_increment: Option, diff --git a/json/src/spec/spec.rs b/json/src/spec/spec.rs index 68824cad99..013320c27d 100644 --- a/json/src/spec/spec.rs +++ b/json/src/spec/spec.rs @@ -31,6 +31,7 @@ pub enum ForkSpec { Byzantium, Constantinople, ConstantinopleFix, + Istanbul, EIP158ToByzantiumAt5, FrontierToHomesteadAt5, HomesteadToDaoAt5, diff --git a/machine/Cargo.toml b/machine/Cargo.toml deleted file mode 100644 index 2ebb5c4099..0000000000 --- a/machine/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "parity-machine" -version = "0.1.0" -description = "Generalization of a state machine for consensus engines" -authors = ["Parity Technologies "] - -[dependencies] -ethereum-types = "0.4" diff --git a/machine/src/lib.rs b/machine/src/lib.rs deleted file mode 100644 index 8a0b5e3f2e..0000000000 --- a/machine/src/lib.rs +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -//! Generalization of a state machine for a consensus engine. -//! This will define traits for the header, block, and state of a blockchain. - -extern crate ethereum_types; - -use ethereum_types::{H256, U256, Address}; - -/// A header. This contains important metadata about the block, as well as a -/// "seal" that indicates validity to a consensus engine. -pub trait Header { - /// Cryptographic hash of the header, excluding the seal. - fn bare_hash(&self) -> H256; - - /// Cryptographic hash of the header, including the seal. - fn hash(&self) -> H256; - - /// Get a reference to the seal fields. - fn seal(&self) -> &[Vec]; - - /// The author of the header. - fn author(&self) -> &Address; - - /// The number of the header. - fn number(&self) -> u64; -} - -/// A header with an associated score (difficulty in PoW terms) -pub trait ScoredHeader: Header { - type Value; - - /// Get the score of this header. - fn score(&self) -> &Self::Value; - - /// Set the score of this header. - fn set_score(&mut self, score: Self::Value); -} - -/// A header with associated total score. -pub trait TotalScoredHeader: Header { - type Value; - - /// Get the total score of this header. - fn total_score(&self) -> Self::Value; -} - -/// A header with finalized information. -pub trait FinalizableHeader: Header { - /// Get whether this header is considered finalized, so that it will never be replaced in reorganization. - fn is_finalized(&self) -> bool; -} - -/// A header with metadata information. -pub trait WithMetadataHeader: Header { - /// Get the current header metadata. - fn metadata(&self) -> Option<&[u8]>; -} - -/// A "live" block is one which is in the process of the transition. -/// The state of this block can be mutated by arbitrary rules of the -/// state transition function. -pub trait LiveBlock: 'static { - /// The block header type; - type Header: Header; - - /// Get a reference to the header. - fn header(&self) -> &Self::Header; - - /// Get a reference to the uncle headers. If the block type doesn't - /// support uncles, return the empty slice. - fn uncles(&self) -> &[Self::Header]; -} - -/// Trait for blocks which have a transaction type. -pub trait Transactions: LiveBlock { - /// The transaction type. - type Transaction; - - /// Get a reference to the transactions in this block. - fn transactions(&self) -> &[Self::Transaction]; -} - -/// Generalization of types surrounding blockchain-suitable state machines. -pub trait Machine: for<'a> LocalizedMachine<'a> { - /// The block header type. - type Header: Header; - /// The live block type. - type LiveBlock: LiveBlock; - /// Block header with metadata information. - type ExtendedHeader: Header; - /// A handle to a blockchain client for this machine. - type EngineClient: ?Sized; - /// A description of needed auxiliary data. - type AuxiliaryRequest; - /// Actions taken on ancestry blocks when commiting a new block. - type AncestryAction; - - /// Errors which can occur when querying or interacting with the machine. - type Error; -} - -/// Machine-related types localized to a specific lifetime. -// TODO: this is a workaround for a lack of associated type constructors in the language. -pub trait LocalizedMachine<'a>: Sync + Send { - /// Definition of auxiliary data associated to a specific block. - type AuxiliaryData: 'a; - /// A context providing access to the state in a controlled capacity. - /// Generally also provides verifiable proofs. - type StateContext: ?Sized + 'a; -} - -/// A state machine that uses balances. -pub trait WithBalances: Machine { - /// Get the balance, in base units, associated with an account. - /// Extracts data from the live block. - fn balance(&self, live: &Self::LiveBlock, address: &Address) -> Result; - - /// Increment the balance of an account in the state of the live block. - fn add_balance(&self, live: &mut Self::LiveBlock, address: &Address, amount: &U256) -> Result<(), Self::Error>; -} diff --git a/miner/Cargo.toml b/miner/Cargo.toml index 02e64ad4f8..7432b10512 100644 --- a/miner/Cargo.toml +++ b/miner/Cargo.toml @@ -1,5 +1,5 @@ [package] -description = "Parity Miner interface." +description = "Parity Ethereum Miner Interface." name = "ethcore-miner" homepage = "http://parity.io" license = "GPL-3.0" @@ -32,7 +32,7 @@ parking_lot = "0.7" price-info = { path = "./price-info", optional = true } rlp = { version = "0.3.0", features = ["ethereum"] } trace-time = "0.1" -transaction-pool = "1.13" +transaction-pool = "2.0.1" [dev-dependencies] env_logger = "0.5" diff --git a/miner/src/gas_pricer.rs b/miner/src/gas_pricer.rs index 0f851a9f86..c4e04442f1 100644 --- a/miner/src/gas_pricer.rs +++ b/miner/src/gas_pricer.rs @@ -45,7 +45,7 @@ impl GasPricer { /// Recalibrate current gas price. pub fn recalibrate(&mut self, set_price: F) { match *self { - GasPricer::Fixed(ref max) => set_price(max.clone()), + GasPricer::Fixed(ref curr) => set_price(curr.clone()), #[cfg(feature = "price-info")] GasPricer::Calibrated(ref mut cal) => cal.recalibrate(set_price), } diff --git a/miner/src/lib.rs b/miner/src/lib.rs index 921e6dbaad..55091093ac 100644 --- a/miner/src/lib.rs +++ b/miner/src/lib.rs @@ -57,6 +57,7 @@ pub mod external; #[cfg(feature = "price-info")] pub mod gas_price_calibrator; pub mod gas_pricer; +pub mod local_accounts; pub mod pool; pub mod service_transaction_checker; #[cfg(feature = "work-notify")] diff --git a/json/src/misc/account_meta.rs b/miner/src/local_accounts.rs similarity index 56% rename from json/src/misc/account_meta.rs rename to miner/src/local_accounts.rs index f6f8c0c637..23bcf81442 100644 --- a/json/src/misc/account_meta.rs +++ b/miner/src/local_accounts.rs @@ -14,19 +14,30 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -//! Misc deserialization. - -use hash; - -/// Collected account metadata -#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct AccountMeta { - /// The name of the account. - pub name: String, - /// The rest of the metadata of the account. - pub meta: String, - /// The 128-bit Uuid of the account, if it has one (brain-wallets don't). - pub uuid: Option, +//! Local Accounts checker + +use std::collections::HashSet; + +use ethereum_types::Address; + +/// Local accounts checker +pub trait LocalAccounts: Send + Sync { + /// Returns true if given address should be considered local account. + fn is_local(&self, &Address) -> bool; +} + +impl LocalAccounts for HashSet
{ + fn is_local(&self, address: &Address) -> bool { + self.contains(address) + } +} + +impl LocalAccounts for (A, B) where + A: LocalAccounts, + B: LocalAccounts, +{ + fn is_local(&self, address: &Address) -> bool { + self.0.is_local(address) || self.1.is_local(address) + } } -impl_serialization!(hash::Address => AccountMeta); diff --git a/miner/src/pool/listener.rs b/miner/src/pool/listener.rs index fac98b0a17..67034aa523 100644 --- a/miner/src/pool/listener.rs +++ b/miner/src/pool/listener.rs @@ -92,7 +92,7 @@ impl txpool::Listener for Logger { } } - fn rejected(&mut self, _tx: &Arc, reason: &txpool::ErrorKind) { + fn rejected(&mut self, _tx: &Arc, reason: &txpool::Error) { trace!(target: "txqueue", "Rejected {}.", reason); } diff --git a/miner/src/pool/local_transactions.rs b/miner/src/pool/local_transactions.rs index c805484d1c..346877d030 100644 --- a/miner/src/pool/local_transactions.rs +++ b/miner/src/pool/local_transactions.rs @@ -171,7 +171,7 @@ impl txpool::Listener for LocalTransactionsList { } } - fn rejected(&mut self, tx: &Arc, reason: &txpool::ErrorKind) { + fn rejected(&mut self, tx: &Arc, reason: &txpool::Error) { if !tx.priority().is_local() { return; } diff --git a/miner/src/pool/mod.rs b/miner/src/pool/mod.rs index 561b85f4bc..40a226d9fc 100644 --- a/miner/src/pool/mod.rs +++ b/miner/src/pool/mod.rs @@ -27,6 +27,7 @@ mod ready; pub mod client; pub mod local_transactions; +pub mod replace; pub mod scoring; pub mod verifier; @@ -121,7 +122,7 @@ pub trait ScoredTransaction { } /// Verified transaction stored in the pool. -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct VerifiedTransaction { transaction: transaction::PendingTransaction, // TODO [ToDr] hash and sender should go directly from the transaction diff --git a/miner/src/pool/queue.rs b/miner/src/pool/queue.rs index 51c46ad823..58966df859 100644 --- a/miner/src/pool/queue.rs +++ b/miner/src/pool/queue.rs @@ -27,7 +27,7 @@ use txpool::{self, Verifier}; use types::transaction; use pool::{ - self, scoring, verifier, client, ready, listener, + self, replace, scoring, verifier, client, ready, listener, PrioritizationStrategy, PendingOrdering, PendingSettings, }; use pool::local_transactions::LocalTransactionsList; @@ -240,7 +240,7 @@ impl TransactionQueue { /// /// Given blockchain and state access (Client) /// verifies and imports transactions to the pool. - pub fn import( + pub fn import( &self, client: C, transactions: Vec, @@ -263,12 +263,14 @@ impl TransactionQueue { }; let verifier = verifier::Verifier::new( - client, + client.clone(), options, self.insertion_id.clone(), transaction_to_replace, ); + let mut replace = replace::ReplaceByScoreAndReadiness::new(self.pool.read().scoring().clone(), client); + let results = transactions .into_iter() .map(|transaction| { @@ -286,7 +288,7 @@ impl TransactionQueue { let imported = verifier .verify_transaction(transaction) .and_then(|verified| { - self.pool.write().import(verified).map_err(convert_error) + self.pool.write().import(verified, &mut replace).map_err(convert_error) }); match imported { @@ -579,17 +581,13 @@ impl TransactionQueue { } } -fn convert_error(err: txpool::Error) -> transaction::Error { - use self::txpool::ErrorKind; - - match *err.kind() { - ErrorKind::AlreadyImported(..) => transaction::Error::AlreadyImported, - ErrorKind::TooCheapToEnter(..) => transaction::Error::LimitReached, - ErrorKind::TooCheapToReplace(..) => transaction::Error::TooCheapToReplace, - ref e => { - warn!(target: "txqueue", "Unknown import error: {:?}", e); - transaction::Error::NotAllowed - }, +fn convert_error(err: txpool::Error) -> transaction::Error { + use self::txpool::Error; + + match err { + Error::AlreadyImported(..) => transaction::Error::AlreadyImported, + Error::TooCheapToEnter(..) => transaction::Error::LimitReached, + Error::TooCheapToReplace(..) => transaction::Error::TooCheapToReplace { prev: None, new: None } } } diff --git a/miner/src/pool/replace.rs b/miner/src/pool/replace.rs new file mode 100644 index 0000000000..0655af5999 --- /dev/null +++ b/miner/src/pool/replace.rs @@ -0,0 +1,513 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +//! Replacing Transactions +//! +//! When queue limits are reached, a new transaction may replace one already +//! in the pool. The decision whether to reject, replace or retain both is +//! delegated to an implementation of `ShouldReplace`. +//! +//! Here we decide based on the sender, the nonce and gas price, and finally +//! on the `Readiness` of the transactions when comparing them + +use std::cmp; + +use ethereum_types::{U256, H160 as Address}; +use txpool::{self, scoring::{Choice, Scoring}, ReplaceTransaction}; +use txpool::VerifiedTransaction; +use super::{client, ScoredTransaction}; + +/// Choose whether to replace based on the sender, the score and finally the +/// `Readiness` of the transactions being compared. +#[derive(Debug)] +pub struct ReplaceByScoreAndReadiness { + scoring: S, + client: C, +} + +impl ReplaceByScoreAndReadiness { + /// Create a new `ReplaceByScoreAndReadiness` + pub fn new(scoring: S, client: C) -> Self { + ReplaceByScoreAndReadiness { scoring, client } + } +} + +impl txpool::ShouldReplace for ReplaceByScoreAndReadiness +where + T: VerifiedTransaction + ScoredTransaction + PartialEq, + S: Scoring, + C: client::NonceClient, +{ + fn should_replace( + &self, + old: &ReplaceTransaction, + new: &ReplaceTransaction, + ) -> Choice { + let both_local = old.priority().is_local() && new.priority().is_local(); + if old.sender() == new.sender() { + // prefer earliest transaction + match new.nonce().cmp(&old.nonce()) { + cmp::Ordering::Equal => self.scoring.choose(&old, &new), + _ if both_local => Choice::InsertNew, + cmp::Ordering::Less => Choice::ReplaceOld, + cmp::Ordering::Greater => Choice::RejectNew, + } + } else if both_local { + Choice::InsertNew + } else { + let old_score = (old.priority(), old.gas_price()); + let new_score = (new.priority(), new.gas_price()); + if new_score > old_score { + // Check if this is a replacement transaction. + // + // With replacement transactions we can safely return `InsertNew` here, because + // we don't need to remove `old` (worst transaction in the pool) since `new` will replace + // some other transaction in the pool so we will never go above limit anyway. + if let Some(txs) = new.pooled_by_sender { + if let Ok(index) = txs.binary_search_by(|old| self.scoring.compare(old, new)) { + return match self.scoring.choose(&txs[index], new) { + Choice::ReplaceOld => Choice::InsertNew, + choice => choice, + } + } + } + + let state = &self.client; + // calculate readiness based on state nonce + pooled txs from same sender + let is_ready = |replace: &ReplaceTransaction| { + let mut nonce = state.account_nonce(replace.sender()); + if let Some(txs) = replace.pooled_by_sender { + for tx in txs.iter() { + if nonce == tx.nonce() && *tx.transaction != ***replace.transaction { + nonce = nonce.saturating_add(U256::from(1)) + } else { + break + } + } + } + nonce == replace.nonce() + }; + + if !is_ready(new) && is_ready(old) { + // prevent a ready transaction being replace by a non-ready transaction + Choice::RejectNew + } else { + Choice::ReplaceOld + } + } else { + Choice::RejectNew + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use std::sync::Arc; + use ethkey::{Random, Generator, KeyPair}; + use pool::tests::tx::{Tx, TxExt}; + use pool::tests::client::TestClient; + use pool::scoring::*; + use pool::{PrioritizationStrategy, VerifiedTransaction}; + use txpool::scoring::Choice::*; + use txpool::ShouldReplace; + + fn local_tx_verified(tx: Tx, keypair: &KeyPair) -> VerifiedTransaction { + let mut verified_tx = tx.unsigned().sign(keypair.secret(), None).verified(); + verified_tx.priority = ::pool::Priority::Local; + verified_tx + } + + fn should_replace(replace: &ShouldReplace, old: VerifiedTransaction, new: VerifiedTransaction) -> Choice { + let old_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(old) }; + let new_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(new) }; + let old = ReplaceTransaction::new(&old_tx, Default::default()); + let new = ReplaceTransaction::new(&new_tx, Default::default()); + replace.should_replace(&old, &new) + } + + #[test] + fn should_always_accept_local_transactions_unless_same_sender_and_nonce() { + let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly); + let client = TestClient::new().with_nonce(1); + let replace = ReplaceByScoreAndReadiness::new(scoring, client); + + // same sender txs + let keypair = Random.generate().unwrap(); + + let same_sender_tx1 = local_tx_verified(Tx { + nonce: 1, + gas_price: 1, + ..Default::default() + }, &keypair); + + let same_sender_tx2 = local_tx_verified(Tx { + nonce: 2, + gas_price: 100, + ..Default::default() + }, &keypair); + + let same_sender_tx3 = local_tx_verified(Tx { + nonce: 2, + gas_price: 200, + ..Default::default() + }, &keypair); + + // different sender txs + let sender1 = Random.generate().unwrap(); + let different_sender_tx1 = local_tx_verified(Tx { + nonce: 2, + gas_price: 1, + ..Default::default() + }, &sender1); + + let sender2 = Random.generate().unwrap(); + let different_sender_tx2 = local_tx_verified(Tx { + nonce: 1, + gas_price: 10, + ..Default::default() + }, &sender2); + + assert_eq!(should_replace(&replace, same_sender_tx1.clone(), same_sender_tx2.clone()), InsertNew); + assert_eq!(should_replace(&replace, same_sender_tx2.clone(), same_sender_tx1.clone()), InsertNew); + + assert_eq!(should_replace(&replace, different_sender_tx1.clone(), different_sender_tx2.clone()), InsertNew); + assert_eq!(should_replace(&replace, different_sender_tx2.clone(), different_sender_tx1.clone()), InsertNew); + + // txs with same sender and nonce + assert_eq!(should_replace(&replace, same_sender_tx2.clone(), same_sender_tx3.clone()), ReplaceOld); + assert_eq!(should_replace(&replace, same_sender_tx3.clone(), same_sender_tx2.clone()), RejectNew); + } + + #[test] + fn should_replace_same_sender_by_nonce() { + let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly); + let client = TestClient::new().with_nonce(1); + let replace = ReplaceByScoreAndReadiness::new(scoring, client); + + let tx1 = Tx { + nonce: 1, + gas_price: 1, + ..Default::default() + }; + let tx2 = Tx { + nonce: 2, + gas_price: 100, + ..Default::default() + }; + let tx3 = Tx { + nonce: 2, + gas_price: 110, + ..Default::default() + }; + let tx4 = Tx { + nonce: 2, + gas_price: 130, + ..Default::default() + }; + + let keypair = Random.generate().unwrap(); + let txs = vec![tx1, tx2, tx3, tx4].into_iter().map(|tx| { + tx.unsigned().sign(keypair.secret(), None).verified() + }).collect::>(); + + assert_eq!(should_replace(&replace, txs[0].clone(), txs[1].clone()), RejectNew); + assert_eq!(should_replace(&replace, txs[1].clone(), txs[0].clone()), ReplaceOld); + + assert_eq!(should_replace(&replace, txs[1].clone(), txs[2].clone()), RejectNew); + assert_eq!(should_replace(&replace, txs[2].clone(), txs[1].clone()), RejectNew); + + assert_eq!(should_replace(&replace, txs[1].clone(), txs[3].clone()), ReplaceOld); + assert_eq!(should_replace(&replace, txs[3].clone(), txs[1].clone()), RejectNew); + } + + #[test] + fn should_replace_different_sender_by_priority_and_gas_price() { + // given + let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly); + let client = TestClient::new().with_nonce(0); + let replace = ReplaceByScoreAndReadiness::new(scoring, client); + + let tx_regular_low_gas = { + let tx = Tx { + nonce: 1, + gas_price: 1, + ..Default::default() + }; + tx.signed().verified() + }; + let tx_regular_high_gas = { + let tx = Tx { + nonce: 2, + gas_price: 10, + ..Default::default() + }; + tx.signed().verified() + }; + let tx_local_low_gas = { + let tx = Tx { + nonce: 2, + gas_price: 1, + ..Default::default() + }; + let mut verified_tx = tx.signed().verified(); + verified_tx.priority = ::pool::Priority::Local; + verified_tx + }; + let tx_local_high_gas = { + let tx = Tx { + nonce: 1, + gas_price: 10, + ..Default::default() + }; + let mut verified_tx = tx.signed().verified(); + verified_tx.priority = ::pool::Priority::Local; + verified_tx + }; + + assert_eq!(should_replace(&replace, tx_regular_low_gas.clone(), tx_regular_high_gas.clone()), ReplaceOld); + assert_eq!(should_replace(&replace, tx_regular_high_gas.clone(), tx_regular_low_gas.clone()), RejectNew); + + assert_eq!(should_replace(&replace, tx_regular_high_gas.clone(), tx_local_low_gas.clone()), ReplaceOld); + assert_eq!(should_replace(&replace, tx_local_low_gas.clone(), tx_regular_high_gas.clone()), RejectNew); + + assert_eq!(should_replace(&replace, tx_local_low_gas.clone(), tx_local_high_gas.clone()), InsertNew); + assert_eq!(should_replace(&replace, tx_local_high_gas.clone(), tx_regular_low_gas.clone()), RejectNew); + } + + #[test] + fn should_not_replace_ready_transaction_with_future_transaction() { + let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly); + let client = TestClient::new().with_nonce(1); + let replace = ReplaceByScoreAndReadiness::new(scoring, client); + + let tx_ready_low_score = { + let tx = Tx { + nonce: 1, + gas_price: 1, + ..Default::default() + }; + tx.signed().verified() + }; + let tx_future_high_score = { + let tx = Tx { + nonce: 3, // future nonce + gas_price: 10, + ..Default::default() + }; + tx.signed().verified() + }; + + assert_eq!(should_replace(&replace, tx_ready_low_score, tx_future_high_score), RejectNew); + } + + #[test] + fn should_compute_readiness_with_pooled_transactions_from_the_same_sender_as_the_existing_transaction() { + let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly); + let client = TestClient::new().with_nonce(1); + let replace = ReplaceByScoreAndReadiness::new(scoring, client); + + let old_sender = Random.generate().unwrap(); + let tx_old_ready_1 = { + let tx = Tx { + nonce: 1, + gas_price: 1, + ..Default::default() + }; + tx.unsigned().sign(&old_sender.secret(), None).verified() + }; + let tx_old_ready_2 = { + let tx = Tx { + nonce: 2, + gas_price: 1, + ..Default::default() + }; + tx.unsigned().sign(&old_sender.secret(), None).verified() + }; + let tx_old_ready_3 = { + let tx = Tx { + nonce: 3, + gas_price: 1, + ..Default::default() + }; + tx.unsigned().sign(&old_sender.secret(), None).verified() + }; + + let new_tx = { + let tx = Tx { + nonce: 3, // future nonce + gas_price: 10, + ..Default::default() + }; + tx.signed().verified() + }; + + let old_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_old_ready_3) }; + let pooled_txs = [ + txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_old_ready_1) }, + txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_old_ready_2) }, + ]; + + let new_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(new_tx) }; + + let old = ReplaceTransaction::new(&old_tx, Some(&pooled_txs)); + let new = ReplaceTransaction::new(&new_tx, Default::default()); + + assert_eq!(replace.should_replace(&old, &new), RejectNew); + } + + #[test] + fn should_compute_readiness_with_pooled_transactions_from_the_same_sender_as_the_new_transaction() { + let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly); + let client = TestClient::new().with_nonce(1); + let replace = ReplaceByScoreAndReadiness::new(scoring, client); + + // current transaction is ready but has a lower gas price than the new one + let old_tx = { + let tx = Tx { + nonce: 1, + gas_price: 1, + ..Default::default() + }; + tx.signed().verified() + }; + + let new_sender = Random.generate().unwrap(); + let tx_new_ready_1 = { + let tx = Tx { + nonce: 1, + gas_price: 1, + ..Default::default() + }; + tx.unsigned().sign(&new_sender.secret(), None).verified() + }; + let tx_new_ready_2 = { + let tx = Tx { + nonce: 2, + gas_price: 1, + ..Default::default() + }; + tx.unsigned().sign(&new_sender.secret(), None).verified() + }; + let tx_new_ready_3 = { + let tx = Tx { + nonce: 3, + gas_price: 10, // hi + ..Default::default() + }; + tx.unsigned().sign(&new_sender.secret(), None).verified() + }; + + let old_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(old_tx) }; + + let new_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_new_ready_3) }; + let pooled_txs = [ + txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_new_ready_1) }, + txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_new_ready_2) }, + ]; + + let old = ReplaceTransaction::new(&old_tx, None); + let new = ReplaceTransaction::new(&new_tx, Some(&pooled_txs)); + + assert_eq!(replace.should_replace(&old, &new), ReplaceOld); + } + + #[test] + fn should_accept_local_tx_with_same_sender_and_nonce_with_better_gas_price() { + let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly); + let client = TestClient::new().with_nonce(1); + let replace = ReplaceByScoreAndReadiness::new(scoring, client); + + // current transaction is ready + let old_tx = { + let tx = Tx { + nonce: 1, + gas_price: 1, + ..Default::default() + }; + tx.signed().verified() + }; + + let new_sender = Random.generate().unwrap(); + let tx_new_ready_1 = local_tx_verified(Tx { + nonce: 1, + gas_price: 1, + ..Default::default() + }, &new_sender); + + let tx_new_ready_2 = local_tx_verified(Tx { + nonce: 1, + gas_price: 2, // same nonce, higher gas price + ..Default::default() + }, &new_sender); + + let old_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(old_tx) }; + + let new_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_new_ready_2) }; + let pooled_txs = [ + txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_new_ready_1) }, + ]; + + let old = ReplaceTransaction::new(&old_tx, None); + let new = ReplaceTransaction::new(&new_tx, Some(&pooled_txs)); + + assert_eq!(replace.should_replace(&old, &new), InsertNew); + } + + #[test] + fn should_reject_local_tx_with_same_sender_and_nonce_with_worse_gas_price() { + let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly); + let client = TestClient::new().with_nonce(1); + let replace = ReplaceByScoreAndReadiness::new(scoring, client); + + // current transaction is ready + let old_tx = { + let tx = Tx { + nonce: 1, + gas_price: 1, + ..Default::default() + }; + tx.signed().verified() + }; + + let new_sender = Random.generate().unwrap(); + let tx_new_ready_1 = local_tx_verified(Tx { + nonce: 1, + gas_price: 2, + ..Default::default() + }, &new_sender); + + let tx_new_ready_2 = local_tx_verified(Tx { + nonce: 1, + gas_price: 1, // same nonce, lower gas price + ..Default::default() + }, &new_sender); + + let old_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(old_tx) }; + + let new_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_new_ready_2) }; + let pooled_txs = [ + txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_new_ready_1) }, + ]; + + let old = ReplaceTransaction::new(&old_tx, None); + let new = ReplaceTransaction::new(&new_tx, Some(&pooled_txs)); + + assert_eq!(replace.should_replace(&old, &new), RejectNew); + } +} diff --git a/miner/src/pool/scoring.rs b/miner/src/pool/scoring.rs index aff7ac49ef..0360bec354 100644 --- a/miner/src/pool/scoring.rs +++ b/miner/src/pool/scoring.rs @@ -122,29 +122,6 @@ impl

txpool::Scoring

for NonceAndGasPrice where P: ScoredTransaction + txp } } - fn should_replace(&self, old: &P, new: &P) -> scoring::Choice { - let both_local = old.priority().is_local() && new.priority().is_local(); - if old.sender() == new.sender() { - // prefer earliest transaction - match new.nonce().cmp(&old.nonce()) { - cmp::Ordering::Equal => self.choose(old, new), - _ if both_local => scoring::Choice::InsertNew, - cmp::Ordering::Less => scoring::Choice::ReplaceOld, - cmp::Ordering::Greater => scoring::Choice::RejectNew, - } - } else if both_local { - scoring::Choice::InsertNew - } else { - let old_score = (old.priority(), old.gas_price()); - let new_score = (new.priority(), new.gas_price()); - if new_score > old_score { - scoring::Choice::ReplaceOld - } else { - scoring::Choice::RejectNew - } - } - } - fn should_ignore_sender_limit(&self, new: &P) -> bool { new.priority().is_local() } @@ -155,156 +132,8 @@ mod tests { use super::*; use std::sync::Arc; - use ethkey::{Random, Generator, KeyPair}; use pool::tests::tx::{Tx, TxExt}; use txpool::Scoring; - use txpool::scoring::Choice::*; - - fn local_tx_verified(tx: Tx, keypair: &KeyPair) -> VerifiedTransaction { - let mut verified_tx = tx.unsigned().sign(keypair.secret(), None).verified(); - verified_tx.priority = ::pool::Priority::Local; - verified_tx - } - - #[test] - fn should_always_accept_local_transactions_unless_same_sender_and_nonce() { - let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly); - - // same sender txs - let keypair = Random.generate().unwrap(); - - let same_sender_tx1 = local_tx_verified(Tx { - nonce: 1, - gas_price: 1, - ..Default::default() - }, &keypair); - - let same_sender_tx2 = local_tx_verified(Tx { - nonce: 2, - gas_price: 100, - ..Default::default() - }, &keypair); - - let same_sender_tx3 = local_tx_verified(Tx { - nonce: 2, - gas_price: 200, - ..Default::default() - }, &keypair); - - // different sender txs - let different_sender_tx1 = local_tx_verified(Tx { - nonce: 2, - gas_price: 1, - ..Default::default() - }, &Random.generate().unwrap()); - - let different_sender_tx2 = local_tx_verified(Tx { - nonce: 1, - gas_price: 10, - ..Default::default() - }, &Random.generate().unwrap()); - - assert_eq!(scoring.should_replace(&same_sender_tx1, &same_sender_tx2), InsertNew); - assert_eq!(scoring.should_replace(&same_sender_tx2, &same_sender_tx1), InsertNew); - - assert_eq!(scoring.should_replace(&different_sender_tx1, &different_sender_tx2), InsertNew); - assert_eq!(scoring.should_replace(&different_sender_tx2, &different_sender_tx1), InsertNew); - - // txs with same sender and nonce - assert_eq!(scoring.should_replace(&same_sender_tx2, &same_sender_tx3), ReplaceOld); - assert_eq!(scoring.should_replace(&same_sender_tx3, &same_sender_tx2), RejectNew); - } - - #[test] - fn should_replace_same_sender_by_nonce() { - let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly); - - let tx1 = Tx { - nonce: 1, - gas_price: 1, - ..Default::default() - }; - let tx2 = Tx { - nonce: 2, - gas_price: 100, - ..Default::default() - }; - let tx3 = Tx { - nonce: 2, - gas_price: 110, - ..Default::default() - }; - let tx4 = Tx { - nonce: 2, - gas_price: 130, - ..Default::default() - }; - - let keypair = Random.generate().unwrap(); - let txs = vec![tx1, tx2, tx3, tx4].into_iter().map(|tx| { - tx.unsigned().sign(keypair.secret(), None).verified() - }).collect::>(); - - assert_eq!(scoring.should_replace(&txs[0], &txs[1]), RejectNew); - assert_eq!(scoring.should_replace(&txs[1], &txs[0]), ReplaceOld); - - assert_eq!(scoring.should_replace(&txs[1], &txs[2]), RejectNew); - assert_eq!(scoring.should_replace(&txs[2], &txs[1]), RejectNew); - - assert_eq!(scoring.should_replace(&txs[1], &txs[3]), ReplaceOld); - assert_eq!(scoring.should_replace(&txs[3], &txs[1]), RejectNew); - } - - #[test] - fn should_replace_different_sender_by_priority_and_gas_price() { - // given - let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly); - let tx_regular_low_gas = { - let tx = Tx { - nonce: 1, - gas_price: 1, - ..Default::default() - }; - tx.signed().verified() - }; - let tx_regular_high_gas = { - let tx = Tx { - nonce: 2, - gas_price: 10, - ..Default::default() - }; - tx.signed().verified() - }; - let tx_local_low_gas = { - let tx = Tx { - nonce: 2, - gas_price: 1, - ..Default::default() - }; - let mut verified_tx = tx.signed().verified(); - verified_tx.priority = ::pool::Priority::Local; - verified_tx - }; - let tx_local_high_gas = { - let tx = Tx { - nonce: 1, - gas_price: 10, - ..Default::default() - }; - let mut verified_tx = tx.signed().verified(); - verified_tx.priority = ::pool::Priority::Local; - verified_tx - }; - - assert_eq!(scoring.should_replace(&tx_regular_low_gas, &tx_regular_high_gas), ReplaceOld); - assert_eq!(scoring.should_replace(&tx_regular_high_gas, &tx_regular_low_gas), RejectNew); - - assert_eq!(scoring.should_replace(&tx_regular_high_gas, &tx_local_low_gas), ReplaceOld); - assert_eq!(scoring.should_replace(&tx_local_low_gas, &tx_regular_high_gas), RejectNew); - - assert_eq!(scoring.should_replace(&tx_local_low_gas, &tx_local_high_gas), InsertNew); - assert_eq!(scoring.should_replace(&tx_local_high_gas, &tx_regular_low_gas), RejectNew); - } #[test] fn should_calculate_score_correctly() { diff --git a/miner/src/pool/tests/mod.rs b/miner/src/pool/tests/mod.rs index ad9f6824fa..1df1be4ce7 100644 --- a/miner/src/pool/tests/mod.rs +++ b/miner/src/pool/tests/mod.rs @@ -91,13 +91,13 @@ fn should_return_correct_nonces_when_dropped_because_of_limit() { // then assert_eq!(res, vec![Ok(()), Ok(())]); assert_eq!(res2, vec![ - // The error here indicates reaching the limit - // and minimal effective gas price taken into account. - Err(transaction::Error::InsufficientGasPrice { minimal: 2.into(), got: 1.into() }), - Ok(()) + // The error here indicates reaching the limit + // and minimal effective gas price taken into account. + Err(transaction::Error::TooCheapToReplace { prev: Some(2.into()), new: Some(1.into()) }), + Ok(()) ]); assert_eq!(txq.status().status.transaction_count, 3); - // tx2 transacton got dropped because of limit + // tx2 transaction got dropped because of limit // tx1 and tx1' are kept, because they have lower insertion_ids so they are preferred. assert_eq!(txq.next_nonce(TestClient::new(), &sender), None); } @@ -585,7 +585,7 @@ fn should_not_replace_same_transaction_if_the_fee_is_less_than_minimal_bump() { let res = txq.import(client.clone(), vec![tx2, tx4].local()); // then - assert_eq!(res, vec![Err(transaction::Error::TooCheapToReplace), Ok(())]); + assert_eq!(res, vec![Err(transaction::Error::TooCheapToReplace { prev: None, new: None }), Ok(())]); assert_eq!(txq.status().status.transaction_count, 2); assert_eq!(txq.pending(client.clone(), PendingSettings::all_prioritized(0, 0))[0].signed().gas_price, U256::from(20)); assert_eq!(txq.pending(client.clone(), PendingSettings::all_prioritized(0, 0))[1].signed().gas_price, U256::from(2)); @@ -1027,9 +1027,9 @@ fn should_reject_early_in_case_gas_price_is_less_than_min_effective() { let client = TestClient::new(); let tx1 = Tx::default().signed().unverified(); let res = txq.import(client.clone(), vec![tx1]); - assert_eq!(res, vec![Err(transaction::Error::InsufficientGasPrice { - minimal: 2.into(), - got: 1.into(), + assert_eq!(res, vec![Err(transaction::Error::TooCheapToReplace { + prev: Some(2.into()), + new: Some(1.into()), })]); assert!(!client.was_verification_triggered()); diff --git a/miner/src/pool/verifier.rs b/miner/src/pool/verifier.rs index 1fded37630..51232e967a 100644 --- a/miner/src/pool/verifier.rs +++ b/miner/src/pool/verifier.rs @@ -231,9 +231,9 @@ impl txpool::Verifier for Verifier(&self, client: &C) -> Result { + trace!(target: "txqueue", "Refreshing certified addresses cache"); + // replace the cache with an empty list, + // since it's not recent it won't be used anyway. + let cache = mem::replace(&mut *self.certified_addresses_cache.write(), HashMap::default()); + + if let Some(contract_address) = client.registry_address(SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned(), BlockId::Latest) { + let addresses: Vec<_> = cache.keys().collect(); + let mut cache: HashMap = HashMap::default(); + for address in addresses { + let allowed = self.call_contract(client, contract_address, *address)?; + cache.insert(*address, allowed); + } + mem::replace(&mut *self.certified_addresses_cache.write(), cache); + Ok(true) + } else { + Ok(false) + } + } + fn call_contract(&self, client: &C, contract_address: Address, sender: Address) -> Result { let (data, decoder) = service_transaction::functions::certified::call(sender); - let value = client.call_contract(BlockId::Latest, address, data)?; + let value = client.call_contract(BlockId::Latest, contract_address, data)?; decoder.decode(&value).map_err(|e| e.to_string()) } } diff --git a/miner/stratum/Cargo.toml b/miner/stratum/Cargo.toml index 137604d53b..a7e13ef681 100644 --- a/miner/stratum/Cargo.toml +++ b/miner/stratum/Cargo.toml @@ -8,9 +8,8 @@ authors = ["Parity Technologies "] [dependencies] ethereum-types = "0.4" keccak-hash = "0.1" -jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } -jsonrpc-macros = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } -jsonrpc-tcp-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } +jsonrpc-core = "10.0.1" +jsonrpc-tcp-server = "10.0.1" log = "0.4" parking_lot = "0.7" diff --git a/miner/stratum/src/lib.rs b/miner/stratum/src/lib.rs index 5d2cb68a35..5ee0296dac 100644 --- a/miner/stratum/src/lib.rs +++ b/miner/stratum/src/lib.rs @@ -18,7 +18,6 @@ extern crate jsonrpc_tcp_server; extern crate jsonrpc_core; -extern crate jsonrpc_macros; extern crate ethereum_types; extern crate keccak_hash as hash; extern crate parking_lot; @@ -39,8 +38,7 @@ use jsonrpc_tcp_server::{ Server as JsonRpcServer, ServerBuilder as JsonRpcServerBuilder, RequestContext, MetaExtractor, Dispatcher, PushMessageError, }; -use jsonrpc_core::{MetaIoHandler, Params, to_value, Value, Metadata, Compatibility}; -use jsonrpc_macros::IoDelegate; +use jsonrpc_core::{MetaIoHandler, Params, to_value, Value, Metadata, Compatibility, IoDelegate}; use std::sync::Arc; use std::net::SocketAddr; diff --git a/parity-clib/Cargo.toml b/parity-clib/Cargo.toml index b3635c6e08..f57e503dea 100644 --- a/parity-clib/Cargo.toml +++ b/parity-clib/Cargo.toml @@ -11,7 +11,7 @@ crate-type = ["cdylib", "staticlib"] [dependencies] futures = "0.1.6" -jni = { version = "0.10.1", optional = true } +jni = { version = "0.11", optional = true } panic_hook = { path = "../util/panic-hook" } parity-ethereum = { path = "../", default-features = false } tokio = "0.1.11" diff --git a/parity-clib/Parity.java b/parity-clib/Parity.java index 37a6722b78..3885cfb1e6 100644 --- a/parity-clib/Parity.java +++ b/parity-clib/Parity.java @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Parity. // Parity is free software: you can redistribute it and/or modify @@ -28,9 +28,9 @@ public class Parity { * * @param options The CLI options to start Parity with */ - public Parity(String[] options) { + public Parity(String[] options, String loggerMode, String loggerFile) { long config = configFromCli(options); - inner = build(config); + inner = build(config, loggerMode, loggerFile); } /** Performs an asynchronous RPC query by spawning a background thread that is executed until @@ -76,7 +76,7 @@ public void unsubscribeWebSocket(long session) { } private static native long configFromCli(String[] cliOptions); - private static native long build(long config); + private static native long build(long config, String loggerMode, String loggerFile); private static native void destroy(long inner); private static native void rpcQueryNative(long inner, String rpc, long timeoutMillis, Object callback); private static native long subscribeWebSocketNative(long inner, String rpc, Object callback); diff --git a/parity-clib/examples/cpp/CMakeLists.txt b/parity-clib/examples/cpp/CMakeLists.txt index d3aaf457b3..8cc6aef8f5 100644 --- a/parity-clib/examples/cpp/CMakeLists.txt +++ b/parity-clib/examples/cpp/CMakeLists.txt @@ -15,4 +15,4 @@ ExternalProject_Add( LOG_BUILD ON) add_dependencies(parity-example libparity) -target_link_libraries(parity-example "${CMAKE_SOURCE_DIR}/../../../target/debug/libparity.so") +target_link_libraries(parity-example "${CMAKE_SOURCE_DIR}/../../../target/debug/${CMAKE_SHARED_LIBRARY_PREFIX}parity${CMAKE_SHARED_LIBRARY_SUFFIX}") diff --git a/parity-clib/examples/cpp/main.cpp b/parity-clib/examples/cpp/main.cpp index d4603ceb7a..43b31d793f 100644 --- a/parity-clib/examples/cpp/main.cpp +++ b/parity-clib/examples/cpp/main.cpp @@ -53,10 +53,8 @@ const std::vector ws_subscriptions { void callback(void* user_data, const char* response, size_t _len) { Callback* cb = static_cast(user_data); if (cb->type == CALLBACK_RPC) { - printf("rpc response: %s\r\n", response); cb->counter -= 1; } else if (cb->type == CALLBACK_WS) { - printf("websocket response: %s\r\n", response); std::regex is_subscription ("\\{\"jsonrpc\":\"2.0\",\"result\":\"0[xX][a-fA-F0-9]{16}\",\"id\":1\\}"); if (std::regex_match(response, is_subscription) == true) { cb->counter -= 1; @@ -153,7 +151,8 @@ void* parity_run(std::vector args) { ParityParams cfg = { .configuration = nullptr, .on_client_restart_cb = callback, - .on_client_restart_cb_custom = nullptr + .on_client_restart_cb_custom = nullptr, + .logger = nullptr }; std::vector str_lens; @@ -173,6 +172,10 @@ void* parity_run(std::vector args) { } } + // enable logging but only the `rpc module` and don't write it to a file + char log_mode [] = "rpc=trace"; + parity_set_logger(log_mode, strlen(log_mode), nullptr, 0, &cfg.logger); + void *parity = nullptr; if (parity_start(&cfg, &parity) != 0) { return nullptr; diff --git a/parity-clib/examples/java/Main.java b/parity-clib/examples/java/Main.java index 88189af1c5..c20b9e34d6 100644 --- a/parity-clib/examples/java/Main.java +++ b/parity-clib/examples/java/Main.java @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Parity. // Parity is free software: you can redistribute it and/or modify @@ -35,7 +35,9 @@ class Main { }; public static void runParity(String[] config) { - Parity parity = new Parity(config); + String loggerMode = "rpc=trace"; + String loggerFile = "foo.log"; + Parity parity = new Parity(config, loggerMode, loggerFile); Callback rpcCallback = new Callback(1); Callback webSocketCallback = new Callback(2); @@ -94,12 +96,6 @@ public Callback(int type) { } public void callback(Object response) { - response = (String) response; - if (callbackType == 1) { - System.out.println("rpc: " + response); - } else if (callbackType == 2) { - System.out.println("ws: " + response); - } counter.getAndIncrement(); } diff --git a/parity-clib/parity.h b/parity-clib/parity.h index 71d6ca775d..7bba08e433 100644 --- a/parity-clib/parity.h +++ b/parity-clib/parity.h @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Parity. // Parity is free software: you can redistribute it and/or modify @@ -35,6 +35,9 @@ struct ParityParams { /// Custom parameter passed to the `on_client_restart_cb` callback as first parameter. void *on_client_restart_cb_custom; + + /// Logger object which must be created by the `parity_config_logger` function + void *logger; }; #ifdef __cplusplus @@ -63,6 +66,33 @@ extern "C" { /// int parity_config_from_cli(char const* const* args, size_t const* arg_lens, size_t len, void** out); +/// Builds a new logger object which should be a member of the `ParityParams struct` +/// +/// - log_mode : String representing the log mode according to `Rust LOG` or nullptr to disable logging. +/// See module documentation for `ethcore-logger` for more info. +/// - log_mode_len : Length of the log_mode or zero to disable logging +/// - log_file : String respresenting the file name to write to log to or nullptr to disable logging to a file +/// - log_mode_len : Length of the log_file or zero to disable logging to a file +/// - logger : Pointer to point to the created `Logger` object + +/// **Important**: This function must only be called exactly once otherwise it will panic. If you want to disable a +/// logging mode or logging to a file make sure that you pass the `length` as zero +/// +/// # Example +/// +/// ```no_run +/// void* cfg; +/// const char *args[] = {"--light", "--can-restart"}; +/// size_t str_lens[] = {7, 13}; +/// if (parity_config_from_cli(args, str_lens, 2, &cfg) != 0) { +/// return 1; +/// } +/// char[] logger_mode = "rpc=trace"; +/// parity_set_logger(logger_mode, strlen(logger_mode), nullptr, 0, &cfg.logger); +/// ``` +/// +int parity_set_logger(const char* log_mode, size_t log_mode_len, const char* log_file, size_t log_file_len, void** logger); + /// Destroys a configuration object created earlier. /// /// **Important**: You probably don't need to call this function. Calling `parity_start` destroys diff --git a/parity-clib/src/java.rs b/parity-clib/src/java.rs index 88f5444ea8..98969b1d10 100644 --- a/parity-clib/src/java.rs +++ b/parity-clib/src/java.rs @@ -15,34 +15,28 @@ // along with Parity Ethereum. If not, see . use std::{mem, ptr}; +use std::ffi::c_void; use std::sync::Arc; -use std::time::Duration; -use std::thread; -use std::os::raw::c_void; -use {parity_config_from_cli, parity_destroy, parity_start, parity_unsubscribe_ws, ParityParams, error}; +use {Callback, parity_config_from_cli, parity_destroy, parity_rpc_worker, parity_start, parity_set_logger, + parity_unsubscribe_ws, parity_ws_worker, ParityParams}; -use futures::{Future, Stream}; -use futures::sync::mpsc; use jni::{JavaVM, JNIEnv}; use jni::objects::{JClass, JString, JObject, JValue, GlobalRef}; use jni::sys::{jlong, jobjectArray, va_list}; -use tokio_current_thread::CurrentThread; -use parity_ethereum::{RunningClient, PubSubSession}; +use parity_ethereum::RunningClient; type CheckedQuery<'a> = (&'a RunningClient, String, JavaVM, GlobalRef); // Creates a Java callback to a static method named `void callback(Object)` -struct Callback<'a> { +struct JavaCallback<'a> { jvm: JavaVM, callback: GlobalRef, method_name: &'a str, method_descriptor: &'a str, } -unsafe impl<'a> Send for Callback<'a> {} -unsafe impl<'a> Sync for Callback<'a> {} -impl<'a> Callback<'a> { +impl<'a> JavaCallback<'a> { fn new(jvm: JavaVM, callback: GlobalRef) -> Self { Self { jvm, @@ -51,7 +45,9 @@ impl<'a> Callback<'a> { method_descriptor: "(Ljava/lang/Object;)V", } } +} +impl<'a> Callback for JavaCallback<'a> { fn call(&self, msg: &str) { let env = self.jvm.attach_current_thread().expect("JavaVM should have an environment; qed"); let java_str = env.new_string(msg.to_string()).expect("Rust String is valid JString; qed"); @@ -63,13 +59,13 @@ impl<'a> Callback<'a> { #[no_mangle] pub unsafe extern "system" fn Java_io_parity_ethereum_Parity_configFromCli(env: JNIEnv, _: JClass, cli: jobjectArray) -> jlong { - let cli_len = env.get_array_length(cli).expect("invalid Java bindings"); + let cli_len = env.get_array_length(cli).expect("invalid Java bindings") as usize; - let mut jni_strings = Vec::with_capacity(cli_len as usize); - let mut opts = Vec::with_capacity(cli_len as usize); - let mut opts_lens = Vec::with_capacity(cli_len as usize); + let mut jni_strings = Vec::with_capacity(cli_len); + let mut opts = Vec::with_capacity(cli_len); + let mut opts_lens = Vec::with_capacity(cli_len); - for n in 0..cli_len { + for n in 0..cli_len as i32 { let elem = env.get_object_array_element(cli, n).expect("invalid Java bindings"); let elem_str: JString = elem.into(); match env.get_string(elem_str) { @@ -77,7 +73,7 @@ pub unsafe extern "system" fn Java_io_parity_ethereum_Parity_configFromCli(env: opts.push(s.as_ptr()); opts_lens.push(s.to_bytes().len()); jni_strings.push(s); - }, + } Err(err) => { let _ = env.throw_new("java/lang/Exception", err.to_string()); return 0 @@ -86,7 +82,7 @@ pub unsafe extern "system" fn Java_io_parity_ethereum_Parity_configFromCli(env: } let mut out = ptr::null_mut(); - match parity_config_from_cli(opts.as_ptr(), opts_lens.as_ptr(), cli_len as usize, &mut out) { + match parity_config_from_cli(opts.as_ptr(), opts_lens.as_ptr(), cli_len, &mut out) { 0 => out as jlong, _ => { let _ = env.throw_new("java/lang/Exception", "failed to create config object"); @@ -96,19 +92,31 @@ pub unsafe extern "system" fn Java_io_parity_ethereum_Parity_configFromCli(env: } #[no_mangle] -pub unsafe extern "system" fn Java_io_parity_ethereum_Parity_build(env: JNIEnv, _: JClass, config: va_list) -> jlong { - let params = ParityParams { +pub unsafe extern "system" fn Java_io_parity_ethereum_Parity_build( + env: JNIEnv, + _: JClass, + config: va_list, + logger_mode: JString, + logger_file: JString +) -> jlong { + let mut params = ParityParams { configuration: config, .. mem::zeroed() }; + let logger_mode: String = env.get_string(logger_mode).expect("valid JString; qed").into(); + let logger_file: String = env.get_string(logger_file).expect("valid JString; qed").into(); + + parity_set_logger(logger_mode.as_ptr(), logger_mode.as_bytes().len(), logger_file.as_ptr(), + logger_file.as_bytes().len(), &mut params.logger); + let mut out = ptr::null_mut(); match parity_start(¶ms, &mut out) { 0 => out as jlong, _ => { let _ = env.throw_new("java/lang/Exception", "failed to start Parity"); 0 - }, + } } } @@ -117,7 +125,7 @@ pub unsafe extern "system" fn Java_io_parity_ethereum_Parity_destroy(_env: JNIEn parity_destroy(parity); } -unsafe fn async_checker<'a>(client: va_list, rpc: JString, callback: JObject, env: &JNIEnv<'a>) +unsafe fn java_query_checker<'a>(client: va_list, rpc: JString, callback: JObject, env: &JNIEnv<'a>) -> Result, String> { let query: String = env.get_string(rpc) .map(Into::into) @@ -139,26 +147,10 @@ pub unsafe extern "system" fn Java_io_parity_ethereum_Parity_rpcQueryNative( callback: JObject, ) { - let _ = async_checker(parity, rpc, callback, &env) + let _ = java_query_checker(parity, rpc, callback, &env) .map(|(client, query, jvm, global_ref)| { - let callback = Arc::new(Callback::new(jvm, global_ref)); - let cb = callback.clone(); - let future = client.rpc_query(&query, None).map(move |response| { - let response = response.unwrap_or_else(|| error::EMPTY.to_string()); - callback.call(&response); - }); - - let _handle = thread::Builder::new() - .name("rpc_query".to_string()) - .spawn(move || { - let mut current_thread = CurrentThread::new(); - current_thread.spawn(future); - let _ = current_thread.run_timeout(Duration::from_millis(timeout_ms as u64)) - .map_err(|_e| { - cb.call(error::TIMEOUT); - }); - }) - .expect("rpc-query thread shouldn't fail; qed"); + let callback = Arc::new(JavaCallback::new(jvm, global_ref)); + parity_rpc_worker(client, &query, callback, timeout_ms as u64); }) .map_err(|e| { let _ = env.throw_new("java/lang/Exception", e); @@ -174,43 +166,10 @@ pub unsafe extern "system" fn Java_io_parity_ethereum_Parity_subscribeWebSocketN callback: JObject, ) -> va_list { - async_checker(parity, rpc, callback, &env) + java_query_checker(parity, rpc, callback, &env) .map(move |(client, query, jvm, global_ref)| { - let callback = Arc::new(Callback::new(jvm, global_ref)); - let (tx, mut rx) = mpsc::channel(1); - let session = Arc::new(PubSubSession::new(tx)); - let weak_session = Arc::downgrade(&session); - let query_future = client.rpc_query(&query, Some(session.clone()));; - - let _handle = thread::Builder::new() - .name("ws-subscriber".into()) - .spawn(move || { - // Wait for subscription ID - // Note this may block forever and can't be destroyed using the session object - // However, this will likely timeout or be catched the RPC layer - if let Ok(Some(response)) = query_future.wait() { - callback.call(&response); - } else { - callback.call(error::SUBSCRIBE); - return; - }; - - loop { - for response in rx.by_ref().wait() { - if let Ok(r) = response { - callback.call(&r); - } - } - - let rc = weak_session.upgrade().map_or(0,|session| Arc::strong_count(&session)); - // No subscription left, then terminate - if rc <= 1 { - break; - } - } - }) - .expect("rpc-subscriber thread shouldn't fail; qed"); - Arc::into_raw(session) as va_list + let callback = Arc::new(JavaCallback::new(jvm, global_ref)); + parity_ws_worker(client, &query, callback) as va_list }) .unwrap_or_else(|e| { let _ = env.throw_new("java/lang/Exception", e); diff --git a/parity-clib/src/lib.rs b/parity-clib/src/lib.rs index 3813037270..bbb60ec2d2 100644 --- a/parity-clib/src/lib.rs +++ b/parity-clib/src/lib.rs @@ -40,7 +40,7 @@ use futures::sync::mpsc; use parity_ethereum::{PubSubSession, RunningClient}; use tokio_current_thread::CurrentThread; -type Callback = Option; +type CCallback = Option; type CheckedQuery<'a> = (&'a RunningClient, &'static str); pub mod error { @@ -52,8 +52,31 @@ pub mod error { #[repr(C)] pub struct ParityParams { pub configuration: *mut c_void, - pub on_client_restart_cb: Callback, + pub on_client_restart_cb: CCallback, pub on_client_restart_cb_custom: *mut c_void, + pub logger: *mut c_void +} + +/// Trait representing a callback that passes a string +pub(crate) trait Callback: Send + Sync { + fn call(&self, msg: &str); +} + +// Internal structure for handling callbacks that get passed a string. +struct CallbackStr { + user_data: *mut c_void, + function: CCallback, +} + +unsafe impl Send for CallbackStr {} +unsafe impl Sync for CallbackStr {} +impl Callback for CallbackStr { + fn call(&self, msg: &str) { + if let Some(ref cb) = self.function { + let cstr = CString::new(msg).expect("valid string with no nul bytes in the middle; qed").into_raw(); + cb(self.user_data, cstr, msg.len()) + } + } } #[no_mangle] @@ -111,7 +134,7 @@ pub unsafe extern fn parity_start(cfg: *const ParityParams, output: *mut *mut c_ panic::catch_unwind(|| { *output = ptr::null_mut(); let cfg: &ParityParams = &*cfg; - + let logger = Arc::from_raw(cfg.logger as *mut parity_ethereum::RotatingLogger); let config = Box::from_raw(cfg.configuration as *mut parity_ethereum::Configuration); let on_client_restart_cb = { @@ -119,10 +142,10 @@ pub unsafe extern fn parity_start(cfg: *const ParityParams, output: *mut *mut c_ user_data: cfg.on_client_restart_cb_custom, function: cfg.on_client_restart_cb, }; - move |new_chain: String| { cb.call(new_chain.as_bytes()); } + move |new_chain: String| { cb.call(&new_chain); } }; - let action = match parity_ethereum::start(*config, on_client_restart_cb, || {}) { + let action = match parity_ethereum::start(*config, logger, on_client_restart_cb, || {}) { Ok(action) => action, Err(_) => return 1, }; @@ -131,7 +154,7 @@ pub unsafe extern fn parity_start(cfg: *const ParityParams, output: *mut *mut c_ parity_ethereum::ExecutionAction::Instant(Some(s)) => { println!("{}", s); 0 }, parity_ethereum::ExecutionAction::Instant(None) => 0, parity_ethereum::ExecutionAction::Running(client) => { - *output = Box::into_raw(Box::::new(client)) as *mut c_void; + *output = Box::into_raw(Box::new(client)) as *mut c_void; 0 } } @@ -146,47 +169,19 @@ pub unsafe extern fn parity_destroy(client: *mut c_void) { }); } -unsafe fn parity_rpc_query_checker<'a>(client: *const c_void, query: *const c_char, len: usize) - -> Option> -{ - let query_str = { - let string = slice::from_raw_parts(query as *const u8, len); - str::from_utf8(string).ok()? - }; - let client: &RunningClient = &*(client as *const RunningClient); - Some((client, query_str)) -} - #[no_mangle] pub unsafe extern fn parity_rpc( client: *const c_void, query: *const c_char, len: usize, timeout_ms: usize, - callback: Callback, + callback: CCallback, user_data: *mut c_void, ) -> c_int { panic::catch_unwind(|| { if let Some((client, query)) = parity_rpc_query_checker(client, query, len) { - let client = client as &RunningClient; let callback = Arc::new(CallbackStr {user_data, function: callback} ); - let cb = callback.clone(); - let query = client.rpc_query(query, None).map(move |response| { - let response = response.unwrap_or_else(|| error::EMPTY.to_string()); - callback.call(response.as_bytes()); - }); - - let _handle = thread::Builder::new() - .name("rpc_query".to_string()) - .spawn(move || { - let mut current_thread = CurrentThread::new(); - current_thread.spawn(query); - let _ = current_thread.run_timeout(Duration::from_millis(timeout_ms as u64)) - .map_err(|_e| { - cb.call(error::TIMEOUT.as_bytes()); - }); - }) - .expect("rpc-query thread shouldn't fail; qed"); + parity_rpc_worker(client, query, callback, timeout_ms as u64); 0 } else { 1 @@ -199,47 +194,13 @@ pub unsafe extern fn parity_subscribe_ws( client: *const c_void, query: *const c_char, len: usize, - callback: Callback, + callback: CCallback, user_data: *mut c_void, ) -> *const c_void { - panic::catch_unwind(|| { if let Some((client, query)) = parity_rpc_query_checker(client, query, len) { - let (tx, mut rx) = mpsc::channel(1); - let session = Arc::new(PubSubSession::new(tx)); - let query_future = client.rpc_query(query, Some(session.clone())); - let weak_session = Arc::downgrade(&session); - let cb = CallbackStr { user_data, function: callback}; - - let _handle = thread::Builder::new() - .name("ws-subscriber".into()) - .spawn(move || { - // Wait for subscription ID - // Note this may block forever and be can't destroyed using the session object - // However, this will likely timeout or be catched the RPC layer - if let Ok(Some(response)) = query_future.wait() { - cb.call(response.as_bytes()); - } else { - cb.call(error::SUBSCRIBE.as_bytes()); - return; - } - - loop { - for response in rx.by_ref().wait() { - if let Ok(r) = response { - cb.call(r.as_bytes()); - } - } - - let rc = weak_session.upgrade().map_or(0,|session| Arc::strong_count(&session)); - // No subscription left, then terminate - if rc <= 1 { - break; - } - } - }) - .expect("rpc-subscriber thread shouldn't fail; qed"); - Arc::into_raw(session) as *const c_void + let callback = Arc::new(CallbackStr { user_data, function: callback}); + parity_ws_worker(client, query, callback) } else { ptr::null() } @@ -255,26 +216,89 @@ pub unsafe extern fn parity_unsubscribe_ws(session: *const c_void) { } #[no_mangle] -pub unsafe extern fn parity_set_panic_hook(callback: Callback, param: *mut c_void) { +pub extern fn parity_set_panic_hook(callback: CCallback, param: *mut c_void) { let cb = CallbackStr {user_data: param, function: callback}; panic_hook::set_with(move |panic_msg| { - cb.call(panic_msg.as_bytes()); + cb.call(panic_msg); }); } -// Internal structure for handling callbacks that get passed a string. -struct CallbackStr { - user_data: *mut c_void, - function: Callback, +#[no_mangle] +pub unsafe extern fn parity_set_logger( + logger_mode: *const u8, + logger_mode_len: usize, + log_file: *const u8, + log_file_len: usize, + logger: *mut *mut c_void) { + + let mut logger_cfg = parity_ethereum::LoggerConfig::default(); + logger_cfg.mode = String::from_utf8(slice::from_raw_parts(logger_mode, logger_mode_len).to_owned()).ok(); + + // Make sure an empty string is not constructed as file name (to prevent panic) + if log_file_len != 0 && !log_file.is_null() { + logger_cfg.file = String::from_utf8(slice::from_raw_parts(log_file, log_file_len).to_owned()).ok(); + } + + *logger = Arc::into_raw(parity_ethereum::setup_log(&logger_cfg).expect("Logger initialized only once; qed")) as *mut _; } -unsafe impl Send for CallbackStr {} -unsafe impl Sync for CallbackStr {} -impl CallbackStr { - fn call(&self, msg: &[u8]) { - if let Some(ref cb) = self.function { - let cstr = CString::new(msg).expect("valid string with no null bytes in the middle; qed").into_raw(); - cb(self.user_data, cstr, msg.len()) - } - } +// WebSocket event loop +fn parity_ws_worker(client: &RunningClient, query: &str, callback: Arc) -> *const c_void { + let (tx, mut rx) = mpsc::channel(1); + let session = Arc::new(PubSubSession::new(tx)); + let query_future = client.rpc_query(query, Some(session.clone())); + let weak_session = Arc::downgrade(&session); + let _handle = thread::Builder::new() + .name("ws-subscriber".into()) + .spawn(move || { + // Wait for subscription ID + // Note this may block forever and be can't destroyed using the session object + // However, this will likely timeout or be catched the RPC layer + if let Ok(Some(response)) = query_future.wait() { + callback.call(&response); + } else { + callback.call(error::SUBSCRIBE); + return; + } + + while weak_session.upgrade().map_or(0, |session| Arc::strong_count(&session)) > 1 { + for response in rx.by_ref().wait() { + if let Ok(r) = response { + callback.call(&r); + } + } + } + }) + .expect("rpc-subscriber thread shouldn't fail; qed"); + Arc::into_raw(session) as *const c_void +} + +// RPC event loop that runs for at most `timeout_ms` +fn parity_rpc_worker(client: &RunningClient, query: &str, callback: Arc, timeout_ms: u64) { + let cb = callback.clone(); + let query = client.rpc_query(query, None).map(move |response| { + let response = response.unwrap_or_else(|| error::EMPTY.to_string()); + callback.call(&response); + }); + + let _handle = thread::Builder::new() + .name("rpc_query".to_string()) + .spawn(move || { + let mut current_thread = CurrentThread::new(); + current_thread.spawn(query); + let _ = current_thread + .run_timeout(Duration::from_millis(timeout_ms)) + .map_err(|_e| { + cb.call(error::TIMEOUT); + }); + }) + .expect("rpc-query thread shouldn't fail; qed"); +} + +unsafe fn parity_rpc_query_checker<'a>(client: *const c_void, query: *const c_char, len: usize) + -> Option> +{ + let query_str = str::from_utf8(slice::from_raw_parts(query as *const u8, len)).ok()?; + let client: &RunningClient = &*(client as *const RunningClient); + Some((client, query_str)) } diff --git a/parity/account.rs b/parity/account.rs index 79681fda7e..118c06fdda 100644 --- a/parity/account.rs +++ b/parity/account.rs @@ -14,12 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use std::path::PathBuf; -use ethstore::{EthStore, SecretStore, import_account, import_accounts, read_geth_accounts}; -use ethstore::accounts_dir::RootDiskDirectory; -use ethstore::SecretVaultRef; -use ethcore::account_provider::{AccountProvider, AccountProviderSettings}; -use helpers::{password_prompt, password_from_file}; +use std::num::NonZeroU32; use params::SpecType; #[derive(Debug, PartialEq)] @@ -38,7 +33,7 @@ pub struct ListAccounts { #[derive(Debug, PartialEq)] pub struct NewAccount { - pub iterations: u32, + pub iterations: NonZeroU32, pub path: String, pub spec: SpecType, pub password_file: Option, @@ -61,83 +56,102 @@ pub struct ImportFromGethAccounts { pub spec: SpecType, } -pub fn execute(cmd: AccountCmd) -> Result { - match cmd { - AccountCmd::New(new_cmd) => new(new_cmd), - AccountCmd::List(list_cmd) => list(list_cmd), - AccountCmd::Import(import_cmd) => import(import_cmd), - AccountCmd::ImportFromGeth(import_geth_cmd) => import_geth(import_geth_cmd) - } -} -fn keys_dir(path: String, spec: SpecType) -> Result { - let spec = spec.spec(&::std::env::temp_dir())?; - let mut path = PathBuf::from(&path); - path.push(spec.data_dir); - RootDiskDirectory::create(path).map_err(|e| format!("Could not open keys directory: {}", e)) +#[cfg(not(feature = "accounts"))] +pub fn execute(_cmd: AccountCmd) -> Result { + Err("Account management is deprecated. Please see #9997 for alternatives:\nhttps://github.com/paritytech/parity-ethereum/issues/9997".into()) } -fn secret_store(dir: Box, iterations: Option) -> Result { - match iterations { - Some(i) => EthStore::open_with_iterations(dir, i), - _ => EthStore::open(dir) - }.map_err(|e| format!("Could not open keys store: {}", e)) -} +#[cfg(feature = "accounts")] +mod command { + use super::*; + use std::path::PathBuf; + use accounts::{AccountProvider, AccountProviderSettings}; + use ethstore::{EthStore, SecretStore, SecretVaultRef, import_account, import_accounts, read_geth_accounts}; + use ethstore::accounts_dir::RootDiskDirectory; + use helpers::{password_prompt, password_from_file}; + + pub fn execute(cmd: AccountCmd) -> Result { + match cmd { + AccountCmd::New(new_cmd) => new(new_cmd), + AccountCmd::List(list_cmd) => list(list_cmd), + AccountCmd::Import(import_cmd) => import(import_cmd), + AccountCmd::ImportFromGeth(import_geth_cmd) => import_geth(import_geth_cmd) + } + } -fn new(n: NewAccount) -> Result { - let password = match n.password_file { - Some(file) => password_from_file(file)?, - None => password_prompt()?, - }; - - let dir = Box::new(keys_dir(n.path, n.spec)?); - let secret_store = Box::new(secret_store(dir, Some(n.iterations))?); - let acc_provider = AccountProvider::new(secret_store, AccountProviderSettings::default()); - let new_account = acc_provider.new_account(&password).map_err(|e| format!("Could not create new account: {}", e))?; - Ok(format!("0x{:x}", new_account)) -} + fn keys_dir(path: String, spec: SpecType) -> Result { + let spec = spec.spec(&::std::env::temp_dir())?; + let mut path = PathBuf::from(&path); + path.push(spec.data_dir); + RootDiskDirectory::create(path).map_err(|e| format!("Could not open keys directory: {}", e)) + } -fn list(list_cmd: ListAccounts) -> Result { - let dir = Box::new(keys_dir(list_cmd.path, list_cmd.spec)?); - let secret_store = Box::new(secret_store(dir, None)?); - let acc_provider = AccountProvider::new(secret_store, AccountProviderSettings::default()); - let accounts = acc_provider.accounts().map_err(|e| format!("{}", e))?; - let result = accounts.into_iter() - .map(|a| format!("0x{:x}", a)) - .collect::>() - .join("\n"); - - Ok(result) -} + fn secret_store(dir: Box, iterations: Option) -> Result { + match iterations { + Some(i) => EthStore::open_with_iterations(dir, i), + _ => EthStore::open(dir) + }.map_err(|e| format!("Could not open keys store: {}", e)) + } -fn import(i: ImportAccounts) -> Result { - let to = keys_dir(i.to, i.spec)?; - let mut imported = 0; - - for path in &i.from { - let path = PathBuf::from(path); - if path.is_dir() { - let from = RootDiskDirectory::at(&path); - imported += import_accounts(&from, &to).map_err(|e| format!("Importing accounts from {:?} failed: {}", path, e))?.len(); - } else if path.is_file() { - import_account(&path, &to).map_err(|e| format!("Importing account from {:?} failed: {}", path, e))?; - imported += 1; - } + fn new(n: NewAccount) -> Result { + let password = match n.password_file { + Some(file) => password_from_file(file)?, + None => password_prompt()?, + }; + + let dir = Box::new(keys_dir(n.path, n.spec)?); + let secret_store = Box::new(secret_store(dir, Some(n.iterations))?); + let acc_provider = AccountProvider::new(secret_store, AccountProviderSettings::default()); + let new_account = acc_provider.new_account(&password).map_err(|e| format!("Could not create new account: {}", e))?; + Ok(format!("0x{:x}", new_account)) } - Ok(format!("{} account(s) imported", imported)) -} + fn list(list_cmd: ListAccounts) -> Result { + let dir = Box::new(keys_dir(list_cmd.path, list_cmd.spec)?); + let secret_store = Box::new(secret_store(dir, None)?); + let acc_provider = AccountProvider::new(secret_store, AccountProviderSettings::default()); + let accounts = acc_provider.accounts().map_err(|e| format!("{}", e))?; + let result = accounts.into_iter() + .map(|a| format!("0x{:x}", a)) + .collect::>() + .join("\n"); + + Ok(result) + } + + fn import(i: ImportAccounts) -> Result { + let to = keys_dir(i.to, i.spec)?; + let mut imported = 0; + + for path in &i.from { + let path = PathBuf::from(path); + if path.is_dir() { + let from = RootDiskDirectory::at(&path); + imported += import_accounts(&from, &to).map_err(|e| format!("Importing accounts from {:?} failed: {}", path, e))?.len(); + } else if path.is_file() { + import_account(&path, &to).map_err(|e| format!("Importing account from {:?} failed: {}", path, e))?; + imported += 1; + } + } -fn import_geth(i: ImportFromGethAccounts) -> Result { - use std::io::ErrorKind; - use ethstore::Error; - - let dir = Box::new(keys_dir(i.to, i.spec)?); - let secret_store = Box::new(secret_store(dir, None)?); - let geth_accounts = read_geth_accounts(i.testnet); - match secret_store.import_geth_accounts(SecretVaultRef::Root, geth_accounts, i.testnet) { - Ok(v) => Ok(format!("Successfully imported {} account(s) from geth.", v.len())), - Err(Error::Io(ref io_err)) if io_err.kind() == ErrorKind::NotFound => Err("Failed to find geth keys folder.".into()), - Err(err) => Err(format!("Import geth accounts failed. {}", err)) + Ok(format!("{} account(s) imported", imported)) + } + + fn import_geth(i: ImportFromGethAccounts) -> Result { + use std::io::ErrorKind; + use ethstore::Error; + + let dir = Box::new(keys_dir(i.to, i.spec)?); + let secret_store = Box::new(secret_store(dir, None)?); + let geth_accounts = read_geth_accounts(i.testnet); + match secret_store.import_geth_accounts(SecretVaultRef::Root, geth_accounts, i.testnet) { + Ok(v) => Ok(format!("Successfully imported {} account(s) from geth.", v.len())), + Err(Error::Io(ref io_err)) if io_err.kind() == ErrorKind::NotFound => Err("Failed to find geth keys folder.".into()), + Err(err) => Err(format!("Import geth accounts failed. {}", err)) + } } } + +#[cfg(feature = "accounts")] +pub use self::command::execute; diff --git a/parity/account_utils.rs b/parity/account_utils.rs new file mode 100644 index 0000000000..6c11ae23b3 --- /dev/null +++ b/parity/account_utils.rs @@ -0,0 +1,244 @@ +// 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::sync::Arc; + +use dir::Directories; +use ethereum_types::Address; +use ethkey::Password; + +use params::{SpecType, AccountsConfig}; + +#[cfg(not(feature = "accounts"))] +mod accounts { + use super::*; + + /// Dummy AccountProvider + pub struct AccountProvider; + + impl ::ethcore::miner::LocalAccounts for AccountProvider { + fn is_local(&self, _address: &Address) -> bool { + false + } + } + + pub fn prepare_account_provider(_spec: &SpecType, _dirs: &Directories, _data_dir: &str, _cfg: AccountsConfig, _passwords: &[Password]) -> Result { + warn!("Note: Your instance of Parity Ethereum is running without account support. Some CLI options are ignored."); + Ok(AccountProvider) + } + + pub fn miner_local_accounts(_: Arc) -> AccountProvider { + AccountProvider + } + + pub fn miner_author(_spec: &SpecType, _dirs: &Directories, _account_provider: &Arc, _engine_signer: Address, _passwords: &[Password]) -> Result, String> { + Ok(None) + } + + pub fn private_tx_signer(_account_provider: Arc, _passwords: &[Password]) -> Result, String> { + Ok(Arc::new(::ethcore_private_tx::DummySigner)) + } + + pub fn accounts_list(_account_provider: Arc) -> Arc Vec

+ Send + Sync> { + Arc::new(|| vec![]) + } +} + +#[cfg(feature = "accounts")] +mod accounts { + use super::*; + use upgrade::upgrade_key_location; + + pub use accounts::AccountProvider; + + /// Pops along with error messages when a password is missing or invalid. + const VERIFY_PASSWORD_HINT: &str = "Make sure valid password is present in files passed using `--password` or in the configuration file."; + + /// Initialize account provider + pub fn prepare_account_provider(spec: &SpecType, dirs: &Directories, data_dir: &str, cfg: AccountsConfig, passwords: &[Password]) -> Result { + use ethstore::EthStore; + use ethstore::accounts_dir::RootDiskDirectory; + use accounts::AccountProviderSettings; + + let path = dirs.keys_path(data_dir); + upgrade_key_location(&dirs.legacy_keys_path(cfg.testnet), &path); + let dir = Box::new(RootDiskDirectory::create(&path).map_err(|e| format!("Could not open keys directory: {}", e))?); + let account_settings = AccountProviderSettings { + enable_hardware_wallets: cfg.enable_hardware_wallets, + hardware_wallet_classic_key: spec == &SpecType::Classic, + unlock_keep_secret: cfg.enable_fast_unlock, + blacklisted_accounts: match *spec { + SpecType::Morden | SpecType::Ropsten | SpecType::Kovan | SpecType::Sokol | SpecType::Dev => vec![], + _ => vec![ + "00a329c0648769a73afac7f9381e08fb43dbea72".into() + ], + }, + }; + + let ethstore = EthStore::open_with_iterations(dir, cfg.iterations).map_err(|e| format!("Could not open keys directory: {}", e))?; + if cfg.refresh_time > 0 { + ethstore.set_refresh_time(::std::time::Duration::from_secs(cfg.refresh_time)); + } + let account_provider = AccountProvider::new( + Box::new(ethstore), + account_settings, + ); + + // Add development account if running dev chain: + if let SpecType::Dev = *spec { + insert_dev_account(&account_provider); + } + + for a in cfg.unlocked_accounts { + // Check if the account exists + if !account_provider.has_account(a) { + return Err(format!("Account {} not found for the current chain. {}", a, build_create_account_hint(spec, &dirs.keys))); + } + + // Check if any passwords have been read from the password file(s) + if passwords.is_empty() { + return Err(format!("No password found to unlock account {}. {}", a, VERIFY_PASSWORD_HINT)); + } + + if !passwords.iter().any(|p| account_provider.unlock_account_permanently(a, (*p).clone()).is_ok()) { + return Err(format!("No valid password to unlock account {}. {}", a, VERIFY_PASSWORD_HINT)); + } + } + + Ok(account_provider) + } + + pub struct LocalAccounts(Arc); + impl ::ethcore::miner::LocalAccounts for LocalAccounts { + fn is_local(&self, address: &Address) -> bool { + self.0.has_account(*address) + } + } + + pub fn miner_local_accounts(account_provider: Arc) -> LocalAccounts { + LocalAccounts(account_provider) + } + + pub fn miner_author(spec: &SpecType, dirs: &Directories, account_provider: &Arc, engine_signer: Address, passwords: &[Password]) -> Result, String> { + use ethcore::engines::EngineSigner; + + // Check if engine signer exists + if !account_provider.has_account(engine_signer) { + return Err(format!("Consensus signer account not found for the current chain. {}", build_create_account_hint(spec, &dirs.keys))); + } + + // Check if any passwords have been read from the password file(s) + if passwords.is_empty() { + return Err(format!("No password found for the consensus signer {}. {}", engine_signer, VERIFY_PASSWORD_HINT)); + } + + let mut author = None; + for password in passwords { + let signer = parity_rpc::signer::EngineSigner::new( + account_provider.clone(), + engine_signer, + password.clone(), + ); + if signer.sign(Default::default()).is_ok() { + author = Some(::ethcore::miner::Author::Sealer(Box::new(signer))); + } + } + if author.is_none() { + return Err(format!("No valid password for the consensus signer {}. {}", engine_signer, VERIFY_PASSWORD_HINT)); + } + + Ok(author) + } + + + mod private_tx { + use super::*; + use ethkey::{Signature, Message}; + use ethcore_private_tx::{Error}; + + pub struct AccountSigner { + pub accounts: Arc, + pub passwords: Vec, + } + + impl ::ethcore_private_tx::Signer for AccountSigner { + fn decrypt(&self, account: Address, shared_mac: &[u8], payload: &[u8]) -> Result, Error> { + let password = self.find_account_password(&account); + Ok(self.accounts.decrypt(account, password, shared_mac, payload).map_err(|e| e.to_string())?) + } + + fn sign(&self, account: Address, hash: Message) -> Result { + let password = self.find_account_password(&account); + Ok(self.accounts.sign(account, password, hash).map_err(|e| e.to_string())?) + } + } + + impl AccountSigner { + /// Try to unlock account using stored password, return found password if any + fn find_account_password(&self, account: &Address) -> Option { + for password in &self.passwords { + if let Ok(true) = self.accounts.test_password(account, password) { + return Some(password.clone()); + } + } + None + } + } + } + + pub fn private_tx_signer(accounts: Arc, passwords: &[Password]) -> Result, String> { + Ok(Arc::new(self::private_tx::AccountSigner { + accounts, + passwords: passwords.to_vec(), + })) + } + + pub fn accounts_list(account_provider: Arc) -> Arc Vec
+ Send + Sync> { + Arc::new(move || account_provider.accounts().unwrap_or_default()) + } + + fn insert_dev_account(account_provider: &AccountProvider) { + let secret: ethkey::Secret = "4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7".into(); + let dev_account = ethkey::KeyPair::from_secret(secret.clone()).expect("Valid secret produces valid key;qed"); + if !account_provider.has_account(dev_account.address()) { + match account_provider.insert_account(secret, &Password::from(String::new())) { + Err(e) => warn!("Unable to add development account: {}", e), + Ok(address) => { + let _ = account_provider.set_account_name(address.clone(), "Development Account".into()); + let _ = account_provider.set_account_meta(address, ::serde_json::to_string(&(vec![ + ("description", "Never use this account outside of development chain!"), + ("passwordHint","Password is empty string"), + ].into_iter().collect::<::std::collections::HashMap<_,_>>())).expect("Serialization of hashmap does not fail.")); + }, + } + } + } + + // Construct an error `String` with an adaptive hint on how to create an account. + fn build_create_account_hint(spec: &SpecType, keys: &str) -> String { + format!("You can create an account via RPC, UI or `parity account new --chain {} --keys-path {}`.", spec, keys) + } +} + +pub use self::accounts::{ + AccountProvider, + prepare_account_provider, + miner_local_accounts, + miner_author, + private_tx_signer, + accounts_list, +}; + diff --git a/parity/blockchain.rs b/parity/blockchain.rs index 959de3a30b..262b98ae2c 100644 --- a/parity/blockchain.rs +++ b/parity/blockchain.rs @@ -25,8 +25,9 @@ use hash::{keccak, KECCAK_NULL_RLP}; use ethereum_types::{U256, H256, Address}; use bytes::ToPretty; use rlp::PayloadInfo; -use ethcore::account_provider::AccountProvider; -use ethcore::client::{Mode, DatabaseCompactionProfile, VMType, Nonce, Balance, BlockChainClient, BlockId, BlockInfo, ImportBlock}; +use ethcore::client::{ + Mode, DatabaseCompactionProfile, VMType, Nonce, Balance, BlockChainClient, BlockId, BlockInfo, ImportBlock, BlockChainReset +}; use ethcore::error::{ImportErrorKind, ErrorKind as EthcoreErrorKind, Error as EthcoreError}; use ethcore::miner::Miner; use ethcore::verification::queue::VerifierSettings; @@ -40,6 +41,7 @@ use dir::Directories; use user_defaults::UserDefaults; use ethcore_private_tx; use db; +use ansi_term::Colour; #[derive(Debug, PartialEq)] pub enum DataFormat { @@ -71,6 +73,21 @@ pub enum BlockchainCmd { Import(ImportBlockchain), Export(ExportBlockchain), ExportState(ExportState), + Reset(ResetBlockchain) +} + +#[derive(Debug, PartialEq)] +pub struct ResetBlockchain { + pub dirs: Directories, + pub spec: SpecType, + pub pruning: Pruning, + pub pruning_history: u64, + pub pruning_memory: usize, + pub tracing: Switch, + pub fat_db: Switch, + pub compaction: DatabaseCompactionProfile, + pub cache_config: CacheConfig, + pub num: u32, } #[derive(Debug, PartialEq)] @@ -153,6 +170,7 @@ pub fn execute(cmd: BlockchainCmd) -> Result<(), String> { } BlockchainCmd::Export(export_cmd) => execute_export(export_cmd), BlockchainCmd::ExportState(export_cmd) => execute_export_state(export_cmd), + BlockchainCmd::Reset(reset_cmd) => execute_reset(reset_cmd), } } @@ -377,9 +395,10 @@ fn execute_import(cmd: ImportBlockchain) -> Result<(), String> { // TODO [ToDr] don't use test miner here // (actually don't require miner at all) Arc::new(Miner::new_for_tests(&spec, None)), - Arc::new(AccountProvider::transient_provider()), + Arc::new(ethcore_private_tx::DummySigner), Box::new(ethcore_private_tx::NoopEncryptor), Default::default(), + Default::default(), ).map_err(|e| format!("Client service error: {:?}", e))?; // free up the spec in memory. @@ -568,9 +587,10 @@ fn start_client( // It's fine to use test version here, // since we don't care about miner parameters at all Arc::new(Miner::new_for_tests(&spec, None)), - Arc::new(AccountProvider::transient_provider()), + Arc::new(ethcore_private_tx::DummySigner), Box::new(ethcore_private_tx::NoopEncryptor), Default::default(), + Default::default(), ).map_err(|e| format!("Client service error: {:?}", e))?; drop(spec); @@ -709,6 +729,28 @@ fn execute_export_state(cmd: ExportState) -> Result<(), String> { Ok(()) } +fn execute_reset(cmd: ResetBlockchain) -> Result<(), String> { + let service = start_client( + cmd.dirs, + cmd.spec, + cmd.pruning, + cmd.pruning_history, + cmd.pruning_memory, + cmd.tracing, + cmd.fat_db, + cmd.compaction, + cmd.cache_config, + false, + 0, + )?; + + let client = service.client(); + client.reset(cmd.num)?; + info!("{}", Colour::Green.bold().paint("Successfully reset db!")); + + Ok(()) +} + pub fn kill_db(cmd: KillBlockchain) -> Result<(), String> { let spec = cmd.spec.spec(&cmd.dirs.cache)?; let genesis_hash = spec.genesis_header().hash(); diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index 8a23d4a52a..b36ddb0ca9 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -18,6 +18,9 @@ mod usage; mod presets; +use std::collections::HashSet; +use super::helpers; + usage! { { // CLI subcommands @@ -217,6 +220,15 @@ usage! { CMD cmd_db_kill { "Clean the database of the given --chain (default: mainnet)", } + + CMD cmd_db_reset { + "Removes NUM latests blocks from the db", + + ARG arg_db_reset_num: (u32) = 10u32, + "", + "Number of blocks to revert", + } + } CMD cmd_export_hardcoded_sync @@ -288,7 +300,7 @@ usage! { ARG arg_chain: (String) = "foundation", or |c: &Config| c.parity.as_ref()?.chain.clone(), "--chain=[CHAIN]", - "Specify the blockchain type. CHAIN may be either a JSON chain specification file or ethereum, classic, poacore, tobalaba, expanse, musicoin, ellaism, easthub, social, mix, callisto, morden, ropsten, kovan, poasokol, testnet, or dev.", + "Specify the blockchain type. CHAIN may be either a JSON chain specification file or ethereum, classic, poacore, xdai, volta, ewc, expanse, musicoin, ellaism, mix, callisto, morden, ropsten, kovan, rinkeby, goerli, kotti, poasokol, testnet, or dev.", ARG arg_keys_path: (String) = "$BASE/keys", or |c: &Config| c.parity.as_ref()?.keys_path.clone(), "--keys-path=[PATH]", @@ -309,7 +321,7 @@ usage! { ["Convenience Options"] FLAG flag_unsafe_expose: (bool) = false, or |c: &Config| c.misc.as_ref()?.unsafe_expose, "--unsafe-expose", - "All servers will listen on external interfaces and will be remotely accessible. It's equivalent with setting the following: --[ws,jsonrpc,ui,ipfs-api,secretstore,stratum,dapps,secretstore-http]-interface=all --*-hosts=all This option is UNSAFE and should be used with great care!", + "All servers will listen on external interfaces and will be remotely accessible. It's equivalent with setting the following: --[ws,jsonrpc,ipfs-api,secretstore,stratum,dapps,secretstore-http]-interface=all --*-hosts=all This option is UNSAFE and should be used with great care!", ARG arg_config: (String) = "$BASE/config.toml", or |_| None, "-c, --config=[CONFIG]", @@ -765,6 +777,10 @@ usage! { "--tx-queue-per-sender=[LIMIT]", "Maximum number of transactions per sender in the queue. By default it's 1% of the entire queue, but not less than 16.", + ARG arg_tx_queue_locals: (Option) = None, or |c: &Config| helpers::join_set(c.mining.as_ref()?.tx_queue_locals.as_ref()), + "--tx-queue-locals=[ACCOUNTS]", + "Specify local accounts for which transactions are prioritized in the queue. ACCOUNTS is a comma-delimited list of addresses.", + ARG arg_tx_queue_strategy: (String) = "gas_price", or |c: &Config| c.mining.as_ref()?.tx_queue_strategy.clone(), "--tx-queue-strategy=[S]", "Prioritization strategy used to order transactions in the queue. S may be: gas_price - Prioritize txs with high gas price", @@ -915,7 +931,7 @@ usage! { "--whisper", "Enable the Whisper network.", - ARG arg_whisper_pool_size: (usize) = 10usize, or |c: &Config| c.whisper.as_ref()?.pool_size.clone(), + ARG arg_whisper_pool_size: (usize) = 10usize, or |c: &Config| c.whisper.as_ref()?.pool_size.clone(), "--whisper-pool-size=[MB]", "Target size of the whisper message pool in megabytes.", @@ -1359,6 +1375,7 @@ struct Mining { tx_queue_size: Option, tx_queue_per_sender: Option, tx_queue_mem_limit: Option, + tx_queue_locals: Option>, tx_queue_strategy: Option, tx_queue_ban_count: Option, tx_queue_ban_time: Option, @@ -1624,6 +1641,7 @@ mod tests { cmd_tools_hash: false, cmd_db: false, cmd_db_kill: false, + cmd_db_reset: false, cmd_export_hardcoded_sync: false, // Arguments @@ -1643,6 +1661,7 @@ mod tests { arg_dapp_path: None, arg_account_import_path: None, arg_wallet_import_path: None, + arg_db_reset_num: 10, // -- Operating Options arg_mode: "last".into(), @@ -1803,6 +1822,7 @@ mod tests { arg_tx_queue_size: 8192usize, arg_tx_queue_per_sender: None, arg_tx_queue_mem_limit: 4u32, + arg_tx_queue_locals: Some("0xdeadbeefcafe0000000000000000000000000000".into()), arg_tx_queue_strategy: "gas_factor".into(), arg_tx_queue_ban_count: Some(1u16), arg_tx_queue_ban_time: Some(180u16), @@ -2079,6 +2099,7 @@ mod tests { tx_queue_size: Some(8192), tx_queue_per_sender: None, tx_queue_mem_limit: None, + tx_queue_locals: None, tx_queue_strategy: None, tx_queue_ban_count: None, tx_queue_ban_time: None, diff --git a/parity/cli/tests/config.full.toml b/parity/cli/tests/config.full.toml index 99603954c8..34dd39058b 100644 --- a/parity/cli/tests/config.full.toml +++ b/parity/cli/tests/config.full.toml @@ -129,6 +129,7 @@ price_update_period = "hourly" gas_floor_target = "8000000" gas_cap = "10000000" tx_queue_size = 8192 +tx_queue_locals = ["0xdeadbeefcafe0000000000000000000000000000"] tx_queue_strategy = "gas_factor" tx_queue_ban_count = 1 tx_queue_ban_time = 180 #s diff --git a/parity/cli/usage.rs b/parity/cli/usage.rs index f48387b2a7..8b06f4f1f6 100644 --- a/parity/cli/usage.rs +++ b/parity/cli/usage.rs @@ -14,13 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -macro_rules! println_stderr( - ($($arg:tt)*) => { { - let r = writeln!(&mut ::std::io::stderr(), $($arg)*); - r.expect("failed printing to stderr"); - } } -); - macro_rules! return_if_parse_error { ($e:expr) => ( match $e { @@ -143,7 +136,7 @@ macro_rules! usage { ) => { use toml; use std::{fs, io, process, cmp}; - use std::io::{Read, Write}; + use std::io::Read; use parity_version::version; use clap::{Arg, App, SubCommand, AppSettings, ArgSettings, Error as ClapError, ErrorKind as ClapErrorKind}; use dir::helpers::replace_home; @@ -172,17 +165,17 @@ macro_rules! usage { match self { ArgsError::Clap(e) => e.exit(), ArgsError::Decode(e) => { - println_stderr!("You might have supplied invalid parameters in config file."); - println_stderr!("{}", e); + eprintln!("You might have supplied invalid parameters in config file."); + eprintln!("{}", e); process::exit(2) }, ArgsError::Config(path, e) => { - println_stderr!("There was an error reading your config file at: {}", path); - println_stderr!("{}", e); + eprintln!("There was an error reading your config file at: {}", path); + eprintln!("{}", e); process::exit(2) }, ArgsError::PeerConfiguration => { - println_stderr!("You have supplied `min_peers` > `max_peers`"); + eprintln!("You have supplied `min_peers` > `max_peers`"); process::exit(2) } } @@ -332,7 +325,7 @@ macro_rules! usage { let args = match (fs::File::open(&config_file), raw_args.arg_config.clone()) { // Load config file (Ok(mut file), _) => { - println_stderr!("Loading config file from {}", &config_file); + eprintln!("Loading config file from {}", &config_file); let mut config = String::new(); file.read_to_string(&mut config).map_err(|e| ArgsError::Config(config_file, e))?; Ok(raw_args.into_args(Self::parse_config(&config)?)) diff --git a/parity/cli/usage_header.txt b/parity/cli/usage_header.txt index 82a6d58b24..ec9f7a2216 100644 --- a/parity/cli/usage_header.txt +++ b/parity/cli/usage_header.txt @@ -1,3 +1,6 @@ Parity Ethereum Client. - By Wood/Paronyan/Kotewicz/Drwięga/Volf et al. - Copyright 2015-2018 Parity Technologies (UK) Ltd. + By Wood/Paronyan/Kotewicz/Drwięga/Volf/Greeff + Habermeier/Czaban/Gotchac/Redman/Nikolsky + Schoedon/Tang/Adolfsson/Silva/Palm/Hirsz et al. + Copyright 2015-2019 Parity Technologies (UK) Ltd. + License GPLv3+: GNU GPL version 3 or later . diff --git a/parity/cli/version.txt b/parity/cli/version.txt index 480fe5469c..26eae78ddf 100644 --- a/parity/cli/version.txt +++ b/parity/cli/version.txt @@ -1,9 +1,10 @@ -Parity Ethereum +Parity Ethereum Client. version {} -Copyright 2015-2018 Parity Technologies (UK) Ltd. +Copyright 2015-2019 Parity Technologies (UK) Ltd. License GPLv3+: GNU GPL version 3 or later . This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. -By Wood/Paronyan/Kotewicz/Drwięga/Volf - Habermeier/Czaban/Greeff/Gotchac/Redmann +By Wood/Paronyan/Kotewicz/Drwięga/Volf/Greeff + Habermeier/Czaban/Gotchac/Redman/Nikolsky + Schoedon/Tang/Adolfsson/Silva/Palm/Hirsz et al. diff --git a/parity/configuration.rs b/parity/configuration.rs index 5f7f001f3e..ab0c0f9490 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -16,9 +16,11 @@ use std::time::Duration; use std::io::Read; -use std::net::SocketAddr; +use std::net::{SocketAddr, ToSocketAddrs}; +use std::num::NonZeroU32; use std::path::PathBuf; -use std::collections::BTreeMap; +use std::collections::{HashSet, BTreeMap}; +use std::iter::FromIterator; use std::cmp; use cli::{Args, ArgsError}; use hash::keccak; @@ -27,7 +29,7 @@ use parity_version::{version_data, version}; use bytes::Bytes; use ansi_term::Colour; use sync::{NetworkConfiguration, validate_node_url, self}; -use ethstore::ethkey::{Secret, Public}; +use ethkey::{Secret, Public}; use ethcore::client::{VMType}; use ethcore::miner::{stratum, MinerOptions}; use ethcore::snapshot::SnapshotConfiguration; @@ -39,7 +41,7 @@ use rpc::{IpcConfiguration, HttpConfiguration, WsConfiguration}; use parity_rabbitmq::client::RabbitMqConfig; use parity_rpc::NetworkSettings; use cache::CacheConfig; -use helpers::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_price, geth_ipc_path, parity_ipc_path, to_bootnodes, to_addresses, to_address, to_queue_strategy, to_queue_penalization, passwords_from_files}; +use helpers::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_price, geth_ipc_path, parity_ipc_path, to_bootnodes, to_addresses, to_address, to_queue_strategy, to_queue_penalization}; use dir::helpers::{replace_home, replace_home_and_local}; use params::{ResealPolicy, AccountsConfig, GasPricerConfig, MinerExtras, SpecType}; use ethcore_logger::Config as LogConfig; @@ -49,7 +51,7 @@ use ethcore_private_tx::{ProviderConfig, EncryptorConfig}; use secretstore::{NodeSecretKey, Configuration as SecretStoreConfiguration, ContractAddress as SecretStoreContractAddress}; use updater::{UpdatePolicy, UpdateFilter, ReleaseTrack}; use run::RunCmd; -use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, KillBlockchain, ExportState, DataFormat}; +use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, KillBlockchain, ExportState, DataFormat, ResetBlockchain}; use export_hardcoded_sync::ExportHsyncCmd; use presale::ImportWallet; use account::{AccountCmd, NewAccount, ListAccounts, ImportAccounts, ImportFromGethAccounts}; @@ -144,6 +146,8 @@ impl Configuration { let ipfs_conf = self.ipfs_config(); let secretstore_conf = self.secretstore_config()?; let format = self.format()?; + let keys_iterations = NonZeroU32::new(self.args.arg_keys_iterations) + .ok_or_else(|| "--keys-iterations must be non-zero")?; let cmd = if self.args.flag_version { Cmd::Version @@ -178,6 +182,19 @@ impl Configuration { } } else if self.args.cmd_tools && self.args.cmd_tools_hash { Cmd::Hash(self.args.arg_tools_hash_file) + } else if self.args.cmd_db && self.args.cmd_db_reset { + Cmd::Blockchain(BlockchainCmd::Reset(ResetBlockchain { + dirs, + spec, + pruning, + pruning_history, + pruning_memory: self.args.arg_pruning_memory, + tracing, + fat_db, + compaction, + cache_config, + num: self.args.arg_db_reset_num, + })) } else if self.args.cmd_db && self.args.cmd_db_kill { Cmd::Blockchain(BlockchainCmd::Kill(KillBlockchain { spec: spec, @@ -187,7 +204,7 @@ impl Configuration { } else if self.args.cmd_account { let account_cmd = if self.args.cmd_account_new { let new_acc = NewAccount { - iterations: self.args.arg_keys_iterations, + iterations: keys_iterations, path: dirs.keys, spec: spec, password_file: self.accounts_config()?.password_files.first().map(|x| x.to_owned()), @@ -221,7 +238,7 @@ impl Configuration { Cmd::Account(account_cmd) } else if self.args.cmd_wallet { let presale_cmd = ImportWallet { - iterations: self.args.arg_keys_iterations, + iterations: keys_iterations, path: dirs.keys, spec: spec, wallet_path: self.args.arg_wallet_import_path.clone().unwrap(), @@ -428,6 +445,7 @@ impl Configuration { gas_range_target: (floor, ceil), engine_signer: self.engine_signer()?, work_notify: self.work_notify(), + local_accounts: HashSet::from_iter(to_addresses(&self.args.arg_tx_queue_locals)?.into_iter()), }; Ok(extras) @@ -517,8 +535,10 @@ impl Configuration { } fn accounts_config(&self) -> Result { + let keys_iterations = NonZeroU32::new(self.args.arg_keys_iterations) + .ok_or_else(|| "--keys-iterations must be non-zero")?; let cfg = AccountsConfig { - iterations: self.args.arg_keys_iterations, + iterations: keys_iterations, refresh_time: self.args.arg_accounts_refresh, testnet: self.args.flag_testnet, password_files: self.args.arg_password.iter().map(|s| replace_home(&self.directories().base, s)).collect(), @@ -708,9 +728,18 @@ impl Configuration { let port = self.args.arg_ports_shift + self.args.arg_port; let listen_address = SocketAddr::new(self.interface(&self.args.arg_interface).parse().unwrap(), port); let public_address = if self.args.arg_nat.starts_with("extip:") { - let host = &self.args.arg_nat[6..]; - let host = host.parse().map_err(|_| format!("Invalid host given with `--nat extip:{}`", host))?; - Some(SocketAddr::new(host, port)) + let host = self.args.arg_nat[6..].split(':').next().expect("split has at least one part; qed"); + let host = format!("{}:{}", host, port); + match host.to_socket_addrs() { + Ok(mut addr_iter) => { + if let Some(addr) = addr_iter.next() { + Some(addr) + } else { + return Err(format!("Invalid host given with `--nat extip:{}`", &self.args.arg_nat[6..])) + } + }, + Err(_) => return Err(format!("Invalid host given with `--nat extip:{}`", &self.args.arg_nat[6..])) + } } else { None }; @@ -906,20 +935,12 @@ impl Configuration { let provider_conf = ProviderConfig { validator_accounts: to_addresses(&self.args.arg_private_validators)?, signer_account: self.args.arg_private_signer.clone().and_then(|account| to_address(Some(account)).ok()), - passwords: match self.args.arg_private_passwords.clone() { - Some(file) => passwords_from_files(&vec![file].as_slice())?, - None => Vec::new(), - }, }; let encryptor_conf = EncryptorConfig { base_url: self.args.arg_private_sstore_url.clone(), threshold: self.args.arg_private_sstore_threshold.unwrap_or(0), key_server_account: self.args.arg_private_account.clone().and_then(|account| to_address(Some(account)).ok()), - passwords: match self.args.arg_private_passwords.clone() { - Some(file) => passwords_from_files(&vec![file].as_slice())?, - None => Vec::new(), - }, }; Ok((provider_conf, encryptor_conf, self.args.flag_private_enabled)) @@ -930,7 +951,7 @@ impl Configuration { no_periodic: self.args.flag_no_periodic_snapshot, processing_threads: match self.args.arg_snapshot_threads { Some(threads) if threads > 0 => threads, - _ => ::std::cmp::max(1, num_cpus::get() / 2), + _ => ::std::cmp::max(1, num_cpus::get_physical() / 2), }, }; @@ -1060,6 +1081,7 @@ impl Configuration { match self.args.arg_secretstore_secret { Some(ref s) if s.len() == 64 => Ok(Some(NodeSecretKey::Plain(s.parse() .map_err(|e| format!("Invalid secret store secret: {}. Error: {:?}", s, e))?))), + #[cfg(feature = "accounts")] Some(ref s) if s.len() == 40 => Ok(Some(NodeSecretKey::KeyStore(s.parse() .map_err(|e| format!("Invalid secret store secret address: {}. Error: {:?}", s, e))?))), Some(_) => Err(format!("Invalid secret store secret. Must be either existing account address, or hex-encoded private key")), @@ -1207,6 +1229,10 @@ mod tests { use super::*; + lazy_static! { + static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed"); + } + #[derive(Debug, PartialEq)] struct TestPasswordReader(&'static str); @@ -1228,7 +1254,7 @@ mod tests { let args = vec!["parity", "account", "new"]; let conf = parse(&args); assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account(AccountCmd::New(NewAccount { - iterations: 10240, + iterations: *ITERATIONS, path: Directories::default().keys, password_file: None, spec: SpecType::default(), @@ -1263,7 +1289,7 @@ mod tests { let args = vec!["parity", "wallet", "import", "my_wallet.json", "--password", "pwd"]; let conf = parse(&args); assert_eq!(conf.into_command().unwrap().cmd, Cmd::ImportPresaleWallet(ImportWallet { - iterations: 10240, + iterations: *ITERATIONS, path: Directories::default().keys, wallet_path: "my_wallet.json".into(), password_file: Some("pwd".into()), @@ -1835,6 +1861,33 @@ mod tests { assert_eq!(conf1.ipfs_config().port, 5002); } + #[test] + fn should_resolve_external_nat_hosts() { + // Ip works + let conf = parse(&["parity", "--nat", "extip:1.1.1.1"]); + assert_eq!(conf.net_addresses().unwrap().1.unwrap().ip().to_string(), "1.1.1.1"); + assert_eq!(conf.net_addresses().unwrap().1.unwrap().port(), 30303); + + // Ip with port works, port is discarded + let conf = parse(&["parity", "--nat", "extip:192.168.1.1:123"]); + assert_eq!(conf.net_addresses().unwrap().1.unwrap().ip().to_string(), "192.168.1.1"); + assert_eq!(conf.net_addresses().unwrap().1.unwrap().port(), 30303); + + // Hostname works + let conf = parse(&["parity", "--nat", "extip:ethereum.org"]); + assert!(conf.net_addresses().unwrap().1.is_some()); + assert_eq!(conf.net_addresses().unwrap().1.unwrap().port(), 30303); + + // Hostname works, garbage at the end is discarded + let conf = parse(&["parity", "--nat", "extip:ethereum.org:whatever bla bla 123"]); + assert!(conf.net_addresses().unwrap().1.is_some()); + assert_eq!(conf.net_addresses().unwrap().1.unwrap().port(), 30303); + + // Garbage is error + let conf = parse(&["parity", "--nat", "extip:blabla"]); + assert!(conf.net_addresses().is_err()); + } + #[test] fn should_expose_all_servers() { // given diff --git a/parity/helpers.rs b/parity/helpers.rs index 1d018f423b..b68d854d1a 100644 --- a/parity/helpers.rs +++ b/parity/helpers.rs @@ -18,6 +18,7 @@ use std::io; use std::io::{Write, BufReader, BufRead}; use std::time::Duration; use std::fs::File; +use std::collections::HashSet; use ethereum_types::{U256, clean_0x, Address}; use journaldb::Algorithm; use ethcore::client::{Mode, BlockId, VMType, DatabaseCompactionProfile, ClientConfig, VerifierType}; @@ -134,6 +135,13 @@ pub fn to_price(s: &str) -> Result { s.parse::().map_err(|_| format!("Invalid transaciton price 's' given. Must be a decimal number.")) } +pub fn join_set(set: Option<&HashSet>) -> Option { + match set { + Some(s) => Some(s.iter().map(|s| s.as_str()).collect::>().join(",")), + None => None + } +} + /// Flush output buffer. pub fn flush_stdout() { io::stdout().flush().expect("stdout is flushable; qed"); @@ -327,12 +335,13 @@ mod tests { use std::time::Duration; use std::fs::File; use std::io::Write; + use std::collections::HashSet; use tempdir::TempDir; use ethereum_types::U256; use ethcore::client::{Mode, BlockId}; use ethcore::miner::PendingSet; use ethkey::Password; - use super::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_address, to_addresses, to_price, geth_ipc_path, to_bootnodes, password_from_file}; + use super::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_address, to_addresses, to_price, geth_ipc_path, to_bootnodes, join_set, password_from_file}; #[test] fn test_to_duration() { @@ -472,4 +481,20 @@ but the first password is trimmed assert_eq!(to_bootnodes(&Some(one_bootnode.into())), Ok(vec![one_bootnode.into()])); assert_eq!(to_bootnodes(&Some(two_bootnodes.into())), Ok(vec![one_bootnode.into(), one_bootnode.into()])); } + + #[test] + fn test_join_set() { + let mut test_set = HashSet::new(); + test_set.insert("0x1111111111111111111111111111111111111111".to_string()); + test_set.insert("0x0000000000000000000000000000000000000000".to_string()); + + + let res = join_set(Some(&test_set)).unwrap(); + + assert!( + res == "0x1111111111111111111111111111111111111111,0x0000000000000000000000000000000000000000" + || + res == "0x0000000000000000000000000000000000000000,0x1111111111111111111111111111111111111111" + ); + } } diff --git a/parity/informant.rs b/parity/informant.rs index 0299f524f2..78d055686b 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -146,7 +146,7 @@ impl InformantData for FullNodeInformantData { (Some(sync), Some(net)) => { let status = sync.status(); let num_peers_range = net.num_peers_range(); - debug_assert!(num_peers_range.end > num_peers_range.start); + debug_assert!(num_peers_range.end() >= num_peers_range.start()); cache_sizes.insert("sync", status.mem_used); @@ -154,7 +154,7 @@ impl InformantData for FullNodeInformantData { last_imported_block_number: status.last_imported_block_number.unwrap_or(chain_info.best_block_number), last_imported_old_block_number: status.last_imported_old_block_number, num_peers: status.num_peers, - max_peers: status.current_max_peers(num_peers_range.start, num_peers_range.end - 1), + max_peers: status.current_max_peers(*num_peers_range.start(), *num_peers_range.end()), snapshot_sync: status.is_snapshot_syncing(), }) } diff --git a/parity/lib.rs b/parity/lib.rs index 681405b906..b3ca3baf7f 100644 --- a/parity/lib.rs +++ b/parity/lib.rs @@ -15,7 +15,6 @@ // along with Parity Ethereum. If not, see . //! Ethcore client application. - #![warn(missing_docs)] extern crate ansi_term; @@ -43,7 +42,6 @@ extern crate toml; extern crate blooms_db; extern crate cli_signer; extern crate common_types as types; -extern crate parity_bytes as bytes; extern crate ethcore; extern crate ethcore_call_contract as call_contract; extern crate ethcore_db; @@ -56,27 +54,31 @@ extern crate ethcore_private_tx; extern crate ethcore_service; extern crate ethcore_sync as sync; extern crate ethereum_types; -extern crate ethstore; extern crate ethkey; +extern crate ethstore; +extern crate journaldb; +extern crate keccak_hash as hash; extern crate kvdb; +extern crate node_filter; +extern crate parity_bytes as bytes; extern crate parity_hash_fetch as hash_fetch; extern crate parity_ipfs_api; extern crate parity_local_store as local_store; +extern crate parity_path as path; extern crate parity_rabbitmq; -extern crate parity_runtime; extern crate parity_rpc; +extern crate parity_runtime; extern crate parity_updater as updater; extern crate parity_version; extern crate parity_whisper; -extern crate parity_path as path; -extern crate node_filter; -extern crate keccak_hash as hash; -extern crate journaldb; extern crate registrar; #[macro_use] extern crate log as rlog; +#[cfg(feature = "ethcore-accounts")] +extern crate ethcore_accounts as accounts; + #[cfg(feature = "secretstore")] extern crate ethcore_secretstore; @@ -87,7 +89,12 @@ extern crate pretty_assertions; #[cfg(test)] extern crate tempdir; +#[cfg(test)] +#[macro_use] +extern crate lazy_static; + mod account; +mod account_utils; mod blockchain; mod cache; mod cli; @@ -112,19 +119,22 @@ mod user_defaults; mod whisper; mod db; -use std::io::BufReader; use std::fs::File; -use hash::keccak_buffer; +use std::io::BufReader; +use std::sync::Arc; + use cli::Args; use configuration::{Cmd, Execute}; use deprecated::find_deprecated; -use ethcore_logger::setup_log; +use hash::keccak_buffer; + #[cfg(feature = "memory_profiling")] use std::alloc::System; pub use self::configuration::Configuration; pub use self::run::RunningClient; pub use parity_rpc::PubSubSession; +pub use ethcore_logger::{Config as LoggerConfig, setup_log, RotatingLogger}; #[cfg(feature = "memory_profiling")] #[global_allocator] @@ -181,14 +191,13 @@ pub enum ExecutionAction { Running(RunningClient), } -fn execute(command: Execute, on_client_rq: Cr, on_updater_rq: Rr) -> Result +fn execute( + command: Execute, + logger: Arc, + on_client_rq: Cr, on_updater_rq: Rr) -> Result where Cr: Fn(String) + 'static + Send, Rr: Fn() + 'static + Send { - // TODO: move this to `main()` and expose in the C API so that users can setup logging the way - // they want - let logger = setup_log(&command.logger).expect("Logger is initialized only once; qed"); - #[cfg(feature = "deadlock_detection")] run_deadlock_detection_thread(); @@ -222,14 +231,21 @@ fn execute(command: Execute, on_client_rq: Cr, on_updater_rq: Rr) -> Res /// binary. /// /// On error, returns what to print on stderr. -pub fn start(conf: Configuration, on_client_rq: Cr, on_updater_rq: Rr) -> Result - where Cr: Fn(String) + 'static + Send, - Rr: Fn() + 'static + Send +// FIXME: totally independent logging capability, see https://github.com/paritytech/parity-ethereum/issues/10252 +pub fn start( + conf: Configuration, + logger: Arc, + on_client_rq: Cr, + on_updater_rq: Rr +) -> Result + where + Cr: Fn(String) + 'static + Send, + Rr: Fn() + 'static + Send { let deprecated = find_deprecated(&conf.args); for d in deprecated { println!("{}", d); } - execute(conf.into_command()?, on_client_rq, on_updater_rq) + execute(conf.into_command()?, logger, on_client_rq, on_updater_rq) } diff --git a/parity/light_helpers/epoch_fetch.rs b/parity/light_helpers/epoch_fetch.rs index ecf9486089..9c7fd6a8ee 100644 --- a/parity/light_helpers/epoch_fetch.rs +++ b/parity/light_helpers/epoch_fetch.rs @@ -18,7 +18,7 @@ use std::sync::{Arc, Weak}; use ethcore::engines::{EthEngine, StateDependentProof}; use ethcore::machine::EthereumMachine; -use sync::LightSync; +use sync::{LightSync, LightNetworkDispatcher}; use types::encoded; use types::header::Header; use types::receipt::Receipt; @@ -27,7 +27,7 @@ use futures::{future, Future}; use futures::future::Either; use light::client::fetch::ChainDataFetcher; -use light::on_demand::{request, OnDemand}; +use light::on_demand::{request, OnDemand, OnDemandRequester}; use parking_lot::RwLock; use ethereum_types::H256; diff --git a/parity/light_helpers/mod.rs b/parity/light_helpers/mod.rs index 9a9bbf2cd8..843dd419d4 100644 --- a/parity/light_helpers/mod.rs +++ b/parity/light_helpers/mod.rs @@ -17,7 +17,5 @@ //! Utilities and helpers for the light client. mod epoch_fetch; -mod queue_cull; pub use self::epoch_fetch::EpochFetch; -pub use self::queue_cull::QueueCull; diff --git a/parity/light_helpers/queue_cull.rs b/parity/light_helpers/queue_cull.rs deleted file mode 100644 index c919511ba5..0000000000 --- a/parity/light_helpers/queue_cull.rs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -//! Service for culling the light client's transaction queue. - -use std::sync::Arc; -use std::time::Duration; - -use ethcore::client::ClientIoMessage; -use sync::LightSync; -use io::{IoContext, IoHandler, TimerToken}; - -use light::client::LightChainClient; -use light::on_demand::{request, OnDemand}; -use light::TransactionQueue; - -use futures::{future, Future}; - -use parity_runtime::Executor; - -use parking_lot::RwLock; - -// Attepmt to cull once every 10 minutes. -const TOKEN: TimerToken = 1; -const TIMEOUT: Duration = Duration::from_secs(60 * 10); - -// But make each attempt last only 9 minutes -const PURGE_TIMEOUT: Duration = Duration::from_secs(60 * 9); - -/// Periodically culls the transaction queue of mined transactions. -pub struct QueueCull { - /// A handle to the client, for getting the latest block header. - pub client: Arc, - /// A handle to the sync service. - pub sync: Arc, - /// The on-demand request service. - pub on_demand: Arc, - /// The transaction queue. - pub txq: Arc>, - /// Event loop executor. - pub executor: Executor, -} - -impl IoHandler for QueueCull { - fn initialize(&self, io: &IoContext) { - io.register_timer(TOKEN, TIMEOUT).expect("Error registering timer"); - } - - fn timeout(&self, _io: &IoContext, timer: TimerToken) { - if timer != TOKEN { return } - - let senders = self.txq.read().queued_senders(); - if senders.is_empty() { return } - - let (sync, on_demand, txq) = (self.sync.clone(), self.on_demand.clone(), self.txq.clone()); - let best_header = self.client.best_block_header(); - let start_nonce = self.client.engine().account_start_nonce(best_header.number()); - - info!(target: "cull", "Attempting to cull queued transactions from {} senders.", senders.len()); - self.executor.spawn_with_timeout(move || { - let maybe_fetching = sync.with_context(move |ctx| { - // fetch the nonce of each sender in the queue. - let nonce_reqs = senders.iter() - .map(|&address| request::Account { header: best_header.clone().into(), address: address }) - .collect::>(); - - // when they come in, update each sender to the new nonce. - on_demand.request(ctx, nonce_reqs) - .expect("No back-references; therefore all back-references are valid; qed") - .map(move |accs| { - let txq = txq.write(); - let _ = accs.into_iter() - .map(|maybe_acc| maybe_acc.map_or(start_nonce, |acc| acc.nonce)) - .zip(senders) - .fold(txq, |mut txq, (nonce, addr)| { - txq.cull(addr, nonce); - txq - }); - }) - .map_err(|_| debug!(target: "cull", "OnDemand prematurely closed channel.")) - }); - - match maybe_fetching { - Some(fut) => future::Either::A(fut), - None => { - debug!(target: "cull", "Unable to acquire network context; qed"); - future::Either::B(future::ok(())) - }, - } - }, PURGE_TIMEOUT, || {}) - } -} diff --git a/parity/logger/Cargo.toml b/parity/logger/Cargo.toml index 17c8c4396d..217bcf48a6 100644 --- a/parity/logger/Cargo.toml +++ b/parity/logger/Cargo.toml @@ -1,5 +1,5 @@ [package] -description = "Log implementation for Parity" +description = "Parity Ethereum Logger Implementation" name = "ethcore-logger" version = "1.12.0" license = "GPL-3.0" diff --git a/parity/logger/src/lib.rs b/parity/logger/src/lib.rs index da4a28bed1..a2e3de176a 100644 --- a/parity/logger/src/lib.rs +++ b/parity/logger/src/lib.rs @@ -94,7 +94,7 @@ pub fn setup_log(config: &Config) -> Result, String> { let maybe_file = match config.file.as_ref() { Some(f) => Some(open_options .append(true).create(true).open(f) - .map_err(|_| format!("Cannot write to log file given: {}", f))?), + .map_err(|e| format!("Cannot write to log file given: {}, {}", f, e))?), None => None, }; diff --git a/parity/main.rs b/parity/main.rs index 79f83db840..066061cbaf 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -26,24 +26,28 @@ extern crate log; extern crate panic_hook; extern crate parity_ethereum; extern crate parking_lot; +extern crate parity_daemonize; +extern crate ansi_term; #[cfg(windows)] extern crate winapi; extern crate ethcore_logger; use std::ffi::OsString; use std::fs::{remove_file, metadata, File, create_dir_all}; -use std::io::{self as stdio, Read, Write}; +use std::io::{Read, Write}; use std::path::PathBuf; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use std::{process, env}; +use ansi_term::Colour; use ctrlc::CtrlC; use dir::default_hypervisor_path; use fdlimit::raise_fd_limit; +use ethcore_logger::setup_log; use parity_ethereum::{start, ExecutionAction}; +use parity_daemonize::AsHandle; use parking_lot::{Condvar, Mutex}; -use ethcore_logger::setup_log; const PLEASE_RESTART_EXIT_CODE: i32 = 69; const PARITY_EXECUTABLE_NAME: &str = "parity"; @@ -196,6 +200,26 @@ fn main_direct(force_can_restart: bool) -> i32 { conf.args.arg_chain = spec_override; } + // FIXME: `pid_file` shouldn't need to cloned here + // see: `https://github.com/paritytech/parity-daemonize/pull/13` for more info + let handle = if let Some(pid) = conf.args.arg_daemon_pid_file.clone() { + info!("{}", Colour::Blue.paint("starting in daemon mode").to_string()); + let _ = std::io::stdout().flush(); + + match parity_daemonize::daemonize(pid) { + Ok(h) => Some(h), + Err(e) => { + error!( + "{}", + Colour::Red.paint(format!("{}", e)) + ); + return 1; + } + } + } else { + None + }; + let can_restart = force_can_restart || conf.args.flag_can_restart; // increase max number of open files @@ -215,6 +239,7 @@ fn main_direct(force_can_restart: bool) -> i32 { let exec = if can_restart { start( conf, + logger, { let e = exit.clone(); let exiting = exiting.clone(); @@ -246,10 +271,9 @@ fn main_direct(force_can_restart: bool) -> i32 { } } ) - } else { trace!(target: "mode", "Not hypervised: not setting exit handlers."); - start(conf, move |_| {}, move || {}) + start(conf, logger, move |_| {}, move || {}) }; let res = match exec { @@ -261,7 +285,7 @@ fn main_direct(force_can_restart: bool) -> i32 { let e = exit.clone(); let exiting = exiting.clone(); move |panic_msg| { - let _ = stdio::stderr().write_all(panic_msg.as_bytes()); + eprintln!("{}", panic_msg); if !exiting.swap(true, Ordering::SeqCst) { *e.0.lock() = ExitStatus { panicking: true, @@ -290,6 +314,12 @@ fn main_direct(force_can_restart: bool) -> i32 { } }); + // so the client has started successfully + // if this is a daemon, detach from the parent process + if let Some(mut handle) = handle { + handle.detach() + } + // Wait for signal let mut lock = exit.0.lock(); if !lock.should_exit { @@ -313,7 +343,12 @@ fn main_direct(force_can_restart: bool) -> i32 { }, }, Err(err) => { - writeln!(&mut stdio::stderr(), "{}", err).expect("StdErr available; qed"); + // error occured during start up + // if this is a daemon, detach from the parent process + if let Some(mut handle) = handle { + handle.detach_with_msg(format!("{}", Colour::Red.paint(&err))) + } + eprintln!("{}", err); 1 }, }; @@ -328,7 +363,6 @@ fn println_trace_main(s: String) { } } -#[macro_export] macro_rules! trace_main { ($arg:expr) => (println_trace_main($arg.into())); ($($arg:tt)*) => (println_trace_main(format!("{}", format_args!($($arg)*)))); diff --git a/parity/params.rs b/parity/params.rs index 11414edf00..f17cae2c57 100644 --- a/parity/params.rs +++ b/parity/params.rs @@ -14,8 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use std::{str, fs, fmt}; +use std::collections::HashSet; use std::time::Duration; +use std::{str, fs, fmt}; +use std::num::NonZeroU32; use ethcore::client::Mode; use ethcore::ethereum; @@ -34,17 +36,20 @@ pub enum SpecType { Foundation, Classic, Poanet, - Tobalaba, + Xdai, + Volta, + Ewc, Expanse, Musicoin, Ellaism, - Easthub, - Social, Mix, Callisto, Morden, Ropsten, Kovan, + Rinkeby, + Goerli, + Kotti, Sokol, Dev, Custom(String), @@ -64,17 +69,20 @@ impl str::FromStr for SpecType { "ethereum" | "frontier" | "homestead" | "byzantium" | "foundation" | "mainnet" => SpecType::Foundation, "classic" | "frontier-dogmatic" | "homestead-dogmatic" => SpecType::Classic, "poanet" | "poacore" => SpecType::Poanet, - "tobalaba" => SpecType::Tobalaba, + "xdai" => SpecType::Xdai, + "volta" => SpecType::Volta, + "ewc" | "energyweb" => SpecType::Ewc, "expanse" => SpecType::Expanse, "musicoin" => SpecType::Musicoin, "ellaism" => SpecType::Ellaism, - "easthub" => SpecType::Easthub, - "social" => SpecType::Social, "mix" => SpecType::Mix, "callisto" => SpecType::Callisto, "morden" | "classic-testnet" => SpecType::Morden, "ropsten" => SpecType::Ropsten, "kovan" | "testnet" => SpecType::Kovan, + "rinkeby" => SpecType::Rinkeby, + "goerli" | "görli" => SpecType::Goerli, + "kotti" => SpecType::Kotti, "sokol" | "poasokol" => SpecType::Sokol, "dev" => SpecType::Dev, other => SpecType::Custom(other.into()), @@ -89,17 +97,20 @@ impl fmt::Display for SpecType { SpecType::Foundation => "foundation", SpecType::Classic => "classic", SpecType::Poanet => "poanet", - SpecType::Tobalaba => "tobalaba", + SpecType::Xdai => "xdai", + SpecType::Volta => "volta", + SpecType::Ewc => "energyweb", SpecType::Expanse => "expanse", SpecType::Musicoin => "musicoin", SpecType::Ellaism => "ellaism", - SpecType::Easthub => "easthub", - SpecType::Social => "social", SpecType::Mix => "mix", SpecType::Callisto => "callisto", SpecType::Morden => "morden", SpecType::Ropsten => "ropsten", SpecType::Kovan => "kovan", + SpecType::Rinkeby => "rinkeby", + SpecType::Goerli => "goerli", + SpecType::Kotti => "kotti", SpecType::Sokol => "sokol", SpecType::Dev => "dev", SpecType::Custom(ref custom) => custom, @@ -114,17 +125,20 @@ impl SpecType { SpecType::Foundation => Ok(ethereum::new_foundation(params)), SpecType::Classic => Ok(ethereum::new_classic(params)), SpecType::Poanet => Ok(ethereum::new_poanet(params)), - SpecType::Tobalaba => Ok(ethereum::new_tobalaba(params)), + SpecType::Xdai => Ok(ethereum::new_xdai(params)), + SpecType::Volta => Ok(ethereum::new_volta(params)), + SpecType::Ewc => Ok(ethereum::new_ewc(params)), SpecType::Expanse => Ok(ethereum::new_expanse(params)), SpecType::Musicoin => Ok(ethereum::new_musicoin(params)), SpecType::Ellaism => Ok(ethereum::new_ellaism(params)), - SpecType::Easthub => Ok(ethereum::new_easthub(params)), - SpecType::Social => Ok(ethereum::new_social(params)), SpecType::Mix => Ok(ethereum::new_mix(params)), SpecType::Callisto => Ok(ethereum::new_callisto(params)), SpecType::Morden => Ok(ethereum::new_morden(params)), SpecType::Ropsten => Ok(ethereum::new_ropsten(params)), SpecType::Kovan => Ok(ethereum::new_kovan(params)), + SpecType::Rinkeby => Ok(ethereum::new_rinkeby(params)), + SpecType::Goerli => Ok(ethereum::new_goerli(params)), + SpecType::Kotti => Ok(ethereum::new_kotti(params)), SpecType::Sokol => Ok(ethereum::new_sokol(params)), SpecType::Dev => Ok(Spec::new_instant()), SpecType::Custom(ref filename) => { @@ -214,7 +228,7 @@ impl str::FromStr for ResealPolicy { #[derive(Debug, PartialEq)] pub struct AccountsConfig { - pub iterations: u32, + pub iterations: NonZeroU32, pub refresh_time: u64, pub testnet: bool, pub password_files: Vec, @@ -226,7 +240,7 @@ pub struct AccountsConfig { impl Default for AccountsConfig { fn default() -> Self { AccountsConfig { - iterations: 10240, + iterations: NonZeroU32::new(10240).expect("10240 > 0; qed"), refresh_time: 5, testnet: false, password_files: Vec::new(), @@ -282,6 +296,7 @@ pub struct MinerExtras { pub extra_data: Vec, pub gas_range_target: (U256, U256), pub work_notify: Vec, + pub local_accounts: HashSet
, } impl Default for MinerExtras { @@ -292,6 +307,7 @@ impl Default for MinerExtras { extra_data: version_data(), gas_range_target: (8_000_000.into(), 10_000_000.into()), work_notify: Default::default(), + local_accounts: Default::default(), } } } @@ -368,12 +384,13 @@ mod tests { assert_eq!(SpecType::Classic, "homestead-dogmatic".parse().unwrap()); assert_eq!(SpecType::Poanet, "poanet".parse().unwrap()); assert_eq!(SpecType::Poanet, "poacore".parse().unwrap()); - assert_eq!(SpecType::Tobalaba, "tobalaba".parse().unwrap()); + assert_eq!(SpecType::Xdai, "xdai".parse().unwrap()); + assert_eq!(SpecType::Volta, "volta".parse().unwrap()); + assert_eq!(SpecType::Ewc, "ewc".parse().unwrap()); + assert_eq!(SpecType::Ewc, "energyweb".parse().unwrap()); assert_eq!(SpecType::Expanse, "expanse".parse().unwrap()); assert_eq!(SpecType::Musicoin, "musicoin".parse().unwrap()); assert_eq!(SpecType::Ellaism, "ellaism".parse().unwrap()); - assert_eq!(SpecType::Easthub, "easthub".parse().unwrap()); - assert_eq!(SpecType::Social, "social".parse().unwrap()); assert_eq!(SpecType::Mix, "mix".parse().unwrap()); assert_eq!(SpecType::Callisto, "callisto".parse().unwrap()); assert_eq!(SpecType::Morden, "morden".parse().unwrap()); @@ -381,6 +398,10 @@ mod tests { assert_eq!(SpecType::Ropsten, "ropsten".parse().unwrap()); assert_eq!(SpecType::Kovan, "kovan".parse().unwrap()); assert_eq!(SpecType::Kovan, "testnet".parse().unwrap()); + assert_eq!(SpecType::Rinkeby, "rinkeby".parse().unwrap()); + assert_eq!(SpecType::Goerli, "goerli".parse().unwrap()); + assert_eq!(SpecType::Goerli, "görli".parse().unwrap()); + assert_eq!(SpecType::Kotti, "kotti".parse().unwrap()); assert_eq!(SpecType::Sokol, "sokol".parse().unwrap()); assert_eq!(SpecType::Sokol, "poasokol".parse().unwrap()); } @@ -395,17 +416,20 @@ mod tests { assert_eq!(format!("{}", SpecType::Foundation), "foundation"); assert_eq!(format!("{}", SpecType::Classic), "classic"); assert_eq!(format!("{}", SpecType::Poanet), "poanet"); - assert_eq!(format!("{}", SpecType::Tobalaba), "tobalaba"); + assert_eq!(format!("{}", SpecType::Xdai), "xdai"); + assert_eq!(format!("{}", SpecType::Volta), "volta"); + assert_eq!(format!("{}", SpecType::Ewc), "energyweb"); assert_eq!(format!("{}", SpecType::Expanse), "expanse"); assert_eq!(format!("{}", SpecType::Musicoin), "musicoin"); assert_eq!(format!("{}", SpecType::Ellaism), "ellaism"); - assert_eq!(format!("{}", SpecType::Easthub), "easthub"); - assert_eq!(format!("{}", SpecType::Social), "social"); assert_eq!(format!("{}", SpecType::Mix), "mix"); assert_eq!(format!("{}", SpecType::Callisto), "callisto"); assert_eq!(format!("{}", SpecType::Morden), "morden"); assert_eq!(format!("{}", SpecType::Ropsten), "ropsten"); assert_eq!(format!("{}", SpecType::Kovan), "kovan"); + assert_eq!(format!("{}", SpecType::Rinkeby), "rinkeby"); + assert_eq!(format!("{}", SpecType::Goerli), "goerli"); + assert_eq!(format!("{}", SpecType::Kotti), "kotti"); assert_eq!(format!("{}", SpecType::Sokol), "sokol"); assert_eq!(format!("{}", SpecType::Dev), "dev"); assert_eq!(format!("{}", SpecType::Custom("foo/bar".into())), "foo/bar"); diff --git a/parity/presale.rs b/parity/presale.rs index da5bef369e..162d149b54 100644 --- a/parity/presale.rs +++ b/parity/presale.rs @@ -14,15 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use ethstore::{PresaleWallet, EthStore}; -use ethstore::accounts_dir::RootDiskDirectory; -use ethcore::account_provider::{AccountProvider, AccountProviderSettings}; + +use ethkey::Password; +use ethstore::PresaleWallet; use helpers::{password_prompt, password_from_file}; use params::SpecType; +use std::num::NonZeroU32; #[derive(Debug, PartialEq)] pub struct ImportWallet { - pub iterations: u32, + pub iterations: NonZeroU32, pub path: String, pub spec: SpecType, pub wallet_path: String, @@ -30,16 +31,29 @@ pub struct ImportWallet { } pub fn execute(cmd: ImportWallet) -> Result { - let password = match cmd.password_file { + let password = match cmd.password_file.clone() { Some(file) => password_from_file(file)?, None => password_prompt()?, }; - let dir = Box::new(RootDiskDirectory::create(cmd.path).unwrap()); - let secret_store = Box::new(EthStore::open_with_iterations(dir, cmd.iterations).unwrap()); - let acc_provider = AccountProvider::new(secret_store, AccountProviderSettings::default()); - let wallet = PresaleWallet::open(cmd.wallet_path).map_err(|_| "Unable to open presale wallet.")?; + let wallet = PresaleWallet::open(cmd.wallet_path.clone()).map_err(|_| "Unable to open presale wallet.")?; let kp = wallet.decrypt(&password).map_err(|_| "Invalid password.")?; - let address = acc_provider.insert_account(kp.secret().clone(), &password).unwrap(); + let address = kp.address(); + import_account(&cmd, kp, password); Ok(format!("{:?}", address)) } + +#[cfg(feature = "accounts")] +pub fn import_account(cmd: &ImportWallet, kp: ethkey::KeyPair, password: Password) { + use accounts::{AccountProvider, AccountProviderSettings}; + use ethstore::EthStore; + use ethstore::accounts_dir::RootDiskDirectory; + + let dir = Box::new(RootDiskDirectory::create(cmd.path.clone()).unwrap()); + let secret_store = Box::new(EthStore::open_with_iterations(dir, cmd.iterations).unwrap()); + let acc_provider = AccountProvider::new(secret_store, AccountProviderSettings::default()); + acc_provider.insert_account(kp.secret().clone(), &password).unwrap(); +} + +#[cfg(not(feature = "accounts"))] +pub fn import_account(_cmd: &ImportWallet, _kp: ethkey::KeyPair, _password: Password) {} diff --git a/parity/rpc.rs b/parity/rpc.rs index 57bb584775..b07ca3f3e4 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -151,7 +151,7 @@ pub fn new_ws( let url = format!("{}:{}", conf.interface, conf.port); let addr = url.parse().map_err(|_| format!("Invalid WebSockets listen host/port given: {}", url))?; - let full_handler = setup_apis(rpc_apis::ApiSet::SafeContext, deps); + let full_handler = setup_apis(rpc_apis::ApiSet::All, deps); let handler = { let mut handler = MetaIoHandler::with_middleware(( rpc::WsDispatcher::new(full_handler), diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index 10eaa55448..668206174b 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -21,7 +21,7 @@ use std::sync::{Arc, Weak}; pub use parity_rpc::signer::SignerService; -use ethcore::account_provider::AccountProvider; +use account_utils::{self, AccountProvider}; use ethcore::client::Client; use ethcore::miner::Miner; use ethcore::snapshot::SnapshotService; @@ -113,11 +113,9 @@ impl FromStr for Api { #[derive(Debug, Clone)] pub enum ApiSet { - // Safe context (like token-protected WS interface) - SafeContext, // Unsafe context (like jsonrpc over http) UnsafeContext, - // All possible APIs + // All possible APIs (safe context like token-protected WS interface) All, // Local "unsafe" context and accounts access IpcContext, @@ -197,6 +195,26 @@ fn to_modules(apis: &HashSet) -> BTreeMap { modules } +macro_rules! add_signing_methods { + ($namespace:ident, $handler:expr, $deps:expr, $dispatch:expr) => {{ + let deps = &$deps; + let (dispatcher, accounts) = $dispatch; + if deps.signer_service.is_enabled() { + $handler.extend_with($namespace::to_delegate(SigningQueueClient::new( + &deps.signer_service, + dispatcher.clone(), + deps.executor.clone(), + accounts, + ))) + } else { + $handler.extend_with($namespace::to_delegate(SigningUnsafeClient::new( + accounts, + dispatcher.clone(), + ))) + } + }}; +} + /// RPC dependencies can be used to initialize RPC endpoints from APIs. pub trait Dependencies { type Notifier: ActivityNotifier; @@ -217,7 +235,7 @@ pub struct FullDependencies { pub snapshot: Arc, pub sync: Arc, pub net: Arc, - pub secret_store: Arc, + pub accounts: Arc, pub private_tx_service: Option>, pub miner: Arc, pub external_miner: Arc, @@ -234,6 +252,7 @@ pub struct FullDependencies { pub gas_price_percentile: usize, pub poll_lifetime: u32, pub allow_missing_blocks: bool, + pub no_ancient_blocks: bool, } impl FullDependencies { @@ -247,31 +266,6 @@ impl FullDependencies { { use parity_rpc::v1::*; - macro_rules! add_signing_methods { - ($namespace:ident, $handler:expr, $deps:expr, $nonces:expr) => {{ - let deps = &$deps; - let dispatcher = FullDispatcher::new( - deps.client.clone(), - deps.miner.clone(), - $nonces, - deps.gas_price_percentile, - ); - if deps.signer_service.is_enabled() { - $handler.extend_with($namespace::to_delegate(SigningQueueClient::new( - &deps.signer_service, - dispatcher, - deps.executor.clone(), - &deps.secret_store, - ))) - } else { - $handler.extend_with($namespace::to_delegate(SigningUnsafeClient::new( - &deps.secret_store, - dispatcher, - ))) - } - }}; - } - let nonces = Arc::new(Mutex::new(dispatch::Reservations::new( self.executor.clone(), ))); @@ -281,13 +275,16 @@ impl FullDependencies { nonces.clone(), self.gas_price_percentile, ); + let account_signer = Arc::new(dispatch::Signer::new(self.accounts.clone())) as _; + let accounts = account_utils::accounts_list(self.accounts.clone()); + for api in apis { match *api { Api::Debug => { handler.extend_with(DebugClient::new(self.client.clone()).to_delegate()); } Api::Web3 => { - handler.extend_with(Web3Client::new().to_delegate()); + handler.extend_with(Web3Client::default().to_delegate()); } Api::Net => { handler.extend_with(NetClient::new(&self.sync).to_delegate()); @@ -297,7 +294,7 @@ impl FullDependencies { &self.client, &self.snapshot, &self.sync, - &self.secret_store, + &accounts, &self.miner, &self.external_miner, EthClientOptions { @@ -307,6 +304,7 @@ impl FullDependencies { gas_price_percentile: self.gas_price_percentile, allow_missing_blocks: self.allow_missing_blocks, allow_experimental_rpcs: self.experimental_rpcs, + no_ancient_blocks: self.no_ancient_blocks } ); handler.extend_with(client.to_delegate()); @@ -319,7 +317,7 @@ impl FullDependencies { ); handler.extend_with(filter_client.to_delegate()); - add_signing_methods!(EthSigning, handler, self, nonces.clone()); + add_signing_methods!(EthSigning, handler, self, (&dispatcher, &account_signer)); } } Api::EthPubSub => { @@ -341,9 +339,10 @@ impl FullDependencies { } } Api::Personal => { + #[cfg(feature = "accounts")] handler.extend_with( PersonalClient::new( - &self.secret_store, + &self.accounts, dispatcher.clone(), self.geth_compatibility, self.experimental_rpcs, @@ -353,7 +352,7 @@ impl FullDependencies { Api::Signer => { handler.extend_with( SignerClient::new( - &self.secret_store, + account_signer.clone(), dispatcher.clone(), &self.signer_service, self.executor.clone(), @@ -372,7 +371,6 @@ impl FullDependencies { self.sync.clone(), self.updater.clone(), self.net_service.clone(), - self.secret_store.clone(), self.logger.clone(), self.settings.clone(), signer, @@ -380,9 +378,11 @@ impl FullDependencies { self.snapshot.clone().into(), ).to_delegate(), ); + #[cfg(feature = "accounts")] + handler.extend_with(ParityAccountsInfo::to_delegate(ParityAccountsClient::new(&self.accounts))); if !for_generic_pubsub { - add_signing_methods!(ParitySigning, handler, self, nonces.clone()); + add_signing_methods!(ParitySigning, handler, self, (&dispatcher, &account_signer)); } } Api::ParityPubSub => { @@ -398,25 +398,35 @@ impl FullDependencies { } } Api::ParityAccounts => { - handler - .extend_with(ParityAccountsClient::new(&self.secret_store).to_delegate()); + #[cfg(feature = "accounts")] + handler.extend_with(ParityAccounts::to_delegate(ParityAccountsClient::new(&self.accounts))); + } + Api::ParitySet => { + handler.extend_with( + ParitySetClient::new( + &self.client, + &self.miner, + &self.updater, + &self.net_service, + self.fetch.clone(), + ).to_delegate(), + ); + #[cfg(feature = "accounts")] + handler.extend_with( + ParitySetAccountsClient::new( + &self.accounts, + &self.miner, + ).to_delegate(), + ); } - Api::ParitySet => handler.extend_with( - ParitySetClient::new( - &self.client, - &self.miner, - &self.updater, - &self.net_service, - self.fetch.clone(), - ).to_delegate(), - ), Api::Traces => handler.extend_with(TracesClient::new(&self.client).to_delegate()), Api::Rpc => { let modules = to_modules(&apis); handler.extend_with(RpcClient::new(modules).to_delegate()); } Api::SecretStore => { - handler.extend_with(SecretStoreClient::new(&self.secret_store).to_delegate()); + #[cfg(feature = "accounts")] + handler.extend_with(SecretStoreClient::new(&self.accounts).to_delegate()); } Api::Whisper => { if let Some(ref whisper_rpc) = self.whisper_rpc { @@ -475,7 +485,7 @@ pub struct LightDependencies { pub client: Arc, pub sync: Arc, pub net: Arc, - pub secret_store: Arc, + pub accounts: Arc, pub logger: Arc, pub settings: Arc, pub on_demand: Arc<::light::on_demand::OnDemand>, @@ -512,27 +522,8 @@ impl LightDependencies { ))), self.gas_price_percentile, ); - - macro_rules! add_signing_methods { - ($namespace:ident, $handler:expr, $deps:expr) => {{ - let deps = &$deps; - let dispatcher = dispatcher.clone(); - let secret_store = deps.secret_store.clone(); - if deps.signer_service.is_enabled() { - $handler.extend_with($namespace::to_delegate(SigningQueueClient::new( - &deps.signer_service, - dispatcher, - deps.executor.clone(), - &secret_store, - ))) - } else { - $handler.extend_with($namespace::to_delegate(SigningUnsafeClient::new( - &secret_store, - dispatcher, - ))) - } - }}; - } + let account_signer = Arc::new(dispatch::Signer::new(self.accounts.clone())) as _; + let accounts = account_utils::accounts_list(self.accounts.clone()); for api in apis { match *api { @@ -540,7 +531,7 @@ impl LightDependencies { warn!(target: "rpc", "Debug API is not available in light client mode.") } Api::Web3 => { - handler.extend_with(Web3Client::new().to_delegate()); + handler.extend_with(Web3Client::default().to_delegate()); } Api::Net => { handler.extend_with(light::NetClient::new(self.sync.clone()).to_delegate()); @@ -551,7 +542,7 @@ impl LightDependencies { self.client.clone(), self.on_demand.clone(), self.transaction_queue.clone(), - self.secret_store.clone(), + accounts.clone(), self.cache.clone(), self.gas_price_percentile, self.poll_lifetime, @@ -560,7 +551,7 @@ impl LightDependencies { if !for_generic_pubsub { handler.extend_with(EthFilter::to_delegate(client)); - add_signing_methods!(EthSigning, handler, self); + add_signing_methods!(EthSigning, handler, self, (&dispatcher, &account_signer)); } } Api::EthPubSub => { @@ -584,9 +575,10 @@ impl LightDependencies { handler.extend_with(EthPubSub::to_delegate(client)); } Api::Personal => { + #[cfg(feature = "accounts")] handler.extend_with( PersonalClient::new( - &self.secret_store, + &self.accounts, dispatcher.clone(), self.geth_compatibility, self.experimental_rpcs, @@ -596,7 +588,7 @@ impl LightDependencies { Api::Signer => { handler.extend_with( SignerClient::new( - &self.secret_store, + account_signer.clone(), dispatcher.clone(), &self.signer_service, self.executor.clone(), @@ -611,7 +603,6 @@ impl LightDependencies { handler.extend_with( light::ParityClient::new( Arc::new(dispatcher.clone()), - self.secret_store.clone(), self.logger.clone(), self.settings.clone(), signer, @@ -619,9 +610,13 @@ impl LightDependencies { self.gas_price_percentile, ).to_delegate(), ); + #[cfg(feature = "accounts")] + handler.extend_with( + ParityAccountsInfo::to_delegate(ParityAccountsClient::new(&self.accounts)) + ); if !for_generic_pubsub { - add_signing_methods!(ParitySigning, handler, self); + add_signing_methods!(ParitySigning, handler, self, (&dispatcher, &account_signer)); } } Api::ParityPubSub => { @@ -637,11 +632,11 @@ impl LightDependencies { } } Api::ParityAccounts => { - handler - .extend_with(ParityAccountsClient::new(&self.secret_store).to_delegate()); + #[cfg(feature = "accounts")] + handler.extend_with(ParityAccounts::to_delegate(ParityAccountsClient::new(&self.accounts))); } Api::ParitySet => handler.extend_with( - light::ParitySetClient::new(self.sync.clone(), self.fetch.clone()) + light::ParitySetClient::new(self.client.clone(), self.sync.clone(), self.fetch.clone()) .to_delegate(), ), Api::Traces => handler.extend_with(light::TracesClient.to_delegate()), @@ -650,7 +645,8 @@ impl LightDependencies { handler.extend_with(RpcClient::new(modules).to_delegate()); } Api::SecretStore => { - handler.extend_with(SecretStoreClient::new(&self.secret_store).to_delegate()); + #[cfg(feature = "accounts")] + handler.extend_with(SecretStoreClient::new(&self.accounts).to_delegate()); } Api::Whisper => { if let Some(ref whisper_rpc) = self.whisper_rpc { @@ -727,16 +723,6 @@ impl ApiSet { public_list.insert(Api::ParityAccounts); public_list } - ApiSet::SafeContext => { - public_list.insert(Api::Debug); - public_list.insert(Api::Traces); - public_list.insert(Api::ParityPubSub); - public_list.insert(Api::ParityAccounts); - public_list.insert(Api::ParitySet); - public_list.insert(Api::Signer); - public_list.insert(Api::SecretStore); - public_list - } ApiSet::All => { public_list.insert(Api::Debug); public_list.insert(Api::Traces); @@ -842,33 +828,6 @@ mod test { assert_eq!(ApiSet::IpcContext.list_apis(), expected); } - #[test] - fn test_api_set_safe_context() { - let expected = vec![ - // safe - Api::Web3, - Api::Net, - Api::Eth, - Api::EthPubSub, - Api::Parity, - Api::ParityPubSub, - Api::Traces, - Api::Rpc, - Api::SecretStore, - Api::Whisper, - Api::WhisperPubSub, - Api::Private, - // semi-safe - Api::ParityAccounts, - // Unsafe - Api::ParitySet, - Api::Signer, - Api::Debug, - ].into_iter() - .collect(); - assert_eq!(ApiSet::SafeContext.list_apis(), expected); - } - #[test] fn test_all_apis() { assert_eq!( diff --git a/parity/run.rs b/parity/run.rs index 2654e1450e..fe8f1d516b 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -22,29 +22,28 @@ use std::thread; use ansi_term::Colour; use bytes::Bytes; use call_contract::CallContract; -use ethcore::account_provider::{AccountProvider, AccountProviderSettings}; use ethcore::client::{BlockId, Client, Mode, DatabaseCompactionProfile, VMType, BlockChainClient, BlockInfo}; -use ethstore::ethkey; -use ethcore::miner::{stratum, Miner, MinerService, MinerOptions}; +use ethcore::miner::{self, stratum, Miner, MinerService, MinerOptions}; use ethcore::snapshot::{self, SnapshotConfiguration}; use ethcore::spec::{SpecParams, OptimizeFor}; use ethcore::verification::queue::VerifierSettings; use ethcore_logger::{Config as LogConfig, RotatingLogger}; use ethcore_service::ClientService; use ethereum_types::Address; -use sync::{self, SyncConfig, PrivateTxHandler}; -use miner::work_notify::WorkPoster; use futures::IntoFuture; use hash_fetch::{self, fetch}; use informant::{Informant, LightNodeInformantData, FullNodeInformantData}; use journaldb::Algorithm; use light::Cache as LightDataCache; use miner::external::ExternalMiner; +use miner::work_notify::WorkPoster; use node_filter::NodeFilter; use parity_rabbitmq::client::{PubSubClient, RabbitMqConfig}; use parity_runtime::Runtime; -use parity_rpc::{Origin, Metadata, NetworkSettings, informant, is_major_importing, PubSubSession, FutureResult, - FutureResponse, FutureOutput}; +use sync::{self, SyncConfig, PrivateTxHandler}; +use parity_rpc::{ + Origin, Metadata, NetworkSettings, informant, is_major_importing, PubSubSession, FutureResult, FutureResponse, FutureOutput +}; use updater::{UpdatePolicy, Updater}; use parity_version::version; use ethcore_private_tx::{ProviderConfig, EncryptorConfig, SecretStoreEncryptor}; @@ -52,8 +51,8 @@ use params::{ SpecType, Pruning, AccountsConfig, GasPricerConfig, MinerExtras, Switch, tracing_switch_to_bool, fatdb_switch_to_bool, mode_switch_to_bool }; +use account_utils; use helpers::{to_client_config, execute_upgrades, passwords_from_files}; -use upgrade::upgrade_key_location; use dir::{Directories, DatabaseDirectories}; use cache::CacheConfig; use user_defaults::UserDefaults; @@ -66,7 +65,6 @@ use rpc_apis; use secretstore; use signer; use db; -use ethkey::Password; // how often to take periodic snapshots. const SNAPSHOT_PERIOD: u64 = 5000; @@ -78,9 +76,6 @@ const SNAPSHOT_HISTORY: u64 = 100; // Light client only. const GAS_CORPUS_EXPIRATION_MINUTES: u64 = 60 * 6; -// Pops along with error messages when a password is missing or invalid. -const VERIFY_PASSWORD_HINT: &str = "Make sure valid password is present in files passed using `--password` or in the configuration file."; - // Full client number of DNS threads const FETCH_FULL_NUM_DNS_THREADS: usize = 4; @@ -172,7 +167,9 @@ impl ::local_store::NodeInfo for FullNodeInfo { type LightClient = ::light::client::Client<::light_helpers::EpochFetch>; // helper for light execution. -fn execute_light_impl(cmd: RunCmd, logger: Arc) -> Result { +fn execute_light_impl(cmd: RunCmd, logger: Arc, on_client_rq: Cr) -> Result + where Cr: Fn(String) + 'static + Send +{ use light::client as light_client; use sync::{LightSyncParams, LightSync, ManageNetwork}; use parking_lot::{Mutex, RwLock}; @@ -300,17 +297,6 @@ fn execute_light_impl(cmd: RunCmd, logger: Arc) -> Result) -> Result) -> Result) -> Result(cmd: RunCmd, logger: Arc, on_client_rq: let passwords = passwords_from_files(&cmd.acc_conf.password_files)?; - // Run in daemon mode. - // Note, that it should be called before we leave any file descriptor open, - // since `daemonize` will close them. - if let Some(pid_file) = cmd.daemon { - info!("Running as a daemon process!"); - daemonize(pid_file)?; - } - // prepare account provider - let account_provider = Arc::new(prepare_account_provider(&cmd.spec, &cmd.dirs, &spec.data_dir, cmd.acc_conf, &passwords)?); + let account_provider = Arc::new(account_utils::prepare_account_provider(&cmd.spec, &cmd.dirs, &spec.data_dir, cmd.acc_conf, &passwords)?); // spin up event loop let runtime = Runtime::with_default_thread_count(); @@ -513,9 +493,12 @@ fn execute_impl(cmd: RunCmd, logger: Arc, on_client_rq: cmd.miner_options, cmd.gas_pricer_conf.to_gas_pricer(fetch.clone(), runtime.executor()), &spec, - Some(account_provider.clone()), + ( + cmd.miner_extras.local_accounts, + account_utils::miner_local_accounts(account_provider.clone()), + ) )); - miner.set_author(cmd.miner_extras.author, None).expect("Fails only if password is Some; password is None; qed"); + miner.set_author(miner::Author::External(cmd.miner_extras.author)); miner.set_gas_range_target(cmd.miner_extras.gas_range_target); miner.set_extra_data(cmd.miner_extras.extra_data); @@ -527,19 +510,8 @@ fn execute_impl(cmd: RunCmd, logger: Arc, on_client_rq: let engine_signer = cmd.miner_extras.engine_signer; if engine_signer != Default::default() { - // Check if engine signer exists - if !account_provider.has_account(engine_signer) { - return Err(format!("Consensus signer account not found for the current chain. {}", build_create_account_hint(&cmd.spec, &cmd.dirs.keys))); - } - - // Check if any passwords have been read from the password file(s) - if passwords.is_empty() { - return Err(format!("No password found for the consensus signer {}. {}", engine_signer, VERIFY_PASSWORD_HINT)); - } - - // Attempt to sign in the engine signer. - if !passwords.iter().any(|p| miner.set_author(engine_signer, Some(p.to_owned())).is_ok()) { - return Err(format!("No valid password for the consensus signer {}. {}", engine_signer, VERIFY_PASSWORD_HINT)); + if let Some(author) = account_utils::miner_author(&cmd.spec, &cmd.dirs, &account_provider, engine_signer, &passwords)? { + miner.set_author(author); } } @@ -582,6 +554,8 @@ fn execute_impl(cmd: RunCmd, logger: Arc, on_client_rq: let client_db = restoration_db_handler.open(&client_path) .map_err(|e| format!("Failed to open database {:?}", e))?; + let private_tx_signer = account_utils::private_tx_signer(account_provider.clone(), &passwords)?; + // create client service. let service = ClientService::start( client_config, @@ -591,9 +565,10 @@ fn execute_impl(cmd: RunCmd, logger: Arc, on_client_rq: restoration_db_handler, &cmd.dirs.ipc_path(), miner.clone(), - account_provider.clone(), - Box::new(SecretStoreEncryptor::new(cmd.private_encryptor_conf, fetch.clone()).map_err(|e| e.to_string())?), + private_tx_signer.clone(), + Box::new(SecretStoreEncryptor::new(cmd.private_encryptor_conf.clone(), fetch.clone(), private_tx_signer).map_err(|e| e.to_string())?), cmd.private_provider_conf, + cmd.private_encryptor_conf, ).map_err(|e| format!("Client service error: {:?}", e))?; let connection_filter_address = spec.params().node_permission_contract; @@ -752,7 +727,7 @@ fn execute_impl(cmd: RunCmd, logger: Arc, on_client_rq: client: client.clone(), sync: sync_provider.clone(), net: manage_network.clone(), - secret_store: secret_store, + accounts: secret_store, miner: miner.clone(), external_miner: external_miner.clone(), logger: logger.clone(), @@ -769,6 +744,7 @@ fn execute_impl(cmd: RunCmd, logger: Arc, on_client_rq: gas_price_percentile: cmd.gas_price_percentile, poll_lifetime: cmd.poll_lifetime, allow_missing_blocks: cmd.allow_missing_blocks, + no_ancient_blocks: !cmd.download_old_blocks, }); let dependencies = rpc::Dependencies { @@ -794,7 +770,7 @@ fn execute_impl(cmd: RunCmd, logger: Arc, on_client_rq: client: client.clone(), sync: sync_provider.clone(), miner: miner.clone(), - account_provider: account_provider, + account_provider, accounts_passwords: &passwords, }; let secretstore_key_server = secretstore::start(cmd.secretstore_conf.clone(), secretstore_deps, runtime.executor())?; @@ -925,17 +901,27 @@ impl RunningClient { // Create a weak reference to the client so that we can wait on shutdown // until it is dropped let weak_client = Arc::downgrade(&client); - // Shutdown and drop the ServiceClient + // Shutdown and drop the ClientService client_service.shutdown(); + trace!(target: "shutdown", "ClientService shut down"); drop(client_service); + trace!(target: "shutdown", "ClientService dropped"); // drop this stuff as soon as exit detected. drop(rpc); + trace!(target: "shutdown", "RPC dropped"); drop(keep_alive); + trace!(target: "shutdown", "KeepAlive dropped"); // to make sure timer does not spawn requests while shutdown is in progress informant.shutdown(); + trace!(target: "shutdown", "Informant shut down"); // just Arc is dropping here, to allow other reference release in its default time drop(informant); + trace!(target: "shutdown", "Informant dropped"); drop(client); + trace!(target: "shutdown", "Client dropped"); + // This may help when debugging ref cycles. Requires nightly-only `#![feature(weak_counts)]` + // trace!(target: "shutdown", "Waiting for refs to Client to shutdown, strong_count={:?}, weak_count={:?}", weak_client.strong_count(), weak_client.weak_count()); + trace!(target: "shutdown", "Waiting for refs to Client to shutdown"); wait_for_drop(weak_client); } } @@ -956,129 +942,45 @@ pub fn execute(cmd: RunCmd, logger: Arc, Rr: Fn() + 'static + Send { if cmd.light { - execute_light_impl(cmd, logger) + execute_light_impl(cmd, logger, on_client_rq) } else { execute_impl(cmd, logger, on_client_rq, on_updater_rq) } } -#[cfg(not(windows))] -fn daemonize(pid_file: String) -> Result<(), String> { - extern crate daemonize; - - daemonize::Daemonize::new() - .pid_file(pid_file) - .chown_pid_file(true) - .start() - .map(|_| ()) - .map_err(|e| format!("Couldn't daemonize; {}", e)) -} - -#[cfg(windows)] -fn daemonize(_pid_file: String) -> Result<(), String> { - Err("daemon is no supported on windows".into()) -} - fn print_running_environment(data_dir: &str, dirs: &Directories, db_dirs: &DatabaseDirectories) { info!("Starting {}", Colour::White.bold().paint(version())); info!("Keys path {}", Colour::White.bold().paint(dirs.keys_path(data_dir).to_string_lossy().into_owned())); info!("DB path {}", Colour::White.bold().paint(db_dirs.db_root_path().to_string_lossy().into_owned())); } -fn prepare_account_provider(spec: &SpecType, dirs: &Directories, data_dir: &str, cfg: AccountsConfig, passwords: &[Password]) -> Result { - use ethstore::EthStore; - use ethstore::accounts_dir::RootDiskDirectory; - - let path = dirs.keys_path(data_dir); - upgrade_key_location(&dirs.legacy_keys_path(cfg.testnet), &path); - let dir = Box::new(RootDiskDirectory::create(&path).map_err(|e| format!("Could not open keys directory: {}", e))?); - let account_settings = AccountProviderSettings { - enable_hardware_wallets: cfg.enable_hardware_wallets, - hardware_wallet_classic_key: spec == &SpecType::Classic, - unlock_keep_secret: cfg.enable_fast_unlock, - blacklisted_accounts: match *spec { - SpecType::Morden | SpecType::Ropsten | SpecType::Kovan | SpecType::Sokol | SpecType::Dev => vec![], - _ => vec![ - "00a329c0648769a73afac7f9381e08fb43dbea72".into() - ], - }, - }; - - let ethstore = EthStore::open_with_iterations(dir, cfg.iterations).map_err(|e| format!("Could not open keys directory: {}", e))?; - if cfg.refresh_time > 0 { - ethstore.set_refresh_time(::std::time::Duration::from_secs(cfg.refresh_time)); - } - let account_provider = AccountProvider::new( - Box::new(ethstore), - account_settings, - ); - - // Add development account if running dev chain: - if let SpecType::Dev = *spec { - insert_dev_account(&account_provider); - } - - for a in cfg.unlocked_accounts { - // Check if the account exists - if !account_provider.has_account(a) { - return Err(format!("Account {} not found for the current chain. {}", a, build_create_account_hint(spec, &dirs.keys))); - } - - // Check if any passwords have been read from the password file(s) - if passwords.is_empty() { - return Err(format!("No password found to unlock account {}. {}", a, VERIFY_PASSWORD_HINT)); - } - - if !passwords.iter().any(|p| account_provider.unlock_account_permanently(a, (*p).clone()).is_ok()) { - return Err(format!("No valid password to unlock account {}. {}", a, VERIFY_PASSWORD_HINT)); - } - } - - Ok(account_provider) -} - -fn insert_dev_account(account_provider: &AccountProvider) { - let secret: ethkey::Secret = "4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7".into(); - let dev_account = ethkey::KeyPair::from_secret(secret.clone()).expect("Valid secret produces valid key;qed"); - if !account_provider.has_account(dev_account.address()) { - match account_provider.insert_account(secret, &Password::from(String::new())) { - Err(e) => warn!("Unable to add development account: {}", e), - Ok(address) => { - let _ = account_provider.set_account_name(address.clone(), "Development Account".into()); - let _ = account_provider.set_account_meta(address, ::serde_json::to_string(&(vec![ - ("description", "Never use this account outside of development chain!"), - ("passwordHint","Password is empty string"), - ].into_iter().collect::<::std::collections::HashMap<_,_>>())).expect("Serialization of hashmap does not fail.")); - }, - } - } -} - -// Construct an error `String` with an adaptive hint on how to create an account. -fn build_create_account_hint(spec: &SpecType, keys: &str) -> String { - format!("You can create an account via RPC, UI or `parity account new --chain {} --keys-path {}`.", spec, keys) -} - fn wait_for_drop(w: Weak) { - let sleep_duration = Duration::from_secs(1); - let warn_timeout = Duration::from_secs(60); - let max_timeout = Duration::from_secs(300); + const SLEEP_DURATION: Duration = Duration::from_secs(1); + const WARN_TIMEOUT: Duration = Duration::from_secs(60); + const MAX_TIMEOUT: Duration = Duration::from_secs(300); let instant = Instant::now(); let mut warned = false; - while instant.elapsed() < max_timeout { + while instant.elapsed() < MAX_TIMEOUT { if w.upgrade().is_none() { return; } - if !warned && instant.elapsed() > warn_timeout { + if !warned && instant.elapsed() > WARN_TIMEOUT { warned = true; warn!("Shutdown is taking longer than expected."); } - thread::sleep(sleep_duration); + thread::sleep(SLEEP_DURATION); + + // When debugging shutdown issues on a nightly build it can help to enable this with the + // `#![feature(weak_counts)]` added to lib.rs (TODO: enable when + // https://github.com/rust-lang/rust/issues/57977 is stable) + // trace!(target: "shutdown", "Waiting for client to drop, strong_count={:?}, weak_count={:?}", w.strong_count(), w.weak_count()); + trace!(target: "shutdown", "Waiting for client to drop"); } warn!("Shutdown timeout reached, exiting uncleanly."); } + diff --git a/parity/secretstore.rs b/parity/secretstore.rs index c61d4b76cb..d9075edec8 100644 --- a/parity/secretstore.rs +++ b/parity/secretstore.rs @@ -16,12 +16,12 @@ use std::collections::BTreeMap; use std::sync::Arc; +use account_utils::AccountProvider; use dir::default_data_path; use dir::helpers::replace_home; -use ethcore::account_provider::AccountProvider; use ethcore::client::Client; use ethcore::miner::Miner; -use ethkey::{Secret, Public}; +use ethkey::{Secret, Public, Password}; use sync::SyncProvider; use ethereum_types::Address; use parity_runtime::Executor; @@ -32,6 +32,7 @@ pub enum NodeSecretKey { /// Stored as plain text in configuration file. Plain(Secret), /// Stored as account in key store. + #[cfg(feature = "accounts")] KeyStore(Address), } @@ -141,6 +142,7 @@ mod server { let self_secret: Arc = match conf.self_secret.take() { Some(NodeSecretKey::Plain(secret)) => Arc::new(ethcore_secretstore::PlainNodeKeyPair::new( KeyPair::from_secret(secret).map_err(|e| format!("invalid secret: {}", e))?)), + #[cfg(feature = "accounts")] Some(NodeSecretKey::KeyStore(account)) => { // Check if account exists if !deps.account_provider.has_account(account.clone()) { @@ -209,7 +211,6 @@ mod server { } pub use self::server::KeyServer; -use ethkey::Password; impl Default for Configuration { fn default() -> Self { diff --git a/parity/snapshot.rs b/parity/snapshot.rs index 0be4ce15f7..269965c335 100644 --- a/parity/snapshot.rs +++ b/parity/snapshot.rs @@ -21,7 +21,6 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use hash::keccak; -use ethcore::account_provider::AccountProvider; use ethcore::snapshot::{Progress, RestorationStatus, SnapshotConfiguration, SnapshotService as SS}; use ethcore::snapshot::io::{SnapshotReader, PackedReader, PackedWriter}; use ethcore::snapshot::service::Service as SnapshotService; @@ -199,9 +198,10 @@ impl SnapshotCommand { // TODO [ToDr] don't use test miner here // (actually don't require miner at all) Arc::new(Miner::new_for_tests(&spec, None)), - Arc::new(AccountProvider::transient_provider()), + Arc::new(ethcore_private_tx::DummySigner), Box::new(ethcore_private_tx::NoopEncryptor), Default::default(), + Default::default(), ).map_err(|e| format!("Client service error: {:?}", e))?; Ok(service) @@ -261,7 +261,7 @@ impl SnapshotCommand { let cur_size = p.size(); if cur_size != last_size { last_size = cur_size; - let bytes = ::informant::format_bytes(p.size()); + let bytes = ::informant::format_bytes(cur_size as usize); info!("Snapshot: {} accounts {} blocks {}", p.accounts(), p.blocks(), bytes); } diff --git a/parity/upgrade.rs b/parity/upgrade.rs index 3406e573c7..ecd9beff16 100644 --- a/parity/upgrade.rs +++ b/parity/upgrade.rs @@ -28,9 +28,9 @@ use journaldb::Algorithm; #[derive(Debug)] pub enum Error { - CannotCreateConfigPath, - CannotWriteVersionFile, - CannotUpdateVersionFile, + CannotCreateConfigPath(io::Error), + CannotWriteVersionFile(io::Error), + CannotUpdateVersionFile(io::Error), SemVer(SemVerError), } @@ -105,7 +105,7 @@ fn with_locked_version(db_path: &str, script: F) -> Result where F: Fn(&Version) -> Result { let mut path = PathBuf::from(db_path); - create_dir_all(&path).map_err(|_| Error::CannotCreateConfigPath)?; + create_dir_all(&path).map_err(Error::CannotCreateConfigPath)?; path.push("ver.lock"); let version = @@ -118,11 +118,11 @@ fn with_locked_version(db_path: &str, script: F) -> Result }) .unwrap_or(Version::new(0, 9, 0)); - let mut lock = File::create(&path).map_err(|_| Error::CannotWriteVersionFile)?; + let mut lock = File::create(&path).map_err(Error::CannotWriteVersionFile)?; let result = script(&version); let written_version = Version::parse(CURRENT_VERSION)?; - lock.write_all(written_version.to_string().as_bytes()).map_err(|_| Error::CannotUpdateVersionFile)?; + lock.write_all(written_version.to_string().as_bytes()).map_err(Error::CannotUpdateVersionFile)?; result } @@ -139,6 +139,7 @@ fn file_exists(path: &Path) -> bool { } } +#[cfg(any(test, feature = "accounts"))] pub fn upgrade_key_location(from: &PathBuf, to: &PathBuf) { match fs::create_dir_all(&to).and_then(|()| fs::read_dir(from)) { Ok(entries) => { diff --git a/rabbitmq/Cargo.toml b/rabbitmq/Cargo.toml index 519bca715a..2d763a43c9 100644 --- a/rabbitmq/Cargo.toml +++ b/rabbitmq/Cargo.toml @@ -13,7 +13,7 @@ rustc-hex = "1.0" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -tokio = "^0.1" +tokio = "0.1.19" enclose = "0.1.4" ethcore = { path = "../ethcore", features = ["test-helpers"] } diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index a04ca970b7..e95c48cb96 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -1,5 +1,5 @@ [package] -description = "Parity JSON-RPC servers." +description = "Parity Ethereum JSON-RPC Servers (WS, HTTP, IPC)" name = "parity-rpc" version = "1.12.0" license = "GPL-3.0" @@ -27,27 +27,29 @@ tokio-timer = "0.1" transient-hashmap = "0.4" itertools = "0.5" -jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } -jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } -jsonrpc-ws-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } -jsonrpc-ipc-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } -jsonrpc-macros = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } -jsonrpc-pubsub = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } +jsonrpc-core = "10.0.1" +jsonrpc-derive = "10.0.2" +jsonrpc-http-server = "10.0.1" +jsonrpc-ws-server = "10.0.1" +jsonrpc-ipc-server = "10.0.1" +jsonrpc-pubsub = "10.0.1" common-types = { path = "../ethcore/types" } ethash = { path = "../ethash" } -ethcore = { path = "../ethcore", features = ["test-helpers"] } -fastmap = { path = "../util/fastmap" } -parity-bytes = "0.1" -parity-crypto = "0.2" -ethcore-io = { path = "../util/io" } +ethcore = { path = "../ethcore" } +ethcore-accounts = { path = "../accounts", optional = true } ethcore-light = { path = "../ethcore/light" } ethcore-logger = { path = "../parity/logger" } ethcore-miner = { path = "../miner" } +ethcore-network = { path = "../util/network" } ethcore-private-tx = { path = "../ethcore/private-tx" } ethcore-sync = { path = "../ethcore/sync" } ethereum-types = "0.4" +fastmap = { path = "../util/fastmap" } +parity-bytes = "0.1" +parity-crypto = "0.3.0" +eip-712 = { path = "../util/EIP-712" } ethjson = { path = "../json" } ethkey = { path = "../accounts/ethkey" } ethstore = { path = "../accounts/ethstore" } @@ -56,23 +58,19 @@ keccak-hash = "0.1.2" parity-runtime = { path = "../util/runtime" } parity-updater = { path = "../updater" } parity-version = { path = "../util/version" } -patricia-trie = "0.3.0" rlp = { version = "0.3.0", features = ["ethereum"] } -eip-712 = { path = "../util/EIP-712" } stats = { path = "../util/stats" } vm = { path = "../ethcore/vm" } -[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))'.dependencies] -hardware-wallet = { path = "../accounts/hw" } - -[target.'cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))'.dependencies] -fake-hardware-wallet = { path = "../accounts/fake-hardware-wallet" } - [dev-dependencies] ethcore = { path = "../ethcore", features = ["test-helpers"] } +ethcore-accounts = { path = "../accounts" } +ethcore-io = { path = "../util/io" } ethcore-network = { path = "../util/network" } fake-fetch = { path = "../util/fake-fetch" } -kvdb-memorydb = "0.1" macros = { path = "../util/macros" } pretty_assertions = "0.1" -transaction-pool = "1.13" +transaction-pool = "2.0.1" + +[features] +accounts = ["ethcore-accounts"] diff --git a/rpc/src/authcodes.rs b/rpc/src/authcodes.rs index 976ce1a3fb..b348dfd729 100644 --- a/rpc/src/authcodes.rs +++ b/rpc/src/authcodes.rs @@ -51,7 +51,7 @@ const TIME_THRESHOLD: u64 = 7; /// minimal length of hash const TOKEN_LENGTH: usize = 16; /// Separator between fields in serialized tokens file. -const SEPARATOR: &'static str = ";"; +const SEPARATOR: &str = ";"; /// Number of seconds to keep unused tokens. const UNUSED_TOKEN_TIMEOUT: u64 = 3600 * 24; // a day @@ -115,7 +115,7 @@ impl AuthCodes { }) .collect(); Ok(AuthCodes { - codes: codes, + codes, now: time_provider, }) } @@ -128,7 +128,7 @@ impl AuthCodes { pub fn to_file(&self, file: &Path) -> io::Result<()> { let mut file = fs::File::create(file)?; let content = self.codes.iter().map(|code| { - let mut data = vec![code.code.clone(), encode_time(code.created_at.clone())]; + let mut data = vec![code.code.clone(), encode_time(code.created_at)]; if let Some(used_at) = code.last_used_at { data.push(encode_time(used_at)); } @@ -141,11 +141,11 @@ impl AuthCodes { pub fn new(codes: Vec, now: T) -> Self { AuthCodes { codes: codes.into_iter().map(|code| Code { - code: code, + code, created_at: time::Duration::from_secs(now.now()), last_used_at: None, }).collect(), - now: now, + now, } } @@ -183,7 +183,7 @@ impl AuthCodes { .join("-"); trace!(target: "signer", "New authentication token generated."); self.codes.push(Code { - code: code, + code, created_at: time::Duration::from_secs(self.now.now()), last_used_at: None, }); diff --git a/rpc/src/http_common.rs b/rpc/src/http_common.rs index 517bbbf760..99bd392f35 100644 --- a/rpc/src/http_common.rs +++ b/rpc/src/http_common.rs @@ -44,7 +44,7 @@ impl http::MetaExtractor for MetaExtractor where { fn read_metadata(&self, req: &hyper::Request) -> M { let as_string = |header: Option<&hyper::header::HeaderValue>| { - header.and_then(|val| val.to_str().ok().map(|s| s.to_owned())) + header.and_then(|val| val.to_str().ok().map(ToOwned::to_owned)) }; let origin = as_string(req.headers().get("origin")); diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index a72e5e1837..6c0ce2a011 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -14,9 +14,28 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -//! Parity RPC. - -#![warn(missing_docs)] +//! Parity Ethereum JSON-RPC Servers (WS, HTTP, IPC). + +#![warn(missing_docs, unused_extern_crates)] +#![cfg_attr(feature = "cargo-clippy", warn(clippy::all, clippy::pedantic))] +#![cfg_attr( + feature = "cargo-clippy", + allow( + // things are often more readable this way + clippy::cast_lossless, + clippy::module_name_repetitions, + clippy::single_match_else, + clippy::type_complexity, + clippy::use_self, + // not practical + clippy::match_bool, + clippy::needless_pass_by_value, + clippy::similar_names, + // don't require markdown syntax for docs + clippy::doc_markdown, + ), + warn(clippy::indexing_slicing) +)] #[macro_use] extern crate futures; @@ -32,11 +51,11 @@ extern crate rustc_hex; extern crate semver; extern crate serde; extern crate serde_json; -extern crate tiny_keccak; extern crate tokio_timer; extern crate transient_hashmap; extern crate jsonrpc_core; +extern crate jsonrpc_derive; extern crate jsonrpc_http_server as http; extern crate jsonrpc_ipc_server as ipc; extern crate jsonrpc_pubsub; @@ -47,10 +66,10 @@ extern crate ethcore; extern crate fastmap; extern crate parity_bytes as bytes; extern crate parity_crypto as crypto; -extern crate ethcore_io as io; extern crate ethcore_light as light; extern crate ethcore_logger; extern crate ethcore_miner as miner; +extern crate ethcore_network as network; extern crate ethcore_private_tx; extern crate ethcore_sync as sync; extern crate ethereum_types; @@ -61,22 +80,21 @@ extern crate keccak_hash as hash; extern crate parity_runtime; extern crate parity_updater as updater; extern crate parity_version as version; -extern crate patricia_trie as trie; extern crate eip_712; extern crate rlp; extern crate stats; +extern crate tempdir; extern crate vm; -#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))] -extern crate hardware_wallet; -#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))] -extern crate fake_hardware_wallet as hardware_wallet; +#[cfg(any(test, feature = "ethcore-accounts"))] +extern crate ethcore_accounts as accounts; + +#[cfg(any(test, feature = "ethcore-accounts"))] +extern crate tiny_keccak; #[macro_use] extern crate log; #[macro_use] -extern crate jsonrpc_macros; -#[macro_use] extern crate serde_derive; #[cfg(test)] @@ -92,13 +110,11 @@ extern crate pretty_assertions; #[macro_use] extern crate macros; -#[cfg(test)] -extern crate kvdb_memorydb; - #[cfg(test)] extern crate fake_fetch; -extern crate tempdir; +#[cfg(test)] +extern crate ethcore_io as io; pub extern crate jsonrpc_ws_server as ws; @@ -114,7 +130,7 @@ pub use ipc::{Server as IpcServer, MetaExtractor as IpcMetaExtractor, RequestCon pub use http::{ hyper, RequestMiddleware, RequestMiddlewareAction, - AccessControlAllowOrigin, Host, DomainsValidation + AccessControlAllowOrigin, Host, DomainsValidation, cors::AccessControlAllowHeaders }; pub use v1::{NetworkSettings, Metadata, Origin, informant, dispatch, signer}; @@ -148,9 +164,10 @@ pub fn start_http( Ok(http::ServerBuilder::with_meta_extractor(handler, extractor) .keep_alive(keep_alive) .threads(threads) - .cors(cors_domains.into()) - .allowed_hosts(allowed_hosts.into()) + .cors(cors_domains) + .allowed_hosts(allowed_hosts) .health_api(("/api/health", "parity_nodeStatus")) + .cors_allow_headers(AccessControlAllowHeaders::Any) .max_request_body_size(max_payload * 1024 * 1024) .start_http(addr)?) } @@ -178,8 +195,9 @@ pub fn start_http_with_middleware( Ok(http::ServerBuilder::with_meta_extractor(handler, extractor) .keep_alive(keep_alive) .threads(threads) - .cors(cors_domains.into()) - .allowed_hosts(allowed_hosts.into()) + .cors(cors_domains) + .allowed_hosts(allowed_hosts) + .cors_allow_headers(AccessControlAllowHeaders::Any) .max_request_body_size(max_payload * 1024 * 1024) .request_middleware(middleware) .start_http(addr)?) diff --git a/rpc/src/tests/helpers.rs b/rpc/src/tests/helpers.rs index fe04906d4a..301d77e91c 100644 --- a/rpc/src/tests/helpers.rs +++ b/rpc/src/tests/helpers.rs @@ -39,7 +39,7 @@ impl Server { Server { server: f(remote), - event_loop: event_loop, + event_loop, } } } @@ -60,8 +60,8 @@ pub struct GuardedAuthCodes { pub path: PathBuf, } -impl GuardedAuthCodes { - pub fn new() -> Self { +impl Default for GuardedAuthCodes { + fn default() -> Self { let tempdir = TempDir::new("").unwrap(); let path = tempdir.path().join("file"); diff --git a/rpc/src/tests/http_client.rs b/rpc/src/tests/http_client.rs index 7720f4254b..0588c791e7 100644 --- a/rpc/src/tests/http_client.rs +++ b/rpc/src/tests/http_client.rs @@ -30,7 +30,7 @@ pub struct Response { impl Response { pub fn assert_header(&self, header: &str, value: &str) { let header = format!("{}: {}", header, value); - assert!(self.headers.iter().find(|h| *h == &header).is_some(), "Couldn't find header {} in {:?}", header, &self.headers) + assert!(self.headers.iter().any(|h| h == &header), "Couldn't find header {} in {:?}", header, &self.headers) } pub fn assert_status(&self, status: &str) { @@ -98,35 +98,35 @@ pub fn request(address: &SocketAddr, request: &str) -> Response { let mut lines = response.lines(); let status = lines.next().expect("Expected a response").to_owned(); let headers_raw = read_block(&mut lines, false); - let headers = headers_raw.split('\n').map(|v| v.to_owned()).collect(); + let headers = headers_raw.split('\n').map(ToOwned::to_owned).collect(); let body = read_block(&mut lines, true); Response { - status: status, - headers: headers, - headers_raw: headers_raw, - body: body, + status, + headers, + headers_raw, + body, } } /// Check if all required security headers are present pub fn assert_security_headers_present(headers: &[String], port: Option) { - if let None = port { + if port.is_none() { assert!( - headers.iter().find(|header| header.as_str() == "X-Frame-Options: SAMEORIGIN").is_some(), + headers.iter().any(|header| header.as_str() == "X-Frame-Options: SAMEORIGIN") "X-Frame-Options: SAMEORIGIN missing: {:?}", headers ); } assert!( - headers.iter().find(|header| header.as_str() == "X-XSS-Protection: 1; mode=block").is_some(), + headers.iter().any(|header| header.as_str() == "X-XSS-Protection: 1; mode=block") "X-XSS-Protection missing: {:?}", headers ); assert!( - headers.iter().find(|header| header.as_str() == "X-Content-Type-Options: nosniff").is_some(), + headers.iter().any(|header| header.as_str() == "X-Content-Type-Options: nosniff") "X-Content-Type-Options missing: {:?}", headers ); assert!( - headers.iter().find(|header| header.starts_with("Content-Security-Policy: ")).is_some(), + headers.iter().any(|header| header.starts_with("Content-Security-Policy: ")) "Content-Security-Policy missing: {:?}", headers ) } diff --git a/rpc/src/tests/rpc.rs b/rpc/src/tests/rpc.rs index 761ccc4e1f..99498c3e5d 100644 --- a/rpc/src/tests/rpc.rs +++ b/rpc/src/tests/rpc.rs @@ -116,4 +116,31 @@ mod tests { res.assert_status("HTTP/1.1 200 OK"); assert_eq!(res.body, expected); } + + #[test] + fn should_respond_valid_to_any_requested_header() { + // given + let (server, address) = serve(); + let headers = "Something, Anything, Xyz, 123, _?"; + + // when + let res = request(server, + &format!("\ + OPTIONS / HTTP/1.1\r\n\ + Host: {}\r\n\ + Origin: http://parity.io\r\n\ + Content-Length: 0\r\n\ + Content-Type: application/json\r\n\ + Connection: close\r\n\ + Access-Control-Request-Headers: {}\r\n\ + \r\n\ + ", address, headers) + ); + + // then + assert_eq!(res.status, "HTTP/1.1 200 OK".to_owned()); + let expected = format!("access-control-allow-headers: {}", headers); + assert!(res.headers.contains(&expected), "Headers missing in {:?}", res.headers); + } + } diff --git a/rpc/src/tests/ws.rs b/rpc/src/tests/ws.rs index aded13953c..3b60788820 100644 --- a/rpc/src/tests/ws.rs +++ b/rpc/src/tests/ws.rs @@ -29,7 +29,7 @@ use tests::http_client; pub fn serve() -> (Server, usize, GuardedAuthCodes) { let address = "127.0.0.1:0".parse().unwrap(); let io = MetaIoHandler::default(); - let authcodes = GuardedAuthCodes::new(); + let authcodes = GuardedAuthCodes::default(); let stats = Arc::new(informant::RpcStats::default()); let res = Server::new(|_| ::start_ws( @@ -75,7 +75,7 @@ mod testing { ); // then - assert_eq!(response.status, "HTTP/1.1 200 Ok".to_owned()); + assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); } #[test] diff --git a/rpc/src/v1/extractors.rs b/rpc/src/v1/extractors.rs index 9c47b3e6a4..d3384c2c1d 100644 --- a/rpc/src/v1/extractors.rs +++ b/rpc/src/v1/extractors.rs @@ -41,8 +41,8 @@ impl HttpMetaExtractor for RpcExtractor { Metadata { origin: Origin::Rpc( format!("{} / {}", - origin.unwrap_or("unknown origin".to_string()), - user_agent.unwrap_or("unknown agent".to_string())) + origin.unwrap_or_else(|| "unknown origin".to_string()), + user_agent.unwrap_or_else(|| "unknown agent".to_string())) ), session: None, } @@ -67,7 +67,7 @@ impl WsExtractor { /// Creates new `WsExtractor` with given authcodes path. pub fn new(path: Option<&Path>) -> Self { WsExtractor { - authcodes_path: path.map(|p| p.to_owned()), + authcodes_path: path.map(ToOwned::to_owned), } } } @@ -80,7 +80,7 @@ impl ws::MetaExtractor for WsExtractor { Some(ref path) => { let authorization = req.protocols.get(0).and_then(|p| auth_token_hash(&path, p, true)); match authorization { - Some(id) => Origin::Signer { session: id.into() }, + Some(id) => Origin::Signer { session: id }, None => Origin::Ws { session: id.into() }, } }, @@ -98,16 +98,16 @@ impl ws::RequestMiddleware for WsExtractor { fn process(&self, req: &ws::ws::Request) -> ws::MiddlewareAction { use self::ws::ws::Response; - // Reply with 200 Ok to HEAD requests. + // Reply with 200 OK to HEAD requests. if req.method() == "HEAD" { - let mut response = Response::new(200, "Ok", vec![]); + let mut response = Response::new(200, "OK", vec![]); add_security_headers(&mut response); return Some(response).into(); } // Display WS info. if req.header("sec-websocket-key").is_none() { - let mut response = Response::new(200, "Ok", b"WebSocket interface is active. Open WS connection to access RPC.".to_vec()); + let mut response = Response::new(200, "OK", b"WebSocket interface is active. Open WS connection to access RPC.".to_vec()); add_security_headers(&mut response); return Some(response).into(); } @@ -186,7 +186,7 @@ impl WsStats { /// Creates new WS usage tracker. pub fn new(stats: Arc) -> Self { WsStats { - stats: stats, + stats, } } } @@ -210,7 +210,7 @@ impl> WsDispatcher { /// Create new `WsDispatcher` with given full handler. pub fn new(full_handler: core::MetaIoHandler) -> Self { WsDispatcher { - full_handler: full_handler, + full_handler, } } } @@ -229,7 +229,7 @@ impl> core::Middleware for WsDispatcher< X: core::futures::Future, Error=()> + Send + 'static, { let use_full = match &meta.origin { - &Origin::Signer { .. } => true, + Origin::Signer { .. } => true, _ => false, }; diff --git a/rpc/src/v1/helpers/deprecated.rs b/rpc/src/v1/helpers/deprecated.rs new file mode 100644 index 0000000000..49e9d8b074 --- /dev/null +++ b/rpc/src/v1/helpers/deprecated.rs @@ -0,0 +1,111 @@ +// 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 . + +//! Deprecation notice for RPC methods. +//! +//! Displays a warning but avoids spamming the log. + +use std::{ + collections::HashMap, + time::{Duration, Instant}, +}; + +use parking_lot::RwLock; + +/// Deprecation messages +pub mod msgs { + pub const ACCOUNTS: Option<&str> = Some("Account management is being phased out see #9997 for alternatives."); +} + +type MethodName = &'static str; + +const PRINT_INTERVAL: Duration = Duration::from_secs(60); + +/// Displays a deprecation notice without spamming the log. +pub struct DeprecationNotice Instant> { + now: T, + next_warning_at: RwLock>, + printer: Box) + Send + Sync>, +} + +impl Default for DeprecationNotice { + fn default() -> Self { + Self::new(Instant::now, |method, more| { + let more = more.map(|x| format!(": {}", x)).unwrap_or_else(|| ".".into()); + warn!(target: "rpc", "{} is deprecated and will be removed in future versions{}", method, more); + }) + } +} + +impl Instant> DeprecationNotice { + /// Create new deprecation notice printer with custom display and interval. + pub fn new(now: N, printer: T) -> Self where + T: Fn(MethodName, Option<&str>) + Send + Sync + 'static, + { + DeprecationNotice { + now, + next_warning_at: Default::default(), + printer: Box::new(printer), + } + } + + /// Print deprecation notice for given method and with some additional details (explanations). + pub fn print<'a, T: Into>>(&self, method: MethodName, details: T) { + let now = (self.now)(); + match self.next_warning_at.read().get(method) { + Some(next) if *next > now => return, + _ => {}, + } + + self.next_warning_at.write().insert(method.to_owned(), now + PRINT_INTERVAL); + (self.printer)(method, details.into()); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use std::sync::Arc; + + #[test] + fn should_throttle_printing() { + let saved = Arc::new(RwLock::new(None)); + let s = saved.clone(); + let printer = move |method: MethodName, more: Option<&str>| { + *s.write() = Some((method, more.map(|s| s.to_owned()))); + }; + + let now = Arc::new(RwLock::new(Instant::now())); + let n = now.clone(); + let get_now = || n.read().clone(); + let notice = DeprecationNotice::new(get_now, printer); + + let details = Some("See issue #123456"); + notice.print("eth_test", details.clone()); + // printer shouldn't be called + notice.print("eth_test", None); + assert_eq!(saved.read().clone().unwrap(), ("eth_test", details.as_ref().map(|x| x.to_string()))); + // but calling a different method is fine + notice.print("eth_test2", None); + assert_eq!(saved.read().clone().unwrap(), ("eth_test2", None)); + + // wait and call again + *now.write() = Instant::now() + PRINT_INTERVAL; + notice.print("eth_test", None); + assert_eq!(saved.read().clone().unwrap(), ("eth_test", None)); + } +} diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs deleted file mode 100644 index c26fde45f1..0000000000 --- a/rpc/src/v1/helpers/dispatch.rs +++ /dev/null @@ -1,879 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -//! Utilities and helpers for transaction dispatch. - -use std::fmt::Debug; -use std::ops::Deref; -use std::sync::Arc; - -use light::cache::Cache as LightDataCache; -use light::client::LightChainClient; -use light::on_demand::{request, OnDemand}; -use light::TransactionQueue as LightTransactionQueue; -use hash::keccak; -use ethereum_types::{H256, H520, Address, U256}; -use bytes::Bytes; -use parking_lot::{Mutex, RwLock}; -use stats::Corpus; - -use crypto::DEFAULT_MAC; -use ethcore::account_provider::AccountProvider; -use ethcore::client::BlockChainClient; -use ethcore::miner::{self, MinerService}; -use ethkey::{Password, Signature}; -use sync::LightSync; -use types::transaction::{Action, SignedTransaction, PendingTransaction, Transaction, Error as TransactionError}; -use types::basic_account::BasicAccount; -use types::ids::BlockId; - -use jsonrpc_core::{BoxFuture, Result, Error}; -use jsonrpc_core::futures::{future, Future, Poll, Async, IntoFuture}; -use jsonrpc_core::futures::future::Either; -use v1::helpers::{errors, nonce, TransactionRequest, FilledTransactionRequest, ConfirmationPayload}; -use v1::types::{ - H520 as RpcH520, Bytes as RpcBytes, - RichRawTransaction as RpcRichRawTransaction, - ConfirmationPayload as RpcConfirmationPayload, - ConfirmationResponse, - EthSignRequest as RpcEthSignRequest, - EIP191SignRequest as RpcSignRequest, - DecryptRequest as RpcDecryptRequest, -}; -use rlp; - -pub use self::nonce::Reservations; - -/// Has the capability to dispatch, sign, and decrypt. -/// -/// Requires a clone implementation, with the implication that it be cheap; -/// usually just bumping a reference count or two. -pub trait Dispatcher: Send + Sync + Clone { - // TODO: when ATC exist, use zero-cost - // type Out: IntoFuture - - /// Fill optional fields of a transaction request, fetching gas price but not nonce. - fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address, force_nonce: bool) - -> BoxFuture; - - /// Sign the given transaction request, fetching appropriate nonce and executing the PostSign action - fn sign

( - &self, - accounts: Arc, - filled: FilledTransactionRequest, - password: SignWith, - post_sign: P - ) -> BoxFuture - where - P: PostSign + 'static, - ::Future: Send; - - /// Converts a `SignedTransaction` into `RichRawTransaction` - fn enrich(&self, signed: SignedTransaction) -> RpcRichRawTransaction; - - /// "Dispatch" a local transaction. - fn dispatch_transaction(&self, signed_transaction: PendingTransaction) - -> Result; -} - -/// A dispatcher which uses references to a client and miner in order to sign -/// requests locally. -#[derive(Debug)] -pub struct FullDispatcher { - client: Arc, - miner: Arc, - nonces: Arc>, - gas_price_percentile: usize, -} - -impl FullDispatcher { - /// Create a `FullDispatcher` from Arc references to a client and miner. - pub fn new( - client: Arc, - miner: Arc, - nonces: Arc>, - gas_price_percentile: usize, - ) -> Self { - FullDispatcher { - client, - miner, - nonces, - gas_price_percentile, - } - } -} - -impl Clone for FullDispatcher { - fn clone(&self) -> Self { - FullDispatcher { - client: self.client.clone(), - miner: self.miner.clone(), - nonces: self.nonces.clone(), - gas_price_percentile: self.gas_price_percentile, - } - } -} - -impl FullDispatcher { - fn state_nonce(&self, from: &Address) -> U256 { - self.miner.next_nonce(&*self.client, from) - } - - /// Imports transaction to the miner's queue. - pub fn dispatch_transaction(client: &C, miner: &M, signed_transaction: PendingTransaction, trusted: bool) -> Result { - let hash = signed_transaction.transaction.hash(); - - // use `import_claimed_local_transaction` so we can decide (based on config flags) if we want to treat - // it as local or not. Nodes with public RPC interfaces will want these transactions to be treated like - // external transactions. - miner.import_claimed_local_transaction(client, signed_transaction, trusted) - .map_err(errors::transaction) - .map(|_| hash) - } -} - -impl Dispatcher for FullDispatcher { - fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address, force_nonce: bool) - -> BoxFuture - { - let request = request; - let from = request.from.unwrap_or(default_sender); - let nonce = if force_nonce { - request.nonce.or_else(|| Some(self.state_nonce(&from))) - } else { - request.nonce - }; - - Box::new(future::ok(FilledTransactionRequest { - from, - used_default_from: request.from.is_none(), - to: request.to, - nonce, - gas_price: request.gas_price.unwrap_or_else(|| { - default_gas_price(&*self.client, &*self.miner, self.gas_price_percentile) - }), - gas: request.gas.unwrap_or_else(|| self.miner.sensible_gas_limit()), - value: request.value.unwrap_or_else(|| 0.into()), - data: request.data.unwrap_or_else(Vec::new), - condition: request.condition, - })) - } - - fn sign

( - &self, - accounts: Arc, - filled: FilledTransactionRequest, - password: SignWith, - post_sign: P - ) -> BoxFuture - where - P: PostSign + 'static, - ::Future: Send - { - let chain_id = self.client.signing_chain_id(); - - if let Some(nonce) = filled.nonce { - let future = sign_transaction(&*accounts, filled, chain_id, nonce, password) - .into_future() - .and_then(move |signed| post_sign.execute(signed)); - Box::new(future) - } else { - let state = self.state_nonce(&filled.from); - let reserved = self.nonces.lock().reserve(filled.from, state); - - Box::new(ProspectiveSigner::new(accounts, filled, chain_id, reserved, password, post_sign)) - } - } - - fn enrich(&self, signed_transaction: SignedTransaction) -> RpcRichRawTransaction { - RpcRichRawTransaction::from_signed(signed_transaction) - } - - fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result { - Self::dispatch_transaction(&*self.client, &*self.miner, signed_transaction, true) - } -} - -/// Get a recent gas price corpus. -// TODO: this could be `impl Trait`. -pub fn fetch_gas_price_corpus( - sync: Arc, - client: Arc, - on_demand: Arc, - cache: Arc>, -) -> BoxFuture> { - const GAS_PRICE_SAMPLE_SIZE: usize = 100; - - if let Some(cached) = { cache.lock().gas_price_corpus() } { - return Box::new(future::ok(cached)) - } - - let cache = cache.clone(); - let eventual_corpus = sync.with_context(|ctx| { - // get some recent headers with gas used, - // and request each of the blocks from the network. - let block_requests = client.ancestry_iter(BlockId::Latest) - .filter(|hdr| hdr.gas_used() != U256::default()) - .take(GAS_PRICE_SAMPLE_SIZE) - .map(|hdr| request::Body(hdr.into())) - .collect::>(); - - // when the blocks come in, collect gas prices into a vector - on_demand.request(ctx, block_requests) - .expect("no back-references; therefore all back-references are valid; qed") - .map(|bodies| { - bodies.into_iter().fold(Vec::new(), |mut v, block| { - for t in block.transaction_views().iter() { - v.push(t.gas_price()) - } - v - }) - }) - .map(move |prices| { - // produce a corpus from the vector and cache it. - // It's later used to get a percentile for default gas price. - let corpus: ::stats::Corpus<_> = prices.into(); - cache.lock().set_gas_price_corpus(corpus.clone()); - corpus - }) - }); - - match eventual_corpus { - Some(corp) => Box::new(corp.map_err(|_| errors::no_light_peers())), - None => Box::new(future::err(errors::network_disabled())), - } -} - -/// Returns a eth_sign-compatible hash of data to sign. -/// The data is prepended with special message to prevent -/// malicious DApps from using the function to sign forged transactions. -pub fn eth_data_hash(mut data: Bytes) -> H256 { - let mut message_data = - format!("\x19Ethereum Signed Message:\n{}", data.len()) - .into_bytes(); - message_data.append(&mut data); - keccak(message_data) -} - -/// Dispatcher for light clients -- fetches default gas price, next nonce, etc. from network. -#[derive(Clone)] -pub struct LightDispatcher { - /// Sync service. - pub sync: Arc, - /// Header chain client. - pub client: Arc, - /// On-demand request service. - pub on_demand: Arc, - /// Data cache. - pub cache: Arc>, - /// Transaction queue. - pub transaction_queue: Arc>, - /// Nonce reservations - pub nonces: Arc>, - /// Gas Price percentile value used as default gas price. - pub gas_price_percentile: usize, -} - -impl LightDispatcher { - /// Create a new `LightDispatcher` from its requisite parts. - /// - /// For correct operation, the OnDemand service is assumed to be registered as a network handler, - pub fn new( - sync: Arc, - client: Arc, - on_demand: Arc, - cache: Arc>, - transaction_queue: Arc>, - nonces: Arc>, - gas_price_percentile: usize, - ) -> Self { - LightDispatcher { - sync, - client, - on_demand, - cache, - transaction_queue, - nonces, - gas_price_percentile, - } - } - - /// Get a recent gas price corpus. - // TODO: this could be `impl Trait`. - pub fn gas_price_corpus(&self) -> BoxFuture> { - fetch_gas_price_corpus( - self.sync.clone(), - self.client.clone(), - self.on_demand.clone(), - self.cache.clone(), - ) - } - - /// Get an account's state - fn account(&self, addr: Address) -> BoxFuture> { - let best_header = self.client.best_block_header(); - let account_future = self.sync.with_context(|ctx| self.on_demand.request(ctx, request::Account { - header: best_header.into(), - address: addr, - }).expect("no back-references; therefore all back-references valid; qed")); - - match account_future { - Some(response) => Box::new(response.map_err(|_| errors::no_light_peers())), - None => Box::new(future::err(errors::network_disabled())), - } - } - - /// Get an account's next nonce. - pub fn next_nonce(&self, addr: Address) -> BoxFuture { - let account_start_nonce = self.client.engine().account_start_nonce(self.client.best_block_header().number()); - Box::new(self.account(addr) - .and_then(move |maybe_account| { - future::ok(maybe_account.map_or(account_start_nonce, |account| account.nonce)) - }) - ) - } -} - -impl Dispatcher for LightDispatcher { - // Ignore the `force_nonce` flag in order to always query the network when fetching the nonce and - // the account state. If the nonce is specified in the transaction use that nonce instead but do the - // network request anyway to the account state (balance) - fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address, _force_nonce: bool) - -> BoxFuture - { - const DEFAULT_GAS_PRICE: U256 = U256([0, 0, 0, 21_000_000]); - - let gas_limit = self.client.best_block_header().gas_limit(); - let request_gas_price = request.gas_price.clone(); - let from = request.from.unwrap_or(default_sender); - - let with_gas_price = move |gas_price| { - let request = request; - FilledTransactionRequest { - from: from.clone(), - used_default_from: request.from.is_none(), - to: request.to, - nonce: request.nonce, - gas_price: gas_price, - gas: request.gas.unwrap_or_else(|| gas_limit / 3), - value: request.value.unwrap_or_else(|| 0.into()), - data: request.data.unwrap_or_else(Vec::new), - condition: request.condition, - } - }; - - // fast path for known gas price. - let gas_price_percentile = self.gas_price_percentile; - let gas_price = match request_gas_price { - Some(gas_price) => Either::A(future::ok(with_gas_price(gas_price))), - None => Either::B(fetch_gas_price_corpus( - self.sync.clone(), - self.client.clone(), - self.on_demand.clone(), - self.cache.clone() - ).and_then(move |corp| match corp.percentile(gas_price_percentile) { - Some(percentile) => Ok(*percentile), - None => Ok(DEFAULT_GAS_PRICE), // fall back to default on error. - }).map(with_gas_price)) - }; - - let future_account = self.account(from); - - Box::new(gas_price.and_then(move |mut filled| { - future_account - .and_then(move |maybe_account| { - let cost = filled.value.saturating_add(filled.gas.saturating_mul(filled.gas_price)); - match maybe_account { - Some(ref account) if cost > account.balance => { - Err(errors::transaction(TransactionError::InsufficientBalance { - balance: account.balance, - cost, - })) - } - Some(account) => { - if filled.nonce.is_none() { - filled.nonce = Some(account.nonce); - } - Ok(filled) - } - None => Err(errors::account("Account not found", "")), - } - }) - })) - } - - fn sign

( - &self, - accounts: Arc, - filled: FilledTransactionRequest, - password: SignWith, - post_sign: P - ) -> BoxFuture - where - P: PostSign + 'static, - ::Future: Send - { - let chain_id = self.client.signing_chain_id(); - let nonce = filled.nonce.expect("nonce is always provided; qed"); - - let future = sign_transaction(&*accounts, filled, chain_id, nonce, password) - .into_future() - .and_then(move |signed| post_sign.execute(signed)); - Box::new(future) - } - - fn enrich(&self, signed_transaction: SignedTransaction) -> RpcRichRawTransaction { - RpcRichRawTransaction::from_signed(signed_transaction) - } - - fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result { - let hash = signed_transaction.transaction.hash(); - - self.transaction_queue.write().import(signed_transaction) - .map_err(errors::transaction) - .map(|_| hash) - } -} - -fn sign_transaction( - accounts: &AccountProvider, - filled: FilledTransactionRequest, - chain_id: Option, - nonce: U256, - password: SignWith, -) -> Result> { - let t = Transaction { - nonce: nonce, - action: filled.to.map_or(Action::Create, Action::Call), - gas: filled.gas, - gas_price: filled.gas_price, - value: filled.value, - data: filled.data, - }; - - if accounts.is_hardware_address(&filled.from) { - return hardware_signature(accounts, filled.from, t, chain_id).map(WithToken::No) - } - - let hash = t.hash(chain_id); - let signature = signature(accounts, filled.from, hash, password)?; - - Ok(signature.map(|sig| { - SignedTransaction::new(t.with_signature(sig, chain_id)) - .expect("Transaction was signed by AccountsProvider; it never produces invalid signatures; qed") - })) -} - -#[derive(Debug, Clone, Copy)] -enum ProspectiveSignerState { - TryProspectiveSign, - WaitForPostSign, - WaitForNonce, -} - -struct ProspectiveSigner { - accounts: Arc, - filled: FilledTransactionRequest, - chain_id: Option, - reserved: nonce::Reserved, - password: SignWith, - state: ProspectiveSignerState, - prospective: Option>, - ready: Option, - post_sign: Option

, - post_sign_future: Option<::Future> -} - -/// action to execute after signing -/// e.g importing a transaction into the chain -pub trait PostSign: Send { - /// item that this PostSign returns - type Item: Send; - /// incase you need to perform async PostSign actions - type Out: IntoFuture + Send; - /// perform an action with the signed transaction - fn execute(self, signer: WithToken) -> Self::Out; -} - -impl PostSign for () { - type Item = WithToken; - type Out = Result; - fn execute(self, signed: WithToken) -> Self::Out { - Ok(signed) - } -} - -impl PostSign for F - where F: FnOnce(WithToken) -> Result -{ - type Item = T; - type Out = Result; - fn execute(self, signed: WithToken) -> Self::Out { - (self)(signed) - } -} - -impl ProspectiveSigner

{ - pub fn new( - accounts: Arc, - filled: FilledTransactionRequest, - chain_id: Option, - reserved: nonce::Reserved, - password: SignWith, - post_sign: P - ) -> Self { - // If the account is permanently unlocked we can try to sign - // using prospective nonce. This should speed up sending - // multiple subsequent transactions in multi-threaded RPC environment. - let is_unlocked_permanently = accounts.is_unlocked_permanently(&filled.from); - let has_password = password.is_password(); - - ProspectiveSigner { - accounts, - filled, - chain_id, - reserved, - password, - state: if is_unlocked_permanently || has_password { - ProspectiveSignerState::TryProspectiveSign - } else { - ProspectiveSignerState::WaitForNonce - }, - prospective: None, - ready: None, - post_sign: Some(post_sign), - post_sign_future: None - } - } - - fn sign(&self, nonce: &U256) -> Result> { - sign_transaction( - &*self.accounts, - self.filled.clone(), - self.chain_id, - *nonce, - self.password.clone() - ) - } - - fn poll_reserved(&mut self) -> Poll { - self.reserved.poll().map_err(|_| errors::internal("Nonce reservation failure", "")) - } -} - -impl Future for ProspectiveSigner

{ - type Item = P::Item; - type Error = Error; - - fn poll(&mut self) -> Poll { - use self::ProspectiveSignerState::*; - - loop { - match self.state { - TryProspectiveSign => { - // Try to poll reserved, it might be ready. - match self.poll_reserved()? { - Async::NotReady => { - self.state = WaitForNonce; - self.prospective = Some(self.sign(self.reserved.prospective_value())?); - }, - Async::Ready(nonce) => { - self.state = WaitForPostSign; - self.post_sign_future = Some(self.post_sign.take() - .expect("post_sign is set on creation; qed") - .execute(self.sign(nonce.value())?) - .into_future()); - self.ready = Some(nonce); - }, - } - }, - WaitForNonce => { - let nonce = try_ready!(self.poll_reserved()); - let prospective = match (self.prospective.take(), nonce.matches_prospective()) { - (Some(prospective), true) => prospective, - _ => self.sign(nonce.value())?, - }; - self.ready = Some(nonce); - self.state = WaitForPostSign; - self.post_sign_future = Some(self.post_sign.take() - .expect("post_sign is set on creation; qed") - .execute(prospective) - .into_future()); - }, - WaitForPostSign => { - if let Some(mut fut) = self.post_sign_future.as_mut() { - match fut.poll()? { - Async::Ready(item) => { - let nonce = self.ready - .take() - .expect("nonce is set before state transitions to WaitForPostSign; qed"); - nonce.mark_used(); - return Ok(Async::Ready(item)) - }, - Async::NotReady => { - return Ok(Async::NotReady) - } - } - } else { - panic!("Poll after ready."); - } - } - } - } - } -} - -/// Single-use account token. -pub type AccountToken = Password; - -/// Values used to unlock accounts for signing. -#[derive(Clone, PartialEq)] -pub enum SignWith { - /// Nothing -- implies the account is already unlocked. - Nothing, - /// Unlock with password. - Password(Password), - /// Unlock with single-use token. - Token(AccountToken), -} - -impl SignWith { - fn is_password(&self) -> bool { - if let SignWith::Password(_) = *self { - true - } else { - false - } - } -} - -/// A value, potentially accompanied by a signing token. -pub enum WithToken { - /// No token. - No(T), - /// With token. - Yes(T, AccountToken), -} - -impl Deref for WithToken { - type Target = T; - - fn deref(&self) -> &Self::Target { - match *self { - WithToken::No(ref v) => v, - WithToken::Yes(ref v, _) => v, - } - } -} - -impl WithToken { - /// Map the value with the given closure, preserving the token. - pub fn map(self, f: F) -> WithToken where - S: Debug, - F: FnOnce(T) -> S, - { - match self { - WithToken::No(v) => WithToken::No(f(v)), - WithToken::Yes(v, token) => WithToken::Yes(f(v), token), - } - } - - /// Convert into inner value, ignoring possible token. - pub fn into_value(self) -> T { - match self { - WithToken::No(v) => v, - WithToken::Yes(v, _) => v, - } - } - - /// Convert the `WithToken` into a tuple. - pub fn into_tuple(self) -> (T, Option) { - match self { - WithToken::No(v) => (v, None), - WithToken::Yes(v, token) => (v, Some(token)) - } - } -} - -impl From<(T, AccountToken)> for WithToken { - fn from(tuple: (T, AccountToken)) -> Self { - WithToken::Yes(tuple.0, tuple.1) - } -} - -impl From<(T, Option)> for WithToken { - fn from(tuple: (T, Option)) -> Self { - match tuple.1 { - Some(token) => WithToken::Yes(tuple.0, token), - None => WithToken::No(tuple.0), - } - } -} - -/// Execute a confirmation payload. -pub fn execute( - dispatcher: D, - accounts: Arc, - payload: ConfirmationPayload, - pass: SignWith -) -> BoxFuture> { - match payload { - ConfirmationPayload::SendTransaction(request) => { - let condition = request.condition.clone().map(Into::into); - let cloned_dispatcher = dispatcher.clone(); - let post_sign = move |with_token_signed: WithToken| { - let (signed, token) = with_token_signed.into_tuple(); - let signed_transaction = PendingTransaction::new(signed, condition); - cloned_dispatcher.dispatch_transaction(signed_transaction) - .map(|hash| (hash, token)) - }; - let future = dispatcher.sign(accounts, request, pass, post_sign) - .map(|(hash, token)| { - WithToken::from((ConfirmationResponse::SendTransaction(hash.into()), token)) - }); - Box::new(future) - }, - ConfirmationPayload::SignTransaction(request) => { - Box::new(dispatcher.sign(accounts, request, pass, ()) - .map(move |result| result - .map(move |tx| dispatcher.enrich(tx)) - .map(ConfirmationResponse::SignTransaction) - )) - }, - ConfirmationPayload::EthSignMessage(address, data) => { - if accounts.is_hardware_address(&address) { - let signature = accounts.sign_message_with_hardware(&address, &data) - .map(|s| H520(s.into_electrum())) - .map(RpcH520::from) - .map(ConfirmationResponse::Signature) - // TODO: is this correct? I guess the `token` is the wallet in this context - .map(WithToken::No) - .map_err(|e| errors::account("Error signing message with hardware_wallet", e)); - - return Box::new(future::done(signature)); - } - let hash = eth_data_hash(data); - let res = signature(&accounts, address, hash, pass) - .map(|result| result - .map(|rsv| H520(rsv.into_electrum())) - .map(RpcH520::from) - .map(ConfirmationResponse::Signature) - ); - Box::new(future::done(res)) - }, - ConfirmationPayload::SignMessage(address, data) => { - if accounts.is_hardware_address(&address) { - return Box::new(future::err(errors::account("Error signing message with hardware_wallet", - "Message signing is unsupported"))); - } - let res = signature(&accounts, address, data, pass) - .map(|result| result - .map(|rsv| H520(rsv.into_electrum())) - .map(RpcH520::from) - .map(ConfirmationResponse::Signature) - ); - Box::new(future::done(res)) - }, - ConfirmationPayload::Decrypt(address, data) => { - if accounts.is_hardware_address(&address) { - return Box::new(future::err(errors::unsupported("Decrypting via hardware wallets is not supported.", None))); - } - let res = decrypt(&accounts, address, data, pass) - .map(|result| result - .map(RpcBytes) - .map(ConfirmationResponse::Decrypt) - ); - Box::new(future::done(res)) - }, - } -} - -fn signature(accounts: &AccountProvider, address: Address, hash: H256, password: SignWith) -> Result> { - match password.clone() { - SignWith::Nothing => accounts.sign(address, None, hash).map(WithToken::No), - SignWith::Password(pass) => accounts.sign(address, Some(pass), hash).map(WithToken::No), - SignWith::Token(token) => accounts.sign_with_token(address, token, hash).map(Into::into), - }.map_err(|e| match password { - SignWith::Nothing => errors::signing(e), - _ => errors::password(e), - }) -} - -// obtain a hardware signature from the given account. -fn hardware_signature(accounts: &AccountProvider, address: Address, t: Transaction, chain_id: Option) - -> Result -{ - debug_assert!(accounts.is_hardware_address(&address)); - - let mut stream = rlp::RlpStream::new(); - t.rlp_append_unsigned_transaction(&mut stream, chain_id); - let signature = accounts.sign_transaction_with_hardware(&address, &t, chain_id, &stream.as_raw()) - .map_err(|e| { - debug!(target: "miner", "Error signing transaction with hardware wallet: {}", e); - errors::account("Error signing transaction with hardware wallet", e) - })?; - - SignedTransaction::new(t.with_signature(signature, chain_id)) - .map_err(|e| { - debug!(target: "miner", "Hardware wallet has produced invalid signature: {}", e); - errors::account("Invalid signature generated", e) - }) -} - -fn decrypt(accounts: &AccountProvider, address: Address, msg: Bytes, password: SignWith) -> Result> { - match password.clone() { - SignWith::Nothing => accounts.decrypt(address, None, &DEFAULT_MAC, &msg).map(WithToken::No), - SignWith::Password(pass) => accounts.decrypt(address, Some(pass), &DEFAULT_MAC, &msg).map(WithToken::No), - SignWith::Token(token) => accounts.decrypt_with_token(address, token, &DEFAULT_MAC, &msg).map(Into::into), - }.map_err(|e| match password { - SignWith::Nothing => errors::signing(e), - _ => errors::password(e), - }) -} - -/// Extract the default gas price from a client and miner. -pub fn default_gas_price(client: &C, miner: &M, percentile: usize) -> U256 where - C: BlockChainClient, - M: MinerService, -{ - client.gas_price_corpus(100).percentile(percentile).cloned().unwrap_or_else(|| miner.sensible_gas_price()) -} - -/// Convert RPC confirmation payload to signer confirmation payload. -/// May need to resolve in the future to fetch things like gas price. -pub fn from_rpc(payload: RpcConfirmationPayload, default_account: Address, dispatcher: &D) -> BoxFuture - where D: Dispatcher -{ - match payload { - RpcConfirmationPayload::SendTransaction(request) => { - Box::new(dispatcher.fill_optional_fields(request.into(), default_account, false) - .map(ConfirmationPayload::SendTransaction)) - }, - RpcConfirmationPayload::SignTransaction(request) => { - Box::new(dispatcher.fill_optional_fields(request.into(), default_account, false) - .map(ConfirmationPayload::SignTransaction)) - }, - RpcConfirmationPayload::Decrypt(RpcDecryptRequest { address, msg }) => { - Box::new(future::ok(ConfirmationPayload::Decrypt(address.into(), msg.into()))) - }, - RpcConfirmationPayload::EthSignMessage(RpcEthSignRequest { address, data }) => { - Box::new(future::ok(ConfirmationPayload::EthSignMessage(address.into(), data.into()))) - }, - RpcConfirmationPayload::EIP191SignMessage(RpcSignRequest { address, data }) => { - Box::new(future::ok(ConfirmationPayload::SignMessage(address.into(), data.into()))) - }, - } -} diff --git a/rpc/src/v1/helpers/dispatch/full.rs b/rpc/src/v1/helpers/dispatch/full.rs new file mode 100644 index 0000000000..d958416cbf --- /dev/null +++ b/rpc/src/v1/helpers/dispatch/full.rs @@ -0,0 +1,151 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +use std::sync::Arc; + +use ethcore::client::BlockChainClient; +use ethcore::miner::{self, MinerService}; +use ethereum_types::{H256, U256, Address}; +use types::transaction::{SignedTransaction, PendingTransaction}; +use parking_lot::Mutex; + +use jsonrpc_core::{BoxFuture, Result}; +use jsonrpc_core::futures::{future, Future, IntoFuture}; +use v1::helpers::{errors, nonce, TransactionRequest, FilledTransactionRequest}; +use v1::types::{RichRawTransaction as RpcRichRawTransaction}; + +use super::prospective_signer::ProspectiveSigner; +use super::{Dispatcher, Accounts, SignWith, PostSign, default_gas_price}; + +/// A dispatcher which uses references to a client and miner in order to sign +/// requests locally. +#[derive(Debug)] +pub struct FullDispatcher { + client: Arc, + miner: Arc, + nonces: Arc>, + gas_price_percentile: usize, +} + +impl FullDispatcher { + /// Create a `FullDispatcher` from Arc references to a client and miner. + pub fn new( + client: Arc, + miner: Arc, + nonces: Arc>, + gas_price_percentile: usize, + ) -> Self { + FullDispatcher { + client, + miner, + nonces, + gas_price_percentile, + } + } +} + +impl Clone for FullDispatcher { + fn clone(&self) -> Self { + FullDispatcher { + client: self.client.clone(), + miner: self.miner.clone(), + nonces: self.nonces.clone(), + gas_price_percentile: self.gas_price_percentile, + } + } +} + +impl FullDispatcher { + fn state_nonce(&self, from: &Address) -> U256 { + self.miner.next_nonce(&*self.client, from) + } + + /// Post transaction to the network. + /// + /// If transaction is trusted we are more likely to assume it is coming from a local account. + pub fn dispatch_transaction(client: &C, miner: &M, signed_transaction: PendingTransaction, trusted: bool) -> Result { + let hash = signed_transaction.transaction.hash(); + + // use `import_claimed_local_transaction` so we can decide (based on config flags) if we want to treat + // it as local or not. Nodes with public RPC interfaces will want these transactions to be treated like + // external transactions. + miner.import_claimed_local_transaction(client, signed_transaction, trusted) + .map_err(errors::transaction) + .map(|_| hash) + } +} + +impl Dispatcher for FullDispatcher { + fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address, force_nonce: bool) + -> BoxFuture + { + let request = request; + let from = request.from.unwrap_or(default_sender); + let nonce = if force_nonce { + request.nonce.or_else(|| Some(self.state_nonce(&from))) + } else { + request.nonce + }; + + Box::new(future::ok(FilledTransactionRequest { + from, + used_default_from: request.from.is_none(), + to: request.to, + nonce, + gas_price: request.gas_price.unwrap_or_else(|| { + default_gas_price(&*self.client, &*self.miner, self.gas_price_percentile) + }), + gas: request.gas.unwrap_or_else(|| self.miner.sensible_gas_limit()), + value: request.value.unwrap_or_else(|| 0.into()), + data: request.data.unwrap_or_else(Vec::new), + condition: request.condition, + })) + } + + fn sign

( + &self, + filled: FilledTransactionRequest, + signer: &Arc, + password: SignWith, + post_sign: P, + ) -> BoxFuture + where + P: PostSign + 'static, + ::Future: Send, + { + let chain_id = self.client.signing_chain_id(); + + if let Some(nonce) = filled.nonce { + let future = signer.sign_transaction(filled, chain_id, nonce, password) + .into_future() + .and_then(move |signed| post_sign.execute(signed)); + Box::new(future) + } else { + let state = self.state_nonce(&filled.from); + let reserved = self.nonces.lock().reserve(filled.from, state); + + Box::new(ProspectiveSigner::new(signer.clone(), filled, chain_id, reserved, password, post_sign)) + } + } + + fn enrich(&self, signed_transaction: SignedTransaction) -> RpcRichRawTransaction { + RpcRichRawTransaction::from_signed(signed_transaction) + } + + fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result { + Self::dispatch_transaction(&*self.client, &*self.miner, signed_transaction, true) + } +} diff --git a/rpc/src/v1/helpers/dispatch/light.rs b/rpc/src/v1/helpers/dispatch/light.rs new file mode 100644 index 0000000000..88f9fafcf1 --- /dev/null +++ b/rpc/src/v1/helpers/dispatch/light.rs @@ -0,0 +1,299 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +use std::sync::Arc; + +use ethereum_types::{H256, Address, U256}; +use light::TransactionQueue as LightTransactionQueue; +use light::cache::Cache as LightDataCache; +use light::client::LightChainClient; +use light::on_demand::{request, OnDemandRequester}; +use parking_lot::{Mutex, RwLock}; +use stats::Corpus; +use sync::{LightSyncProvider, LightNetworkDispatcher, ManageNetwork}; +use types::basic_account::BasicAccount; +use types::ids::BlockId; +use types::transaction::{SignedTransaction, PendingTransaction, Error as TransactionError}; + +use jsonrpc_core::{BoxFuture, Result}; +use jsonrpc_core::futures::{future, Future, IntoFuture}; +use jsonrpc_core::futures::future::Either; +use v1::helpers::{errors, nonce, TransactionRequest, FilledTransactionRequest}; +use v1::types::{RichRawTransaction as RpcRichRawTransaction,}; + +use super::{Dispatcher, Accounts, SignWith, PostSign}; + +/// Dispatcher for light clients -- fetches default gas price, next nonce, etc. from network. +pub struct LightDispatcher +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ + /// Sync service. + pub sync: Arc, + /// Header chain client. + pub client: Arc, + /// On-demand request service. + pub on_demand: Arc, + /// Data cache. + pub cache: Arc>, + /// Transaction queue. + pub transaction_queue: Arc>, + /// Nonce reservations + pub nonces: Arc>, + /// Gas Price percentile value used as default gas price. + pub gas_price_percentile: usize, +} + +impl LightDispatcher +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ + /// Create a new `LightDispatcher` from its requisite parts. + /// + /// For correct operation, the OnDemand service is assumed to be registered as a network handler, + pub fn new( + sync: Arc, + client: Arc, + on_demand: Arc, + cache: Arc>, + transaction_queue: Arc>, + nonces: Arc>, + gas_price_percentile: usize, + ) -> Self { + LightDispatcher { + sync, + client, + on_demand, + cache, + transaction_queue, + nonces, + gas_price_percentile, + } + } + + /// Get a recent gas price corpus. + // TODO: this could be `impl Trait`. + pub fn gas_price_corpus(&self) -> BoxFuture> { + fetch_gas_price_corpus( + self.sync.clone(), + self.client.clone(), + self.on_demand.clone(), + self.cache.clone(), + ) + } + + /// Get an account's state + fn account(&self, addr: Address) -> BoxFuture> { + let best_header = self.client.best_block_header(); + let account_future = self.sync.with_context(|ctx| self.on_demand.request(ctx, request::Account { + header: best_header.into(), + address: addr, + }).expect("no back-references; therefore all back-references valid; qed")); + + match account_future { + Some(response) => Box::new(response.map_err(|_| errors::no_light_peers())), + None => Box::new(future::err(errors::network_disabled())), + } + } + + /// Get an account's next nonce. + pub fn next_nonce(&self, addr: Address) -> BoxFuture { + let account_start_nonce = self.client.engine().account_start_nonce(self.client.best_block_header().number()); + Box::new(self.account(addr) + .and_then(move |maybe_account| { + future::ok(maybe_account.map_or(account_start_nonce, |account| account.nonce)) + }) + ) + } +} + +impl Clone for LightDispatcher +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ + fn clone(&self) -> Self { + Self { + sync: self.sync.clone(), + client: self.client.clone(), + on_demand: self.on_demand.clone(), + cache: self.cache.clone(), + transaction_queue: self.transaction_queue.clone(), + nonces: self.nonces.clone(), + gas_price_percentile: self.gas_price_percentile + } + } +} + +impl Dispatcher for LightDispatcher +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ + // Ignore the `force_nonce` flag in order to always query the network when fetching the nonce and + // the account state. If the nonce is specified in the transaction use that nonce instead but do the + // network request anyway to the account state (balance) + fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address, _force_nonce: bool) + -> BoxFuture + { + const DEFAULT_GAS_PRICE: U256 = U256([0, 0, 0, 21_000_000]); + + let gas_limit = self.client.best_block_header().gas_limit(); + let request_gas_price = request.gas_price; + let from = request.from.unwrap_or(default_sender); + + let with_gas_price = move |gas_price| { + let request = request; + FilledTransactionRequest { + from, + used_default_from: request.from.is_none(), + to: request.to, + nonce: request.nonce, + gas_price, + gas: request.gas.unwrap_or_else(|| gas_limit / 3), + value: request.value.unwrap_or_default(), + data: request.data.unwrap_or_else(Vec::new), + condition: request.condition, + } + }; + + // fast path for known gas price. + let gas_price_percentile = self.gas_price_percentile; + let gas_price = match request_gas_price { + Some(gas_price) => Either::A(future::ok(with_gas_price(gas_price))), + None => Either::B(fetch_gas_price_corpus( + self.sync.clone(), + self.client.clone(), + self.on_demand.clone(), + self.cache.clone() + ).and_then(move |corp| match corp.percentile(gas_price_percentile) { + Some(percentile) => Ok(*percentile), + None => Ok(DEFAULT_GAS_PRICE), // fall back to default on error. + }).map(with_gas_price)) + }; + + let future_account = self.account(from); + + Box::new(gas_price.and_then(move |mut filled| { + future_account + .and_then(move |maybe_account| { + let cost = filled.value.saturating_add(filled.gas.saturating_mul(filled.gas_price)); + match maybe_account { + Some(ref account) if cost > account.balance => { + Err(errors::transaction(TransactionError::InsufficientBalance { + balance: account.balance, + cost, + })) + } + Some(account) => { + if filled.nonce.is_none() { + filled.nonce = Some(account.nonce); + } + Ok(filled) + } + None => Err(errors::account("Account not found", "")), + } + }) + })) + } + + fn sign

( + &self, + filled: FilledTransactionRequest, + signer: &Arc, + password: SignWith, + post_sign: P + ) -> BoxFuture + where + P: PostSign + 'static, + ::Future: Send, + { + let chain_id = self.client.signing_chain_id(); + let nonce = filled.nonce.expect("nonce is always provided; qed"); + let future = signer.sign_transaction(filled, chain_id, nonce, password) + .into_future() + .and_then(move |signed| post_sign.execute(signed)); + Box::new(future) + } + + fn enrich(&self, signed_transaction: SignedTransaction) -> RpcRichRawTransaction { + RpcRichRawTransaction::from_signed(signed_transaction) + } + + fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result { + let hash = signed_transaction.transaction.hash(); + + self.transaction_queue.write().import(signed_transaction) + .map_err(errors::transaction) + .map(|_| hash) + } +} + +/// Get a recent gas price corpus. +// TODO: this could be `impl Trait`. +pub fn fetch_gas_price_corpus( + sync: Arc, + client: Arc, + on_demand: Arc, + cache: Arc>, +) -> BoxFuture> +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ + const GAS_PRICE_SAMPLE_SIZE: usize = 100; + + if let Some(cached) = { cache.lock().gas_price_corpus() } { + return Box::new(future::ok(cached)) + } + + let cache = cache.clone(); + let eventual_corpus = sync.with_context(|ctx| { + // get some recent headers with gas used, + // and request each of the blocks from the network. + let block_requests = client.ancestry_iter(BlockId::Latest) + .filter(|hdr| hdr.gas_used() != U256::default()) + .take(GAS_PRICE_SAMPLE_SIZE) + .map(|hdr| request::Body(hdr.into())) + .collect::>(); + + // when the blocks come in, collect gas prices into a vector + on_demand.request(ctx, block_requests) + .expect("no back-references; therefore all back-references are valid; qed") + .map(|bodies| { + bodies.into_iter().fold(Vec::new(), |mut v, block| { + for t in block.transaction_views().iter() { + v.push(t.gas_price()) + } + v + }) + }) + .map(move |prices| { + // produce a corpus from the vector and cache it. + // It's later used to get a percentile for default gas price. + let corpus: ::stats::Corpus<_> = prices.into(); + cache.lock().set_gas_price_corpus(corpus.clone()); + corpus + }) + }); + + match eventual_corpus { + Some(corp) => Box::new(corp.map_err(|_| errors::no_light_peers())), + None => Box::new(future::err(errors::network_disabled())), + } +} diff --git a/rpc/src/v1/helpers/dispatch/mod.rs b/rpc/src/v1/helpers/dispatch/mod.rs new file mode 100644 index 0000000000..3f247f0c6c --- /dev/null +++ b/rpc/src/v1/helpers/dispatch/mod.rs @@ -0,0 +1,380 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +//! Utilities and helpers for transaction dispatch. + +pub(crate) mod light; +mod full; +mod prospective_signer; + +#[cfg(any(test, feature = "accounts"))] +mod signing; +#[cfg(not(any(test, feature = "accounts")))] +mod signing { + use super::*; + use v1::helpers::errors; + + /// Dummy signer implementation + #[derive(Debug, Clone)] + pub struct Signer; + + impl Signer { + /// Create new instance of dummy signer (accept any AccountProvider) + pub fn new(_ap: T) -> Self { + Signer + } + } + + impl super::Accounts for Signer { + fn sign_transaction(&self, _filled: FilledTransactionRequest, _chain_id: Option, _nonce: U256, _password: SignWith) -> Result> { + Err(errors::account("Signing unsupported", "See #9997")) + } + + fn sign_message(&self, _address: Address, _password: SignWith, _hash: SignMessage) -> Result> { + Err(errors::account("Signing unsupported", "See #9997")) + } + + fn decrypt(&self, _address: Address, _password: SignWith, _data: Bytes) -> Result> { + Err(errors::account("Signing unsupported", "See #9997")) + } + + fn supports_prospective_signing(&self, _address: &Address, _password: &SignWith) -> bool { + false + } + + fn default_account(&self) -> Address { + Default::default() + } + + fn is_unlocked(&self, _address: &Address) -> bool { + false + } + } +} + +pub use self::light::LightDispatcher; +pub use self::full::FullDispatcher; +pub use self::signing::Signer; +pub use v1::helpers::nonce::Reservations; + +use std::fmt::Debug; +use std::ops::Deref; +use std::sync::Arc; + +use bytes::Bytes; +use ethcore::client::BlockChainClient; +use ethcore::miner::MinerService; +use ethereum_types::{H520, H256, U256, Address}; +use ethkey::{Password, Signature}; +use hash::keccak; +use types::transaction::{SignedTransaction, PendingTransaction}; + +use jsonrpc_core::{BoxFuture, Result, Error}; +use jsonrpc_core::futures::{future, Future, IntoFuture}; +use v1::helpers::{TransactionRequest, FilledTransactionRequest, ConfirmationPayload}; +use v1::types::{ + Bytes as RpcBytes, + RichRawTransaction as RpcRichRawTransaction, + ConfirmationPayload as RpcConfirmationPayload, + ConfirmationResponse, + EthSignRequest as RpcEthSignRequest, + EIP191SignRequest as RpcSignRequest, + DecryptRequest as RpcDecryptRequest, +}; + +/// Has the capability to dispatch, sign, and decrypt. +/// +/// Requires a clone implementation, with the implication that it be cheap; +/// usually just bumping a reference count or two. +pub trait Dispatcher: Send + Sync + Clone { + // TODO: when ATC exist, use zero-cost + // type Out: IntoFuture + + /// Fill optional fields of a transaction request, fetching gas price but not nonce. + fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address, force_nonce: bool) + -> BoxFuture; + + /// Sign the given transaction request without dispatching, fetching appropriate nonce. + fn sign

( + &self, + filled: FilledTransactionRequest, + signer: &Arc, + password: SignWith, + post_sign: P, + ) -> BoxFuture where + P: PostSign + 'static, + ::Future: Send; + + /// Converts a `SignedTransaction` into `RichRawTransaction` + fn enrich(&self, SignedTransaction) -> RpcRichRawTransaction; + + /// "Dispatch" a local transaction. + fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result; +} + +/// Payload to sign +pub enum SignMessage { + /// Eth-sign kind data (requires prefixing) + Data(Bytes), + /// Prefixed data hash + Hash(H256), +} + +/// Abstract transaction signer. +/// +/// NOTE This signer is semi-correct, it's a temporary measure to avoid moving too much code. +/// If accounts are ultimately removed all password-dealing endpoints will be wiped out. +pub trait Accounts: Send + Sync { + /// Sign given filled transaction request for the specified chain_id. + fn sign_transaction(&self, filled: FilledTransactionRequest, chain_id: Option, nonce: U256, password: SignWith) -> Result>; + + /// Sign given message. + fn sign_message(&self, address: Address, password: SignWith, hash: SignMessage) -> Result>; + + /// Decrypt given message. + fn decrypt(&self, address: Address, password: SignWith, data: Bytes) -> Result>; + + /// Returns `true` if the accounts can sign multiple times. + fn supports_prospective_signing(&self, address: &Address, password: &SignWith) -> bool; + + /// Returns default account. + fn default_account(&self) -> Address; + + /// Returns true if account is unlocked (i.e. can sign without a password) + fn is_unlocked(&self, address: &Address) -> bool; +} + +/// action to execute after signing +/// e.g importing a transaction into the chain +pub trait PostSign: Send { + /// item that this PostSign returns + type Item: Send; + /// incase you need to perform async PostSign actions + type Out: IntoFuture + Send; + /// perform an action with the signed transaction + fn execute(self, signer: WithToken) -> Self::Out; +} + +impl PostSign for () { + type Item = WithToken; + type Out = Result; + fn execute(self, signed: WithToken) -> Self::Out { + Ok(signed) + } +} + +impl PostSign for F + where F: FnOnce(WithToken) -> Result +{ + type Item = T; + type Out = Result; + fn execute(self, signed: WithToken) -> Self::Out { + (self)(signed) + } +} + +/// Single-use account token. +pub type AccountToken = Password; + +/// Values used to unlock accounts for signing. +#[derive(Clone, PartialEq)] +pub enum SignWith { + /// Nothing -- implies the account is already unlocked. + Nothing, + /// Unlock with password. + Password(Password), + /// Unlock with single-use token. + Token(AccountToken), +} + +impl SignWith { + #[cfg(any(test, feature = "accounts"))] + fn is_password(&self) -> bool { + if let SignWith::Password(_) = *self { + true + } else { + false + } + } +} + +/// A value, potentially accompanied by a signing token. +pub enum WithToken { + /// No token. + No(T), + /// With token. + Yes(T, AccountToken), +} + +impl Deref for WithToken { + type Target = T; + + fn deref(&self) -> &Self::Target { + match *self { + WithToken::No(ref v) => v, + WithToken::Yes(ref v, _) => v, + } + } +} + +impl WithToken { + /// Map the value with the given closure, preserving the token. + pub fn map(self, f: F) -> WithToken where + S: Debug, + F: FnOnce(T) -> S, + { + match self { + WithToken::No(v) => WithToken::No(f(v)), + WithToken::Yes(v, token) => WithToken::Yes(f(v), token), + } + } + + /// Convert into inner value, ignoring possible token. + pub fn into_value(self) -> T { + match self { + WithToken::No(v) => v, + WithToken::Yes(v, _) => v, + } + } + + /// Convert the `WithToken` into a tuple. + pub fn into_tuple(self) -> (T, Option) { + match self { + WithToken::No(v) => (v, None), + WithToken::Yes(v, token) => (v, Some(token)) + } + } +} + +impl From<(T, AccountToken)> for WithToken { + fn from(tuple: (T, AccountToken)) -> Self { + WithToken::Yes(tuple.0, tuple.1) + } +} + +impl From<(T, Option)> for WithToken { + fn from(tuple: (T, Option)) -> Self { + match tuple.1 { + Some(token) => WithToken::Yes(tuple.0, token), + None => WithToken::No(tuple.0), + } + } +} + +/// Execute a confirmation payload. +pub fn execute( + dispatcher: D, + signer: &Arc, + payload: ConfirmationPayload, + pass: SignWith +) -> BoxFuture> { + match payload { + ConfirmationPayload::SendTransaction(request) => { + let condition = request.condition.clone().map(Into::into); + let cloned_dispatcher = dispatcher.clone(); + let post_sign = move |with_token_signed: WithToken| { + let (signed, token) = with_token_signed.into_tuple(); + let signed_transaction = PendingTransaction::new(signed, condition); + cloned_dispatcher.dispatch_transaction(signed_transaction) + .map(|hash| (hash, token)) + }; + + Box::new( + dispatcher.sign(request, &signer, pass, post_sign).map(|(hash, token)| { + WithToken::from((ConfirmationResponse::SendTransaction(hash), token)) + }) + ) + }, + ConfirmationPayload::SignTransaction(request) => { + Box::new(dispatcher.sign(request, &signer, pass, ()) + .map(move |result| result + .map(move |tx| dispatcher.enrich(tx)) + .map(ConfirmationResponse::SignTransaction) + )) + }, + ConfirmationPayload::EthSignMessage(address, data) => { + let res = signer.sign_message(address, pass, SignMessage::Data(data)) + .map(|result| result + .map(|s| H520(s.into_electrum())) + .map(ConfirmationResponse::Signature) + ); + + Box::new(future::done(res)) + }, + ConfirmationPayload::SignMessage(address, data) => { + let res = signer.sign_message(address, pass, SignMessage::Hash(data)) + .map(|result| result + .map(|rsv| H520(rsv.into_electrum())) + .map(ConfirmationResponse::Signature) + ); + + Box::new(future::done(res)) + }, + ConfirmationPayload::Decrypt(address, data) => { + let res = signer.decrypt(address, pass, data) + .map(|result| result + .map(RpcBytes) + .map(ConfirmationResponse::Decrypt) + ); + Box::new(future::done(res)) + }, + } +} + +/// Returns a eth_sign-compatible hash of data to sign. +/// The data is prepended with special message to prevent +/// malicious DApps from using the function to sign forged transactions. +pub fn eth_data_hash(mut data: Bytes) -> H256 { + let mut message_data = + format!("\x19Ethereum Signed Message:\n{}", data.len()) + .into_bytes(); + message_data.append(&mut data); + keccak(message_data) +} + +/// Extract the default gas price from a client and miner. +pub fn default_gas_price(client: &C, miner: &M, percentile: usize) -> U256 where + C: BlockChainClient, + M: MinerService, +{ + client.gas_price_corpus(100).percentile(percentile).cloned().unwrap_or_else(|| miner.sensible_gas_price()) +} + +/// Convert RPC confirmation payload to signer confirmation payload. +/// May need to resolve in the future to fetch things like gas price. +pub fn from_rpc(payload: RpcConfirmationPayload, default_account: Address, dispatcher: &D) -> BoxFuture + where D: Dispatcher +{ + match payload { + RpcConfirmationPayload::SendTransaction(request) => { + Box::new(dispatcher.fill_optional_fields(request.into(), default_account, false) + .map(ConfirmationPayload::SendTransaction)) + }, + RpcConfirmationPayload::SignTransaction(request) => { + Box::new(dispatcher.fill_optional_fields(request.into(), default_account, false) + .map(ConfirmationPayload::SignTransaction)) + }, + RpcConfirmationPayload::Decrypt(RpcDecryptRequest { address, msg }) => { + Box::new(future::ok(ConfirmationPayload::Decrypt(address, msg.into()))) + }, + RpcConfirmationPayload::EthSignMessage(RpcEthSignRequest { address, data }) => { + Box::new(future::ok(ConfirmationPayload::EthSignMessage(address, data.into()))) + }, + RpcConfirmationPayload::EIP191SignMessage(RpcSignRequest { address, data }) => { + Box::new(future::ok(ConfirmationPayload::SignMessage(address, data))) + }, + } +} diff --git a/rpc/src/v1/helpers/dispatch/prospective_signer.rs b/rpc/src/v1/helpers/dispatch/prospective_signer.rs new file mode 100644 index 0000000000..034d19dc65 --- /dev/null +++ b/rpc/src/v1/helpers/dispatch/prospective_signer.rs @@ -0,0 +1,152 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +use std::sync::Arc; + +use ethereum_types::U256; +use jsonrpc_core::{Result, Error}; +use jsonrpc_core::futures::{Future, Poll, Async, IntoFuture}; +use types::transaction::SignedTransaction; + +use v1::helpers::{errors, nonce, FilledTransactionRequest}; +use super::{Accounts, SignWith, WithToken, PostSign}; + +#[derive(Debug, Clone, Copy)] +enum ProspectiveSignerState { + TryProspectiveSign, + WaitForPostSign, + WaitForNonce, +} + +pub struct ProspectiveSigner { + signer: Arc, + filled: FilledTransactionRequest, + chain_id: Option, + reserved: nonce::Reserved, + password: SignWith, + state: ProspectiveSignerState, + prospective: Option>, + ready: Option, + post_sign: Option

, + post_sign_future: Option<::Future> +} + +impl ProspectiveSigner

{ + pub fn new( + signer: Arc, + filled: FilledTransactionRequest, + chain_id: Option, + reserved: nonce::Reserved, + password: SignWith, + post_sign: P + ) -> Self { + let supports_prospective = signer.supports_prospective_signing(&filled.from, &password); + + ProspectiveSigner { + signer, + filled, + chain_id, + reserved, + password, + state: if supports_prospective { + ProspectiveSignerState::TryProspectiveSign + } else { + ProspectiveSignerState::WaitForNonce + }, + prospective: None, + ready: None, + post_sign: Some(post_sign), + post_sign_future: None + } + } + + fn sign(&self, nonce: &U256) -> Result> { + self.signer.sign_transaction( + self.filled.clone(), + self.chain_id, + *nonce, + self.password.clone() + ) + } + + fn poll_reserved(&mut self) -> Poll { + self.reserved.poll().map_err(|_| errors::internal("Nonce reservation failure", "")) + } +} + +impl Future for ProspectiveSigner

{ + type Item = P::Item; + type Error = Error; + + fn poll(&mut self) -> Poll { + use self::ProspectiveSignerState::*; + + loop { + match self.state { + TryProspectiveSign => { + // Try to poll reserved, it might be ready. + match self.poll_reserved()? { + Async::NotReady => { + self.state = WaitForNonce; + self.prospective = Some(self.sign(self.reserved.prospective_value())?); + }, + Async::Ready(nonce) => { + self.state = WaitForPostSign; + self.post_sign_future = Some( + self.post_sign.take() + .expect("post_sign is set on creation; qed") + .execute(self.sign(nonce.value())?) + .into_future() + ); + self.ready = Some(nonce); + }, + } + }, + WaitForNonce => { + let nonce = try_ready!(self.poll_reserved()); + let prospective = match (self.prospective.take(), nonce.matches_prospective()) { + (Some(prospective), true) => prospective, + _ => self.sign(nonce.value())?, + }; + self.ready = Some(nonce); + self.state = WaitForPostSign; + self.post_sign_future = Some(self.post_sign.take() + .expect("post_sign is set on creation; qed") + .execute(prospective) + .into_future()); + }, + WaitForPostSign => { + if let Some(mut fut) = self.post_sign_future.as_mut() { + match fut.poll()? { + Async::Ready(item) => { + let nonce = self.ready + .take() + .expect("nonce is set before state transitions to WaitForPostSign; qed"); + nonce.mark_used(); + return Ok(Async::Ready(item)) + }, + Async::NotReady => { + return Ok(Async::NotReady) + } + } + } else { + panic!("Poll after ready."); + } + } + } + } + } +} diff --git a/rpc/src/v1/helpers/dispatch/signing.rs b/rpc/src/v1/helpers/dispatch/signing.rs new file mode 100644 index 0000000000..8243dcbdf8 --- /dev/null +++ b/rpc/src/v1/helpers/dispatch/signing.rs @@ -0,0 +1,156 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +use std::sync::Arc; + +use accounts::AccountProvider; +use bytes::Bytes; +use crypto::DEFAULT_MAC; +use ethereum_types::{H256, U256, Address}; +use ethkey::{Signature}; +use types::transaction::{Transaction, Action, SignedTransaction}; + +use jsonrpc_core::Result; +use v1::helpers::{errors, FilledTransactionRequest}; + +use super::{eth_data_hash, WithToken, SignWith, SignMessage}; + +/// Account-aware signer +pub struct Signer { + accounts: Arc, +} + +impl Signer { + /// Create new instance of signer + pub fn new(accounts: Arc) -> Self { + Signer { accounts } + } +} + +impl super::Accounts for Signer { + fn sign_transaction(&self, filled: FilledTransactionRequest, chain_id: Option, nonce: U256, password: SignWith) -> Result> { + let t = Transaction { + nonce: nonce, + action: filled.to.map_or(Action::Create, Action::Call), + gas: filled.gas, + gas_price: filled.gas_price, + value: filled.value, + data: filled.data, + }; + + if self.accounts.is_hardware_address(&filled.from) { + return hardware_signature(&*self.accounts, filled.from, t, chain_id).map(WithToken::No) + } + + let hash = t.hash(chain_id); + let signature = signature(&*self.accounts, filled.from, hash, password)?; + + Ok(signature.map(|sig| { + SignedTransaction::new(t.with_signature(sig, chain_id)) + .expect("Transaction was signed by AccountsProvider; it never produces invalid signatures; qed") + })) + } + + fn sign_message(&self, address: Address, password: SignWith, hash: SignMessage) -> Result> { + if self.accounts.is_hardware_address(&address) { + return if let SignMessage::Data(data) = hash { + let signature = self.accounts.sign_message_with_hardware(&address, &data) + // TODO: is this correct? I guess the `token` is the wallet in this context + .map(WithToken::No) + .map_err(|e| errors::account("Error signing message with hardware_wallet", e)); + + signature + } else { + Err(errors::account("Error signing message with hardware_wallet", "Message signing is unsupported")) + } + } + + match hash { + SignMessage::Data(data) => { + let hash = eth_data_hash(data); + signature(&self.accounts, address, hash, password) + }, + SignMessage::Hash(hash) => { + signature(&self.accounts, address, hash, password) + } + } + } + + fn decrypt(&self, address: Address, password: SignWith, data: Bytes) -> Result> { + if self.accounts.is_hardware_address(&address) { + return Err(errors::unsupported("Decrypting via hardware wallets is not supported.", None)); + } + + match password.clone() { + SignWith::Nothing => self.accounts.decrypt(address, None, &DEFAULT_MAC, &data).map(WithToken::No), + SignWith::Password(pass) => self.accounts.decrypt(address, Some(pass), &DEFAULT_MAC, &data).map(WithToken::No), + SignWith::Token(token) => self.accounts.decrypt_with_token(address, token, &DEFAULT_MAC, &data).map(Into::into), + }.map_err(|e| match password { + SignWith::Nothing => errors::signing(e), + _ => errors::password(e), + }) + } + + fn supports_prospective_signing(&self, address: &Address, password: &SignWith) -> bool { + // If the account is permanently unlocked we can try to sign + // using prospective nonce. This should speed up sending + // multiple subsequent transactions in multi-threaded RPC environment. + let is_unlocked_permanently = self.accounts.is_unlocked_permanently(address); + let has_password = password.is_password(); + + is_unlocked_permanently || has_password + } + + fn default_account(&self) -> Address { + self.accounts.default_account().ok().unwrap_or_default() + } + + fn is_unlocked(&self, address: &Address) -> bool { + self.accounts.is_unlocked(address) + } +} + +fn signature(accounts: &AccountProvider, address: Address, hash: H256, password: SignWith) -> Result> { + match password.clone() { + SignWith::Nothing => accounts.sign(address, None, hash).map(WithToken::No), + SignWith::Password(pass) => accounts.sign(address, Some(pass), hash).map(WithToken::No), + SignWith::Token(token) => accounts.sign_with_token(address, token, hash).map(Into::into), + }.map_err(|e| match password { + SignWith::Nothing => errors::signing(e), + _ => errors::password(e), + }) +} + +// obtain a hardware signature from the given account. +fn hardware_signature(accounts: &AccountProvider, address: Address, t: Transaction, chain_id: Option) + -> Result +{ + debug_assert!(accounts.is_hardware_address(&address)); + + let mut stream = rlp::RlpStream::new(); + t.rlp_append_unsigned_transaction(&mut stream, chain_id); + let signature = accounts.sign_transaction_with_hardware(&address, &t, chain_id, &stream.as_raw()) + .map_err(|e| { + debug!(target: "miner", "Error signing transaction with hardware wallet: {}", e); + errors::account("Error signing transaction with hardware wallet", e) + })?; + + SignedTransaction::new(t.with_signature(signature, chain_id)) + .map_err(|e| { + debug!(target: "miner", "Hardware wallet has produced invalid signature: {}", e); + errors::account("Invalid signature generated", e) + }) +} diff --git a/rpc/src/v1/helpers/engine_signer.rs b/rpc/src/v1/helpers/engine_signer.rs new file mode 100644 index 0000000000..56cead696c --- /dev/null +++ b/rpc/src/v1/helpers/engine_signer.rs @@ -0,0 +1,48 @@ +// 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::sync::Arc; + +use accounts::AccountProvider; +use ethkey::{self, Address, Password}; + +/// An implementation of EngineSigner using internal account management. +pub struct EngineSigner { + accounts: Arc, + address: Address, + password: Password, +} + +impl EngineSigner { + /// Creates new `EngineSigner` given account manager and account details. + pub fn new(accounts: Arc, address: Address, password: Password) -> Self { + EngineSigner { accounts, address, password } + } +} + +impl ethcore::engines::EngineSigner for EngineSigner { + fn sign(&self, message: ethkey::Message) -> Result { + match self.accounts.sign(self.address, Some(self.password.clone()), message) { + Ok(ok) => Ok(ok), + Err(e) => Err(ethkey::Error::InvalidSecret), + } + } + + fn address(&self) -> Address { + self.address + } +} + diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index 4695682e3c..6adb114f36 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -18,7 +18,6 @@ use std::fmt; -use ethcore::account_provider::SignError as AccountError; use ethcore::error::{Error as EthcoreError, ErrorKind, CallError}; use ethcore::client::BlockId; use jsonrpc_core::{futures, Result as RpcResult, Error, ErrorCode, Value}; @@ -30,6 +29,7 @@ use light::on_demand::error::{Error as OnDemandError, ErrorKind as OnDemandError use ethcore::client::BlockChainClient; use types::blockchain_info::BlockChainInfo; use v1::types::BlockNumber; +use v1::impls::EthClientOptions; mod codes { // NOTE [ToDr] Codes from [-32099, -32000] @@ -44,7 +44,9 @@ mod codes { pub const EXECUTION_ERROR: i64 = -32015; pub const EXCEPTION_ERROR: i64 = -32016; pub const DATABASE_ERROR: i64 = -32017; + #[cfg(any(test, feature = "accounts"))] pub const ACCOUNT_LOCKED: i64 = -32020; + #[cfg(any(test, feature = "accounts"))] pub const PASSWORD_INVALID: i64 = -32021; pub const ACCOUNT_ERROR: i64 = -32023; pub const PRIVATE_ERROR: i64 = -32024; @@ -58,6 +60,7 @@ mod codes { pub const NO_PEERS: i64 = -32066; pub const DEPRECATED: i64 = -32070; pub const EXPERIMENTAL_RPC: i64 = -32071; + pub const CANNOT_RESTART: i64 = -32080; } pub fn unimplemented(details: Option) -> Error { @@ -124,6 +127,14 @@ pub fn account(error: &str, details: T) -> Error { } } +pub fn cannot_restart() -> Error { + Error { + code: ErrorCode::ServerError(codes::CANNOT_RESTART), + message: "Parity could not be restarted. This feature is disabled in development mode and if the binary name isn't parity.".into(), + data: None, + } +} + /// Internal error signifying a logic error in code. /// Should not be used when function can just fail /// because of invalid parameters or incomplete node state. @@ -163,11 +174,11 @@ pub fn state_corrupt() -> Error { internal("State corrupt", "") } -pub fn exceptional() -> Error { +pub fn exceptional(data: T) -> Error { Error { code: ErrorCode::ServerError(codes::EXCEPTION_ERROR), message: "The execution failed due to an exception.".into(), - data: None, + data: Some(Value::String(data.to_string())), } } @@ -211,18 +222,34 @@ pub fn cannot_submit_work(err: EthcoreError) -> Error { } } -pub fn unavailable_block() -> Error { - Error { - code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), - message: "Ancient block sync is still in progress".into(), - data: None, +pub fn unavailable_block(no_ancient_block: bool, by_hash: bool) -> Error { + if no_ancient_block { + Error { + code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), + message: "Looks like you disabled ancient block download, unfortunately the information you're \ + trying to fetch doesn't exist in the db and is probably in the ancient blocks.".into(), + data: None, + } + } else if by_hash { + Error { + code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), + message: "Block information is incomplete while ancient block sync is still in progress, before \ + it's finished we can't determine the existence of requested item.".into(), + data: None, + } + } else { + Error { + code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), + message: "Requested block number is in a range that is not available yet, because the ancient block sync is still in progress.".into(), + data: None, + } } } pub fn check_block_number_existence<'a, T, C>( client: &'a C, num: BlockNumber, - allow_missing_blocks: bool, + options: EthClientOptions, ) -> impl Fn(Option) -> RpcResult> + 'a where C: BlockChainClient, @@ -232,8 +259,8 @@ pub fn check_block_number_existence<'a, T, C>( if let BlockNumber::Num(block_number) = num { // tried to fetch block number and got nothing even though the block number is // less than the latest block number - if block_number < client.chain_info().best_block_number && !allow_missing_blocks { - return Err(unavailable_block()); + if block_number < client.chain_info().best_block_number && !options.allow_missing_blocks { + return Err(unavailable_block(options.no_ancient_blocks, false)); } } } @@ -243,22 +270,17 @@ pub fn check_block_number_existence<'a, T, C>( pub fn check_block_gap<'a, T, C>( client: &'a C, - allow_missing_blocks: bool, + options: EthClientOptions, ) -> impl Fn(Option) -> RpcResult> + 'a where C: BlockChainClient, { move |response| { - if response.is_none() && !allow_missing_blocks { + if response.is_none() && !options.allow_missing_blocks { let BlockChainInfo { ancient_block_hash, .. } = client.chain_info(); // block information was requested, but unfortunately we couldn't find it and there // are gaps in the database ethcore/src/blockchain/blockchain.rs if ancient_block_hash.is_some() { - return Err(Error { - code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), - message: "Block information is incomplete while ancient block sync is still in progress, before \ - it's finished we can't determine the existence of requested item.".into(), - data: None, - }) + return Err(unavailable_block(options.no_ancient_blocks, true)) } } Ok(response) @@ -337,14 +359,7 @@ pub fn fetch(error: T) -> Error { } } -pub fn signing(error: AccountError) -> Error { - Error { - code: ErrorCode::ServerError(codes::ACCOUNT_LOCKED), - message: "Your account is locked. Unlock the account via CLI, personal_unlockAccount or use Trusted Signer.".into(), - data: Some(Value::String(format!("{:?}", error))), - } -} - +#[cfg(any(test, feature = "accounts"))] pub fn invalid_call_data(error: T) -> Error { Error { code: ErrorCode::ServerError(codes::ENCODING_ERROR), @@ -353,7 +368,17 @@ pub fn invalid_call_data(error: T) -> Error { } } -pub fn password(error: AccountError) -> Error { +#[cfg(any(test, feature = "accounts"))] +pub fn signing(error: ::accounts::SignError) -> Error { + Error { + code: ErrorCode::ServerError(codes::ACCOUNT_LOCKED), + message: "Your account is locked. Unlock the account via CLI, personal_unlockAccount or use Trusted Signer.".into(), + data: Some(Value::String(format!("{:?}", error))), + } +} + +#[cfg(any(test, feature = "accounts"))] +pub fn password(error: ::accounts::SignError) -> Error { Error { code: ErrorCode::ServerError(codes::PASSWORD_INVALID), message: "Account password is invalid or account does not exist.".into(), @@ -383,8 +408,11 @@ pub fn transaction_message(error: &TransactionError) -> String { match *error { AlreadyImported => "Transaction with the same hash was already imported.".into(), Old => "Transaction nonce is too low. Try incrementing the nonce.".into(), - TooCheapToReplace => { - "Transaction gas price is too low. There is another transaction with same nonce in the queue. Try increasing the gas price or incrementing the nonce.".into() + TooCheapToReplace { prev, new } => { + format!("Transaction gas price {} is too low. There is another transaction with same nonce in the queue{}. Try increasing the gas price or incrementing the nonce.", + new.map(|gas| format!("{}wei", gas)).unwrap_or("supplied".into()), + prev.map(|gas| format!(" with gas price: {}wei", gas)).unwrap_or("".into()) + ) } LimitReached => { "There are too many transactions in the queue. Your transaction was dropped due to limit. Try increasing the fee.".into() @@ -454,7 +482,7 @@ pub fn call(error: CallError) -> Error { match error { CallError::StatePruned => state_pruned(), CallError::StateCorrupt => state_corrupt(), - CallError::Exceptional => exceptional(), + CallError::Exceptional(e) => exceptional(e), CallError::Execution(e) => execution(e), CallError::TransactionNotFound => internal("{}, this should not be the case with eth_call, most likely a bug.", CallError::TransactionNotFound), } diff --git a/rpc/src/v1/helpers/signer.rs b/rpc/src/v1/helpers/external_signer/mod.rs similarity index 70% rename from rpc/src/v1/helpers/signer.rs rename to rpc/src/v1/helpers/external_signer/mod.rs index 0cb13bd7f5..0797929cbd 100644 --- a/rpc/src/v1/helpers/signer.rs +++ b/rpc/src/v1/helpers/external_signer/mod.rs @@ -14,23 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +//! An list of requests to be confirmed or signed by an external approver/signer. + use std::sync::Arc; use std::ops::Deref; -use http::Origin; -use parking_lot::Mutex; -use transient_hashmap::TransientHashMap; - -use ethstore::random_string; -use v1::helpers::signing_queue::{ConfirmationsQueue}; +mod oneshot; +mod signing_queue; -const TOKEN_LIFETIME_SECS: u32 = 3600; +pub use self::signing_queue::{SigningQueue, ConfirmationsQueue, ConfirmationReceiver, ConfirmationResult}; +#[cfg(test)] +pub use self::signing_queue::QueueEvent; /// Manages communication with Signer crate pub struct SignerService { is_enabled: bool, queue: Arc, - web_proxy_tokens: Mutex>, generate_new_token: Box Result + Send + Sync + 'static>, } @@ -40,26 +39,11 @@ impl SignerService { where F: Fn() -> Result + Send + Sync + 'static { SignerService { queue: Arc::new(ConfirmationsQueue::default()), - web_proxy_tokens: Mutex::new(TransientHashMap::new(TOKEN_LIFETIME_SECS)), generate_new_token: Box::new(new_token), - is_enabled: is_enabled, + is_enabled, } } - /// Checks if the token is valid web proxy access token. - pub fn web_proxy_access_token_domain(&self, token: &String) -> Option { - self.web_proxy_tokens.lock().get(token).cloned() - } - - /// Generates a new web proxy access token. - pub fn generate_web_proxy_access_token(&self, domain: Origin) -> String { - let token = random_string(16); - let mut tokens = self.web_proxy_tokens.lock(); - tokens.prune(); - tokens.insert(token.clone(), domain); - token - } - /// Generates new signer authorization token. pub fn generate_token(&self) -> Result { (self.generate_new_token)() diff --git a/rpc/src/v1/helpers/oneshot.rs b/rpc/src/v1/helpers/external_signer/oneshot.rs similarity index 98% rename from rpc/src/v1/helpers/oneshot.rs rename to rpc/src/v1/helpers/external_signer/oneshot.rs index 623691d399..eac3dca7f8 100644 --- a/rpc/src/v1/helpers/oneshot.rs +++ b/rpc/src/v1/helpers/external_signer/oneshot.rs @@ -28,7 +28,7 @@ pub struct Sender { impl Sender { pub fn send(self, data: Res) { let res = self.sender.send(data); - if let Err(_) = res { + if res.is_err() { debug!(target: "rpc", "Responding to a no longer active request."); } } diff --git a/rpc/src/v1/helpers/signing_queue.rs b/rpc/src/v1/helpers/external_signer/signing_queue.rs similarity index 93% rename from rpc/src/v1/helpers/signing_queue.rs rename to rpc/src/v1/helpers/external_signer/signing_queue.rs index 3429f2fa2b..00a459a869 100644 --- a/rpc/src/v1/helpers/signing_queue.rs +++ b/rpc/src/v1/helpers/external_signer/signing_queue.rs @@ -15,28 +15,19 @@ // along with Parity Ethereum. If not, see . use std::collections::BTreeMap; -use ethereum_types::{U256, Address}; + +use ethereum_types::U256; use parking_lot::{Mutex, RwLock}; -use v1::helpers::{ConfirmationRequest, ConfirmationPayload, oneshot, errors}; -use v1::types::{ConfirmationResponse, H160 as RpcH160, Origin}; +use super::oneshot; +use v1::helpers::errors; +use v1::helpers::requests::{ConfirmationRequest, ConfirmationPayload}; +use v1::types::{ConfirmationResponse, Origin}; use jsonrpc_core::Error; /// Result that can be returned from JSON RPC. pub type ConfirmationResult = Result; -/// Type of default account -pub enum DefaultAccount { - /// Default account is known - Provided(Address), -} - -impl From for DefaultAccount { - fn from(address: RpcH160) -> Self { - DefaultAccount::Provided(address.into()) - } -} - /// Possible events happening in the queue that can be listened to. #[derive(Debug, PartialEq, Clone)] pub enum QueueEvent { @@ -130,7 +121,7 @@ impl ConfirmationsQueue { )); // notify confirmation receiver about resolution - let result = result.ok_or(errors::request_rejected()); + let result = result.ok_or_else(errors::request_rejected); sender.sender.send(result); Some(sender.request) @@ -159,7 +150,7 @@ impl SigningQueue for ConfirmationsQueue { // Increment id let id = { let mut last_id = self.id.lock(); - *last_id = *last_id + U256::from(1); + *last_id += U256::from(1); *last_id }; // Add request to queue @@ -225,9 +216,8 @@ mod test { use ethereum_types::{U256, Address}; use parking_lot::Mutex; use jsonrpc_core::futures::Future; - use v1::helpers::{ - SigningQueue, ConfirmationsQueue, QueueEvent, FilledTransactionRequest, ConfirmationPayload, - }; + use v1::helpers::external_signer::{SigningQueue, ConfirmationsQueue, QueueEvent}; + use v1::helpers::{FilledTransactionRequest, ConfirmationPayload}; use v1::types::ConfirmationResponse; fn request() -> ConfirmationPayload { @@ -299,3 +289,4 @@ mod test { assert_eq!(el.payload, request); } } + diff --git a/rpc/src/v1/helpers/fake_sign.rs b/rpc/src/v1/helpers/fake_sign.rs index 76d37aab2f..d93408b89a 100644 --- a/rpc/src/v1/helpers/fake_sign.rs +++ b/rpc/src/v1/helpers/fake_sign.rs @@ -15,25 +15,23 @@ // along with Parity Ethereum. If not, see . use types::transaction::{Transaction, SignedTransaction, Action}; +use std::cmp::min; use ethereum_types::U256; use jsonrpc_core::Error; use v1::helpers::CallRequest; pub fn sign_call(request: CallRequest) -> Result { - let max_gas = U256::from(50_000_000); - let gas = match request.gas { - Some(gas) => gas, - None => max_gas * 10u32, - }; - let from = request.from.unwrap_or(0.into()); + let max_gas = U256::from(500_000_000); + let gas = min(request.gas.unwrap_or(max_gas), max_gas); + let from = request.from.unwrap_or_default(); Ok(Transaction { - nonce: request.nonce.unwrap_or_else(|| 0.into()), + nonce: request.nonce.unwrap_or_default(), action: request.to.map_or(Action::Create, Action::Call), gas, - gas_price: request.gas_price.unwrap_or_else(|| 0.into()), - value: request.value.unwrap_or(0.into()), + gas_price: request.gas_price.unwrap_or_default(), + value: request.value.unwrap_or_default(), data: request.data.unwrap_or_default(), }.fake_sign(from)) } diff --git a/rpc/src/v1/helpers/ipfs.rs b/rpc/src/v1/helpers/ipfs.rs index 928362cf89..93110dbf34 100644 --- a/rpc/src/v1/helpers/ipfs.rs +++ b/rpc/src/v1/helpers/ipfs.rs @@ -28,5 +28,5 @@ pub fn cid(content: Bytes) -> Result { let hash = digest::sha256(&content.0); let mh = multihash::encode(multihash::Hash::SHA2256, &*hash).map_err(errors::encoding)?; let cid = Cid::new(Codec::DagProtobuf, Version::V0, &mh); - Ok(cid.to_string().into()) + Ok(cid.to_string()) } diff --git a/rpc/src/v1/helpers/light_fetch.rs b/rpc/src/v1/helpers/light_fetch.rs index ba6e13b167..819f566455 100644 --- a/rpc/src/v1/helpers/light_fetch.rs +++ b/rpc/src/v1/helpers/light_fetch.rs @@ -16,7 +16,9 @@ //! Helpers for fetching blockchain data either from the light client or the network. +use std::clone::Clone; use std::cmp; +use std::collections::BTreeMap; use std::sync::Arc; use types::basic_account::BasicAccount; @@ -29,34 +31,38 @@ use ethcore::executed::ExecutionError; use jsonrpc_core::{Result, Error}; use jsonrpc_core::futures::{future, Future}; use jsonrpc_core::futures::future::Either; -use jsonrpc_macros::Trailing; use light::cache::Cache; use light::client::LightChainClient; use light::{cht, MAX_HEADERS_PER_REQUEST}; use light::on_demand::{ - request, OnDemand, HeaderRef, Request as OnDemandRequest, + request, OnDemandRequester, HeaderRef, Request as OnDemandRequest, Response as OnDemandResponse, ExecutionResult, }; use light::on_demand::error::Error as OnDemandError; use light::request::Field; +use light::TransactionQueue; + +use sync::{LightNetworkDispatcher, ManageNetwork, LightSyncProvider}; -use sync::LightSync; -use ethereum_types::{U256, Address}; +use ethereum_types::{Address, U256}; use hash::H256; -use parking_lot::Mutex; +use parking_lot::{Mutex, RwLock}; use fastmap::H256FastMap; -use std::collections::BTreeMap; use types::transaction::{Action, Transaction as EthTransaction, PendingTransaction, SignedTransaction, LocalizedTransaction}; use v1::helpers::{CallRequest as CallRequestHelper, errors, dispatch}; use v1::types::{BlockNumber, CallRequest, Log, Transaction}; const NO_INVALID_BACK_REFS_PROOF: &str = "Fails only on invalid back-references; back-references here known to be valid; qed"; - const WRONG_RESPONSE_AMOUNT_TYPE_PROOF: &str = "responses correspond directly with requests in amount and type; qed"; +const DEFAULT_GAS_PRICE: u64 = 21_000; -pub fn light_all_transactions(dispatch: &Arc) -> impl Iterator { +pub fn light_all_transactions(dispatch: &Arc>) -> impl Iterator +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ let txq = dispatch.transaction_queue.read(); let chain_info = dispatch.client.chain_info(); @@ -67,20 +73,40 @@ pub fn light_all_transactions(dispatch: &Arc) -> impl /// Helper for fetching blockchain data either from the light client or the network /// as necessary. -#[derive(Clone)] -pub struct LightFetch { +pub struct LightFetch +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ /// The light client. pub client: Arc, /// The on-demand request service. - pub on_demand: Arc, + pub on_demand: Arc, /// Handle to the network. - pub sync: Arc, + pub sync: Arc, /// The light data cache. pub cache: Arc>, /// Gas Price percentile pub gas_price_percentile: usize, } +impl Clone for LightFetch +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ + fn clone(&self) -> Self { + Self { + client: self.client.clone(), + on_demand: self.on_demand.clone(), + sync: self.sync.clone(), + cache: self.cache.clone(), + gas_price_percentile: self.gas_price_percentile, + } + } +} + + /// Extract a transaction at given index. pub fn extract_transaction_at_index(block: encoded::Block, index: usize) -> Option { block.transactions().into_iter().nth(index) @@ -101,7 +127,7 @@ pub fn extract_transaction_at_index(block: encoded::Block, index: usize) -> Opti cached_sender, } }) - .map(|tx| Transaction::from_localized(tx)) + .map(Transaction::from_localized) } // extract the header indicated by the given `HeaderRef` from the given responses. @@ -116,7 +142,11 @@ fn extract_header(res: &[OnDemandResponse], header: HeaderRef) -> Option LightFetch +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ // push the necessary requests onto the request chain to get the header by the given ID. // yield a header reference which other requests can use. fn make_header_requests(&self, id: BlockId, reqs: &mut Vec) -> Result { @@ -136,7 +166,7 @@ impl LightFetch { let idx = reqs.len(); let hash_ref = Field::back_ref(idx, 0); reqs.push(req.into()); - reqs.push(request::HeaderByHash(hash_ref.clone()).into()); + reqs.push(request::HeaderByHash(hash_ref).into()); Ok(HeaderRef::Unresolved(idx + 1, hash_ref)) } @@ -174,7 +204,7 @@ impl LightFetch { Err(e) => return Either::A(future::err(e)), }; - reqs.push(request::Account { header: header_ref.clone(), address: address }.into()); + reqs.push(request::Account { header: header_ref.clone(), address }.into()); let account_idx = reqs.len() - 1; reqs.push(request::Code { header: header_ref, code_hash: Field::back_ref(account_idx, 0) }.into()); @@ -186,24 +216,41 @@ impl LightFetch { /// Helper for getting account info at a given block. /// `None` indicates the account doesn't exist at the given block. - pub fn account(&self, address: Address, id: BlockId) -> impl Future, Error = Error> + Send { + pub fn account( + &self, + address: Address, + id: BlockId, + tx_queue: Arc> + ) -> impl Future, Error = Error> + Send { + let mut reqs = Vec::new(); let header_ref = match self.make_header_requests(id, &mut reqs) { Ok(r) => r, Err(e) => return Either::A(future::err(e)), }; - reqs.push(request::Account { header: header_ref, address: address }.into()); + reqs.push(request::Account { header: header_ref, address }.into()); - Either::B(self.send_requests(reqs, |mut res|match res.pop() { - Some(OnDemandResponse::Account(acc)) => acc, + Either::B(self.send_requests(reqs, move |mut res| match res.pop() { + Some(OnDemandResponse::Account(maybe_account)) => { + if let Some(ref acc) = maybe_account { + let mut txq = tx_queue.write(); + txq.cull(address, acc.nonce); + } + maybe_account + } _ => panic!(WRONG_RESPONSE_AMOUNT_TYPE_PROOF), })) } /// Helper for getting proved execution. - pub fn proved_read_only_execution(&self, req: CallRequest, num: Trailing) -> impl Future + Send { - const DEFAULT_GAS_PRICE: u64 = 21_000; + pub fn proved_read_only_execution( + &self, + req: CallRequest, + num: Option, + txq: Arc> + ) -> impl Future + Send { + // (21000 G_transaction + 32000 G_create + some marginal to allow a few operations) const START_GAS: u64 = 60_000; @@ -223,24 +270,15 @@ impl LightFetch { } }; - let from = req.from.unwrap_or_else(|| Address::zero()); + let from = req.from.unwrap_or_default(); let nonce_fut = match req.nonce { Some(nonce) => Either::A(future::ok(Some(nonce))), - None => Either::B(self.account(from, id).map(|acc| acc.map(|a| a.nonce))), + None => Either::B(self.account(from, id, txq).map(|acc| acc.map(|a| a.nonce))), }; - let gas_price_percentile = self.gas_price_percentile; let gas_price_fut = match req.gas_price { Some(price) => Either::A(future::ok(price)), - None => Either::B(dispatch::fetch_gas_price_corpus( - self.sync.clone(), - self.client.clone(), - self.on_demand.clone(), - self.cache.clone(), - ).map(move |corp| match corp.percentile(gas_price_percentile) { - Some(percentile) => *percentile, - None => DEFAULT_GAS_PRICE.into(), - })) + None => Either::B(self.gas_price()), }; // if nonce resolves, this should too since it'll be in the LRU-cache. @@ -254,7 +292,7 @@ impl LightFetch { action: req.to.map_or(Action::Create, Action::Call), gas: req.gas.unwrap_or_else(|| START_GAS.into()), gas_price, - value: req.value.unwrap_or_else(U256::zero), + value: req.value.unwrap_or_default(), data: req.data.unwrap_or_default(), })) ) @@ -279,6 +317,23 @@ impl LightFetch { })) } + /// Helper to fetch the corpus gas price from 1) the cache 2) the network then it tries to estimate the percentile + /// using `gas_price_percentile` if the estimated percentile is zero the `DEFAULT_GAS_PRICE` is returned + pub fn gas_price(&self) -> impl Future + Send { + let gas_price_percentile = self.gas_price_percentile; + + dispatch::light::fetch_gas_price_corpus( + self.sync.clone(), + self.client.clone(), + self.on_demand.clone(), + self.cache.clone(), + ) + .map(move |corp| { + corp.percentile(gas_price_percentile) + .map_or_else(|| DEFAULT_GAS_PRICE.into(), |percentile| *percentile) + }) + } + /// Get a block itself. Fails on unknown block ID. pub fn block(&self, id: BlockId) -> impl Future + Send { let mut reqs = Vec::new(); @@ -347,10 +402,10 @@ impl LightFetch { for (transaction_log_index, log) in receipt.logs.into_iter().enumerate() { if filter.matches(&log) { matches.insert((num, block_index), Log { - address: log.address.into(), + address: log.address, topics: log.topics.into_iter().map(Into::into).collect(), data: log.data.into(), - block_hash: Some(hash.into()), + block_hash: Some(hash), block_number: Some(num.into()), // No way to easily retrieve transaction hash, so let's just skip it. transaction_hash: None, @@ -364,7 +419,7 @@ impl LightFetch { block_index += 1; } } - future::ok::<_,OnDemandError>(matches) + future::ok::<_, OnDemandError>(matches) }) .map_err(errors::on_demand_error) .map(|matches| matches.into_iter().map(|(_, v)| v).collect()) @@ -387,8 +442,8 @@ impl LightFetch { let mut blocks = BTreeMap::new(); for log in result.iter() { let block_hash = log.block_hash.as_ref().expect("Previously initialized with value; qed"); - blocks.entry(block_hash.clone()).or_insert_with(|| { - fetcher_block.block(BlockId::Hash(block_hash.clone().into())) + blocks.entry(*block_hash).or_insert_with(|| { + fetcher_block.block(BlockId::Hash(*block_hash)) }); } // future get blocks (unordered it) @@ -396,12 +451,12 @@ impl LightFetch { let transactions_per_block: BTreeMap<_, _> = blocks.iter() .map(|block| (block.hash(), block.transactions())).collect(); for log in result.iter_mut() { - let log_index: U256 = log.transaction_index.expect("Previously initialized with value; qed").into(); - let block_hash = log.block_hash.clone().expect("Previously initialized with value; qed").into(); + let log_index = log.transaction_index.expect("Previously initialized with value; qed"); + let block_hash = log.block_hash.expect("Previously initialized with value; qed"); let tx_hash = transactions_per_block.get(&block_hash) // transaction index is from an enumerate call in log common so not need to check value .and_then(|txs| txs.get(log_index.as_usize())) - .map(|tr| tr.hash().into()); + .map(types::transaction::UnverifiedTransaction::hash); log.transaction_hash = tx_hash; } result @@ -419,7 +474,7 @@ impl LightFetch { Box::new(future::loop_fn(params, move |(sync, on_demand)| { let maybe_future = sync.with_context(|ctx| { - let req = request::TransactionIndex(tx_hash.clone().into()); + let req = request::TransactionIndex(tx_hash.into()); on_demand.request(ctx, req) }); @@ -445,7 +500,7 @@ impl LightFetch { let index = index.index as usize; let transaction = extract_transaction_at_index(blk, index); - if transaction.as_ref().map_or(true, |tx| tx.hash != tx_hash.into()) { + if transaction.as_ref().map_or(true, |tx| tx.hash != tx_hash) { // index is actively wrong: indicated block has // fewer transactions than necessary or the transaction // at that index had a different hash. @@ -468,6 +523,46 @@ impl LightFetch { })) } + /// Helper to cull the `light` transaction queue of mined transactions + pub fn light_cull(&self, txq: Arc>) -> impl Future + Send { + let senders = txq.read().queued_senders(); + if senders.is_empty() { + return Either::B(future::err(errors::internal("No pending local transactions", ""))); + } + + let sync = self.sync.clone(); + let on_demand = self.on_demand.clone(); + let best_header = self.client.best_block_header(); + let start_nonce = self.client.engine().account_start_nonce(best_header.number()); + + let account_request = sync.with_context(move |ctx| { + // fetch the nonce of each sender in the queue. + let nonce_reqs = senders.iter() + .map(|&address| request::Account { header: best_header.clone().into(), address }) + .collect::>(); + + // when they come in, update each sender to the new nonce. + on_demand.request(ctx, nonce_reqs) + .expect(NO_INVALID_BACK_REFS_PROOF) + .map(move |accs| { + let mut txq = txq.write(); + accs.into_iter() + .map(|maybe_acc| maybe_acc.map_or(start_nonce, |acc| acc.nonce)) + .zip(senders) + .for_each(|(nonce, addr)| { + txq.cull(addr, nonce); + }); + }) + .map_err(errors::on_demand_error) + }); + + if let Some(fut) = account_request { + Either::A(fut) + } else { + Either::B(future::err(errors::network_disabled())) + } + } + fn send_requests(&self, reqs: Vec, parse_response: F) -> impl Future + Send where F: FnOnce(Vec) -> T + Send + 'static, T: Send + 'static, @@ -499,7 +594,7 @@ impl LightFetch { ) -> impl Future, Error = Error> { let fetch_hashes = [from_block, to_block].iter() .filter_map(|block_id| match block_id { - BlockId::Hash(hash) => Some(hash.clone()), + BlockId::Hash(hash) => Some(*hash), _ => None, }) .collect::>(); @@ -510,14 +605,14 @@ impl LightFetch { self.headers_by_hash(&fetch_hashes[..]).and_then(move |mut header_map| { let (from_block_num, to_block_num) = { let block_number = |id| match id { - &BlockId::Earliest => 0, - &BlockId::Latest => best_number, - &BlockId::Hash(ref h) => - header_map.get(h).map(|hdr| hdr.number()) + BlockId::Earliest => 0, + BlockId::Latest => best_number, + BlockId::Hash(ref h) => + header_map.get(h).map(types::encoded::Header::number) .expect("from_block and to_block headers are fetched by hash; this closure is only called on from_block and to_block; qed"), - &BlockId::Number(x) => x, + BlockId::Number(x) => x, }; - (block_number(&from_block), block_number(&to_block)) + (block_number(from_block), block_number(to_block)) }; if to_block_num < from_block_num { @@ -534,7 +629,7 @@ impl LightFetch { let headers_fut = fetcher.headers_range(from_block_num, to_block_num, to_header_hint); Either::B(headers_fut.map(move |headers| { // Validate from_block if it's a hash - let last_hash = headers.last().map(|hdr| hdr.hash()); + let last_hash = headers.last().map(types::encoded::Header::hash); match (last_hash, from_block) { (Some(h1), BlockId::Hash(h2)) if h1 != h2 => Vec::new(), _ => headers, @@ -555,15 +650,13 @@ impl LightFetch { } self.send_requests(reqs, move |res| { - let headers = refs.drain() - .map(|(hash, header_ref)| { + refs.into_iter().map(|(hash, header_ref)| { let hdr = extract_header(&res, header_ref) .expect("these responses correspond to requests that header_ref belongs to; \ qed"); (hash, hdr) - }) - .collect(); - headers + }) + .collect() }) } @@ -636,20 +729,45 @@ impl LightFetch { } } -#[derive(Clone)] -struct ExecuteParams { +struct ExecuteParams +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ from: Address, tx: EthTransaction, hdr: encoded::Header, env_info: ::vm::EnvInfo, engine: Arc<::ethcore::engines::EthEngine>, - on_demand: Arc, - sync: Arc, + on_demand: Arc, + sync: Arc, +} + +impl Clone for ExecuteParams +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ + fn clone(&self) -> Self { + Self { + from: self.from, + tx: self.tx.clone(), + hdr: self.hdr.clone(), + env_info: self.env_info.clone(), + engine: self.engine.clone(), + on_demand: self.on_demand.clone(), + sync: self.sync.clone() + } + } } // Has a peer execute the transaction with given params. If `gas_known` is false, this will set the `gas value` to the // `required gas value` unless it exceeds the block gas limit -fn execute_read_only_tx(gas_known: bool, params: ExecuteParams) -> impl Future + Send { +fn execute_read_only_tx(gas_known: bool, params: ExecuteParams) -> impl Future + Send +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ if !gas_known { Box::new(future::loop_fn(params, |mut params| { execute_read_only_tx(true, params.clone()).and_then(move |res| { @@ -674,7 +792,7 @@ fn execute_read_only_tx(gas_known: bool, params: ExecuteParams) -> impl Future. -use ethereum_types::{U256, Address}; +use ethereum_types::{U256, H256, Address}; use bytes::Bytes; use v1::types::{Origin, TransactionCondition}; -use ethereum_types::H256; /// Transaction request coming from RPC #[derive(Debug, Clone, Default, Eq, PartialEq, Hash)] diff --git a/rpc/src/v1/helpers/secretstore.rs b/rpc/src/v1/helpers/secretstore.rs index d8a60d592c..6e1cbca45d 100644 --- a/rpc/src/v1/helpers/secretstore.rs +++ b/rpc/src/v1/helpers/secretstore.rs @@ -16,12 +16,13 @@ use std::collections::BTreeSet; use rand::{Rng, OsRng}; +use ethereum_types::{H256, H512}; use ethkey::{self, Public, Secret, Random, Generator, math}; use crypto; use bytes::Bytes; use jsonrpc_core::Error; use v1::helpers::errors; -use v1::types::{H256, H512, EncryptedDocumentKey}; +use v1::types::EncryptedDocumentKey; use tiny_keccak::Keccak; /// Initialization vector length. diff --git a/rpc/src/v1/helpers/signature.rs b/rpc/src/v1/helpers/signature.rs index c684523fea..b191a3737e 100644 --- a/rpc/src/v1/helpers/signature.rs +++ b/rpc/src/v1/helpers/signature.rs @@ -15,8 +15,9 @@ // along with Parity Ethereum. If not, see . use ethkey::{recover, public_to_address, Signature}; +use ethereum_types::{H256, U64}; use jsonrpc_core::Result; -use v1::types::{Bytes, RecoveredAccount, H256, U64}; +use v1::types::{Bytes, RecoveredAccount}; use v1::helpers::errors; use v1::helpers::dispatch::eth_data_hash; use hash::keccak; @@ -35,7 +36,7 @@ pub fn verify_signature( } else { keccak(message.0) }; - let v: u64 = v.into(); + let v = v.as_u64(); let is_valid_for_current_chain = match (chain_id, v) { (None, v) if v == 0 || v == 1 => true, (Some(chain_id), v) if v >= 35 => (v - 35) / 2 == chain_id, @@ -44,7 +45,7 @@ pub fn verify_signature( let v = if v >= 35 { (v - 1) % 2 } else { v }; - let signature = Signature::from_rsv(&r.into(), &s.into(), v as u8); + let signature = Signature::from_rsv(&r, &s, v as u8); let public_key = recover(&signature, &hash).map_err(errors::encryption)?; let address = public_to_address(&public_key); Ok(RecoveredAccount { address, public_key, is_valid_for_current_chain }) @@ -53,9 +54,8 @@ pub fn verify_signature( #[cfg(test)] mod tests { use super::*; - use std::sync::Arc; - use ethcore::account_provider::AccountProvider; - use v1::types::H160; + use ethkey::Generator; + use ethereum_types::{H160, U64}; pub fn add_chain_replay_protection(v: u64, chain_id: Option) -> u64 { v + if let Some(n) = chain_id { 35 + n * 2 } else { 0 } @@ -71,9 +71,9 @@ mod tests { /// mocked signer fn sign(should_prefix: bool, data: Vec, signing_chain_id: Option) -> (H160, [u8; 32], [u8; 32], U64) { let hash = if should_prefix { eth_data_hash(data) } else { keccak(data) }; - let accounts = Arc::new(AccountProvider::transient_provider()); - let address = accounts.new_account(&"password123".into()).unwrap(); - let sig = accounts.sign(address, Some("password123".into()), hash).unwrap(); + let account = ethkey::Random.generate().unwrap(); + let address = account.address(); + let sig = ethkey::sign(account.secret(), &hash).unwrap(); let (r, s, v) = (sig.r(), sig.s(), sig.v()); let v = add_chain_replay_protection(v as u64, signing_chain_id); let (r_buf, s_buf) = { diff --git a/rpc/src/v1/helpers/subscribers.rs b/rpc/src/v1/helpers/subscribers.rs index 80a6bfe8b1..9483d8e321 100644 --- a/rpc/src/v1/helpers/subscribers.rs +++ b/rpc/src/v1/helpers/subscribers.rs @@ -18,9 +18,9 @@ use std::{ops, str}; use std::collections::HashMap; -use jsonrpc_macros::pubsub::{Subscriber, Sink, SubscriptionId}; +use jsonrpc_pubsub::{typed::{Subscriber, Sink}, SubscriptionId}; +use ethereum_types::H64; use rand::{Rng, StdRng}; -use v1::types::H64; #[derive(Debug, Clone, Hash, Eq, PartialEq)] pub struct Id(H64); @@ -36,8 +36,9 @@ impl str::FromStr for Id { } } impl Id { + // TODO: replace `format!` see [#10412](https://github.com/paritytech/parity-ethereum/issues/10412) pub fn as_string(&self) -> String { - format!("0x{:?}", self.0) + format!("{:?}", self.0) } } diff --git a/rpc/src/v1/helpers/subscription_manager.rs b/rpc/src/v1/helpers/subscription_manager.rs index 4f50cad423..d83beb397f 100644 --- a/rpc/src/v1/helpers/subscription_manager.rs +++ b/rpc/src/v1/helpers/subscription_manager.rs @@ -52,7 +52,7 @@ impl> GenericPollManager { pub fn new(rpc: MetaIoHandler) -> Self { GenericPollManager { subscribers: Default::default(), - rpc: rpc, + rpc, } } diff --git a/rpc/src/v1/helpers/work.rs b/rpc/src/v1/helpers/work.rs index 0a90d446ee..b52cb70c5f 100644 --- a/rpc/src/v1/helpers/work.rs +++ b/rpc/src/v1/helpers/work.rs @@ -20,28 +20,19 @@ use std::sync::Arc; use rlp; use ethcore::miner::{BlockChainClient, MinerService}; -use ethereum_types::{H64 as EthcoreH64, H256 as EthcoreH256}; +use ethereum_types::{H64, H256}; use jsonrpc_core::Error; -use v1::types::{H64, H256}; use v1::helpers::errors; // Submit a POW work and return the block's hash pub fn submit_work_detail(client: &Arc, miner: &Arc, nonce: H64, pow_hash: H256, mix_hash: H256) -> Result { // TODO [ToDr] Should disallow submissions in case of PoA? - let nonce: EthcoreH64 = nonce.into(); - let pow_hash: EthcoreH256 = pow_hash.into(); - let mix_hash: EthcoreH256 = mix_hash.into(); trace!(target: "miner", "submit_work_detail: Decoded: nonce={}, pow_hash={}, mix_hash={}", nonce, pow_hash, mix_hash); let seal = vec![rlp::encode(&mix_hash), rlp::encode(&nonce)]; - let import = miner.submit_seal(pow_hash, seal) - .and_then(|block| client.import_sealed_block(block)); - match import { - Ok(hash) => { - Ok(hash.into()) - }, - Err(err) => { - warn!(target: "miner", "Cannot submit work - {:?}.", err); - Err(errors::cannot_submit_work(err)) - }, - } + miner.submit_seal(pow_hash, seal) + .and_then(|block| client.import_sealed_block(block)) + .map_err(|e| { + warn!(target: "miner", "Cannot submit work - {:?}.", e); + errors::cannot_submit_work(e) + }) } diff --git a/rpc/src/v1/impls/debug.rs b/rpc/src/v1/impls/debug.rs index abec9b1f87..e46dd628d1 100644 --- a/rpc/src/v1/impls/debug.rs +++ b/rpc/src/v1/impls/debug.rs @@ -19,6 +19,7 @@ use std::sync::Arc; use ethcore::client::BlockChainClient; +use types::header::Header; use types::transaction::LocalizedTransaction; use jsonrpc_core::Result; @@ -50,7 +51,7 @@ impl Debug for DebugClient { let hash = block.header.hash(); RichBlock { inner: Block { - hash: Some(hash.into()), + hash: Some(hash), size: Some(block.bytes.len().into()), parent_hash: cast(block.header.parent_hash()), uncles_hash: cast(block.header.uncles_hash()), @@ -65,14 +66,14 @@ impl Debug for DebugClient { timestamp: block.header.timestamp().into(), difficulty: cast(block.header.difficulty()), total_difficulty: None, - seal_fields: block.header.seal().into_iter().cloned().map(Into::into).collect(), - uncles: block.uncles.into_iter().map(|u| u.hash().into()).collect(), + seal_fields: block.header.seal().iter().cloned().map(Into::into).collect(), + uncles: block.uncles.iter().map(Header::hash).collect(), transactions: BlockTransactions::Full(block.transactions .into_iter() .enumerate() .map(|(transaction_index, signed)| Transaction::from_localized(LocalizedTransaction { - block_number: number.into(), - block_hash: hash.into(), + block_number: number, + block_hash: hash, transaction_index, signed, cached_sender: None, diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index bf39557d1a..734e70a61c 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -21,11 +21,10 @@ use std::time::{Instant, Duration, SystemTime, UNIX_EPOCH}; use std::sync::Arc; use rlp::Rlp; -use ethereum_types::{U256, H256, H160, Address}; +use ethereum_types::{Address, H64, H160, H256, U64, U256}; use parking_lot::Mutex; use ethash::{self, SeedHashCompute}; -use ethcore::account_provider::AccountProvider; use ethcore::client::{BlockChainClient, BlockId, TransactionId, UncleId, StateOrBlock, StateClient, StateInfo, Call, EngineInfo, ProvingBlockChainClient}; use ethcore::miner::{self, MinerService}; use ethcore::snapshot::SnapshotService; @@ -39,23 +38,23 @@ use types::filter::Filter as EthcoreFilter; use jsonrpc_core::{BoxFuture, Result}; use jsonrpc_core::futures::future; -use jsonrpc_macros::Trailing; use v1::helpers::{self, errors, limit_logs, fake_sign}; +use v1::helpers::deprecated::{self, DeprecationNotice}; use v1::helpers::dispatch::{FullDispatcher, default_gas_price}; use v1::helpers::block_import::is_major_importing; use v1::traits::Eth; use v1::types::{ RichBlock, Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, CallRequest, Index, Filter, Log, Receipt, Work, EthAccount, StorageProof, - H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256, block_number_to_id, - U64 as RpcU64, + block_number_to_id }; use v1::metadata::Metadata; const EXTRA_INFO_PROOF: &str = "Object exists in blockchain (fetched earlier), extra_info is always available if object exists; qed"; /// Eth RPC options +#[derive(Copy, Clone)] pub struct EthClientOptions { /// Return nonce from transaction queue when pending block not available. pub pending_nonce_from_queue: bool, @@ -70,6 +69,8 @@ pub struct EthClientOptions { pub allow_missing_blocks: bool, /// Enable Experimental RPC-Calls pub allow_experimental_rpcs: bool, + /// flag for ancient block sync + pub no_ancient_blocks: bool, } impl EthClientOptions { @@ -91,6 +92,7 @@ impl Default for EthClientOptions { gas_price_percentile: 50, allow_missing_blocks: false, allow_experimental_rpcs: false, + no_ancient_blocks: false, } } } @@ -106,11 +108,12 @@ pub struct EthClient where client: Arc, snapshot: Arc, sync: Arc, - accounts: Arc, + accounts: Arc Vec

+ Send + Sync>, miner: Arc, external_miner: Arc, seed_compute: Mutex, options: EthClientOptions, + deprecation_notice: DeprecationNotice, } #[derive(Debug)] @@ -185,7 +188,7 @@ impl EthClient, snapshot: &Arc, sync: &Arc, - accounts: &Arc, + accounts: &Arc Vec
+ Send + Sync>, miner: &Arc, em: &Arc, options: EthClientOptions @@ -198,7 +201,8 @@ impl EthClient EthClient None, - false => Some(view.hash().into()), + false => Some(view.hash()), }, size: Some(block.rlp().as_raw().len().into()), - parent_hash: view.parent_hash().into(), - uncles_hash: view.uncles_hash().into(), - author: view.author().into(), - miner: view.author().into(), - state_root: view.state_root().into(), - transactions_root: view.transactions_root().into(), - receipts_root: view.receipts_root().into(), + parent_hash: view.parent_hash(), + uncles_hash: view.uncles_hash(), + author: view.author(), + miner: view.author(), + state_root: view.state_root(), + transactions_root: view.transactions_root(), + receipts_root: view.receipts_root(), number: match is_pending { true => None, false => Some(view.number().into()), }, - gas_used: view.gas_used().into(), - gas_limit: view.gas_limit().into(), + gas_used: view.gas_used(), + gas_limit: view.gas_limit(), logs_bloom: match is_pending { true => None, - false => Some(view.log_bloom().into()), + false => Some(view.log_bloom()), }, timestamp: view.timestamp().into(), - difficulty: view.difficulty().into(), - total_difficulty: Some(total_difficulty.into()), + difficulty: view.difficulty(), + total_difficulty: Some(total_difficulty), seal_fields: view.seal().into_iter().map(Into::into).collect(), - uncles: block.uncle_hashes().into_iter().map(Into::into).collect(), + uncles: block.uncle_hashes(), transactions: match include_txs { - true => BlockTransactions::Full(block.view().localized_transactions().into_iter().map(|t| Transaction::from_localized(t)).collect()), - false => BlockTransactions::Hashes(block.transaction_hashes().into_iter().map(Into::into).collect()), + true => BlockTransactions::Full(block.view().localized_transactions().into_iter().map(Transaction::from_localized).collect()), + false => BlockTransactions::Hashes(block.transaction_hashes()), }, extra_data: Bytes::new(view.extra_data()), }, @@ -334,7 +338,7 @@ impl EthClient EthClient { return Ok(None); } }; - let parent_difficulty = match client.block_total_difficulty(BlockId::Hash(uncle.parent_hash().clone())) { + let parent_difficulty = match client.block_total_difficulty(BlockId::Hash(*uncle.parent_hash())) { Some(difficulty) => difficulty, None => { return Ok(None); } }; @@ -398,29 +402,28 @@ impl EthClient(miner: &M, best_block: EthBlockNumber, filter: &EthcoreFi .filter(|pair| filter.matches(&pair.1)) .map(|pair| { let mut log = Log::from(pair.1); - log.transaction_hash = Some(pair.0.into()); + log.transaction_hash = Some(pair.0); log }) .collect() @@ -518,8 +521,8 @@ impl Eth for EthClient< let info = SyncInfo { starting_block: status.start_block_number.into(), - current_block: current_block.into(), - highest_block: highest_block.into(), + current_block, + highest_block, warp_chunks_amount: warp_chunks_amount.map(|x| U256::from(x as u64)).map(Into::into), warp_chunks_processed: warp_chunks_processed.map(|x| U256::from(x as u64)).map(Into::into), }; @@ -529,16 +532,15 @@ impl Eth for EthClient< } } - fn author(&self) -> Result { + fn author(&self) -> Result { let miner = self.miner.authoring_params().author; if miner == 0.into() { - self.accounts.accounts() - .ok() - .and_then(|a| a.first().cloned()) - .map(From::from) + (self.accounts)() + .first() + .cloned() .ok_or_else(|| errors::account("No accounts were found", "")) } else { - Ok(RpcH160::from(miner)) + Ok(miner) } } @@ -546,47 +548,45 @@ impl Eth for EthClient< Ok(self.miner.is_currently_sealing()) } - fn chain_id(&self) -> Result> { - Ok(self.client.signing_chain_id().map(RpcU64::from)) + fn chain_id(&self) -> Result> { + Ok(self.client.signing_chain_id().map(U64::from)) } - fn hashrate(&self) -> Result { - Ok(RpcU256::from(self.external_miner.hashrate())) + fn hashrate(&self) -> Result { + Ok(self.external_miner.hashrate()) } - fn gas_price(&self) -> Result { - Ok(RpcU256::from(default_gas_price(&*self.client, &*self.miner, self.options.gas_price_percentile))) + fn gas_price(&self) -> BoxFuture { + Box::new(future::ok(default_gas_price(&*self.client, &*self.miner, self.options.gas_price_percentile))) } - fn accounts(&self) -> Result> { - let accounts = self.accounts.accounts() - .map_err(|e| errors::account("Could not fetch accounts.", e))?; - Ok(accounts.into_iter().map(Into::into).collect()) - } + fn accounts(&self) -> Result> { + self.deprecation_notice.print("eth_accounts", deprecated::msgs::ACCOUNTS); - fn block_number(&self) -> Result { - Ok(RpcU256::from(self.client.chain_info().best_block_number)) + let accounts = (self.accounts)(); + Ok(accounts) } - fn balance(&self, address: RpcH160, num: Trailing) -> BoxFuture { - let address = address.into(); + fn block_number(&self) -> Result { + Ok(U256::from(self.client.chain_info().best_block_number)) + } + fn balance(&self, address: H160, num: Option) -> BoxFuture { let num = num.unwrap_or_default(); try_bf!(check_known(&*self.client, num.clone())); let res = match self.client.balance(&address, self.get_state(num)) { - Some(balance) => Ok(balance.into()), + Some(balance) => Ok(balance), None => Err(errors::state_pruned()), }; Box::new(future::done(res)) } - fn proof(&self, address: RpcH160, values: Vec, num: Trailing) -> BoxFuture { + fn proof(&self, address: H160, values: Vec, num: Option) -> BoxFuture { try_bf!(errors::require_experimental(self.options.allow_experimental_rpcs, "1186")); - let a: H160 = address.clone().into(); - let key1 = keccak(a); + let key1 = keccak(address); let num = num.unwrap_or_default(); let id = match num { @@ -594,24 +594,24 @@ impl Eth for EthClient< BlockNumber::Earliest => BlockId::Earliest, BlockNumber::Latest => BlockId::Latest, BlockNumber::Pending => { - warn!("`Pending` is deprecated and may be removed in future versions. Falling back to `Latest`"); + self.deprecation_notice.print("`Pending`", Some("falling back to `Latest`")); BlockId::Latest } }; try_bf!(check_known(&*self.client, num.clone())); let res = match self.client.prove_account(key1, id) { - Some((proof,account)) => Ok(EthAccount { - address: address, - balance: account.balance.into(), - nonce: account.nonce.into(), - code_hash: account.code_hash.into(), - storage_hash: account.storage_root.into(), + Some((proof, account)) => Ok(EthAccount { + address, + balance: account.balance, + nonce: account.nonce, + code_hash: account.code_hash, + storage_hash: account.storage_root, account_proof: proof.into_iter().map(Bytes::new).collect(), storage_proof: values.into_iter().filter_map(|storage_index| { - let key2: H256 = storage_index.into(); + let key2: H256 = storage_index; self.client.prove_storage(key1, keccak(key2), id) - .map(|(storage_proof,storage_value)| StorageProof { + .map(|(storage_proof, storage_value)| StorageProof { key: key2.into(), value: storage_value.into(), proof: storage_proof.into_iter().map(Bytes::new).collect() @@ -625,27 +625,22 @@ impl Eth for EthClient< Box::new(future::done(res)) } - fn storage_at(&self, address: RpcH160, pos: RpcU256, num: Trailing) -> BoxFuture { - let address: Address = RpcH160::into(address); - let position: U256 = RpcU256::into(pos); - + fn storage_at(&self, address: H160, position: U256, num: Option) -> BoxFuture { let num = num.unwrap_or_default(); try_bf!(check_known(&*self.client, num.clone())); let res = match self.client.storage_at(&address, &H256::from(position), self.get_state(num)) { - Some(s) => Ok(s.into()), + Some(s) => Ok(s), None => Err(errors::state_pruned()), }; Box::new(future::done(res)) } - fn transaction_count(&self, address: RpcH160, num: Trailing) -> BoxFuture { - let address: Address = RpcH160::into(address); - + fn transaction_count(&self, address: H160, num: Option) -> BoxFuture { let res = match num.unwrap_or_default() { BlockNumber::Pending if self.options.pending_nonce_from_queue => { - Ok(self.miner.next_nonce(&*self.client, &address).into()) + Ok(self.miner.next_nonce(&*self.client, &address)) } BlockNumber::Pending => { let info = self.client.chain_info(); @@ -658,14 +653,14 @@ impl Eth for EthClient< }); match nonce { - Some(nonce) => Ok(nonce.into()), + Some(nonce) => Ok(nonce), None => Err(errors::database("latest nonce missing")) } }, number => { try_bf!(check_known(&*self.client, number.clone())); match self.client.nonce(&address, block_number_to_id(number)) { - Some(nonce) => Ok(nonce.into()), + Some(nonce) => Ok(nonce), None => Err(errors::state_pruned()), } } @@ -674,15 +669,15 @@ impl Eth for EthClient< Box::new(future::done(res)) } - fn block_transaction_count_by_hash(&self, hash: RpcH256) -> BoxFuture> { - let trx_count = self.client.block(BlockId::Hash(hash.into())) + fn block_transaction_count_by_hash(&self, hash: H256) -> BoxFuture> { + let trx_count = self.client.block(BlockId::Hash(hash)) .map(|block| block.transactions_count().into()); let result = Ok(trx_count) - .and_then(errors::check_block_gap(&*self.client, self.options.allow_missing_blocks)); + .and_then(errors::check_block_gap(&*self.client, self.options)); Box::new(future::done(result)) } - fn block_transaction_count_by_number(&self, num: BlockNumber) -> BoxFuture> { + fn block_transaction_count_by_number(&self, num: BlockNumber) -> BoxFuture> { Box::new(future::done(match num { BlockNumber::Pending => Ok(Some(self.miner.pending_transaction_hashes(&*self.client).len().into())), @@ -693,21 +688,21 @@ impl Eth for EthClient< .and_then(errors::check_block_number_existence( &*self.client, num, - self.options.allow_missing_blocks + self.options )) } })) } - fn block_uncles_count_by_hash(&self, hash: RpcH256) -> BoxFuture> { - let uncle_count = self.client.block(BlockId::Hash(hash.into())) + fn block_uncles_count_by_hash(&self, hash: H256) -> BoxFuture> { + let uncle_count = self.client.block(BlockId::Hash(hash)) .map(|block| block.uncles_count().into()); let result = Ok(uncle_count) - .and_then(errors::check_block_gap(&*self.client, self.options.allow_missing_blocks)); + .and_then(errors::check_block_gap(&*self.client, self.options)); Box::new(future::done(result)) } - fn block_uncles_count_by_number(&self, num: BlockNumber) -> BoxFuture> { + fn block_uncles_count_by_number(&self, num: BlockNumber) -> BoxFuture> { Box::new(future::done(match num { BlockNumber::Pending => Ok(Some(0.into())), _ => { @@ -717,14 +712,14 @@ impl Eth for EthClient< .and_then(errors::check_block_number_existence( &*self.client, num, - self.options.allow_missing_blocks + self.options )) } })) } - fn code_at(&self, address: RpcH160, num: Trailing) -> BoxFuture { - let address: Address = RpcH160::into(address); + fn code_at(&self, address: H160, num: Option) -> BoxFuture { + let address: Address = H160::into(address); let num = num.unwrap_or_default(); try_bf!(check_known(&*self.client, num.clone())); @@ -737,33 +732,32 @@ impl Eth for EthClient< Box::new(future::done(res)) } - fn block_by_hash(&self, hash: RpcH256, include_txs: bool) -> BoxFuture> { - let result = self.rich_block(BlockId::Hash(hash.into()).into(), include_txs) - .and_then(errors::check_block_gap(&*self.client, self.options.allow_missing_blocks)); + fn block_by_hash(&self, hash: H256, include_txs: bool) -> BoxFuture> { + let result = self.rich_block(BlockId::Hash(hash).into(), include_txs) + .and_then(errors::check_block_gap(&*self.client, self.options)); Box::new(future::done(result)) } fn block_by_number(&self, num: BlockNumber, include_txs: bool) -> BoxFuture> { let result = self.rich_block(num.clone().into(), include_txs).and_then( - errors::check_block_number_existence(&*self.client, num, self.options.allow_missing_blocks)); + errors::check_block_number_existence(&*self.client, num, self.options)); Box::new(future::done(result)) } - fn transaction_by_hash(&self, hash: RpcH256) -> BoxFuture> { - let hash: H256 = hash.into(); + fn transaction_by_hash(&self, hash: H256) -> BoxFuture> { let tx = try_bf!(self.transaction(PendingTransactionId::Hash(hash))).or_else(|| { self.miner.transaction(&hash) .map(|t| Transaction::from_pending(t.pending().clone())) }); let result = Ok(tx).and_then( - errors::check_block_gap(&*self.client, self.options.allow_missing_blocks)); + errors::check_block_gap(&*self.client, self.options)); Box::new(future::done(result)) } - fn transaction_by_block_hash_and_index(&self, hash: RpcH256, index: Index) -> BoxFuture> { - let id = PendingTransactionId::Location(PendingOrBlock::Block(BlockId::Hash(hash.into())), index.value()); + fn transaction_by_block_hash_and_index(&self, hash: H256, index: Index) -> BoxFuture> { + let id = PendingTransactionId::Location(PendingOrBlock::Block(BlockId::Hash(hash)), index.value()); let result = self.transaction(id).and_then( - errors::check_block_gap(&*self.client, self.options.allow_missing_blocks)); + errors::check_block_gap(&*self.client, self.options)); Box::new(future::done(result)) } @@ -777,13 +771,11 @@ impl Eth for EthClient< let transaction_id = PendingTransactionId::Location(block_id, index.value()); let result = self.transaction(transaction_id).and_then( - errors::check_block_number_existence(&*self.client, num, self.options.allow_missing_blocks)); + errors::check_block_number_existence(&*self.client, num, self.options)); Box::new(future::done(result)) } - fn transaction_receipt(&self, hash: RpcH256) -> BoxFuture> { - let hash: H256 = hash.into(); - + fn transaction_receipt(&self, hash: H256) -> BoxFuture> { if self.options.allow_pending_receipt_query { let best_block = self.client.chain_info().best_block_number; if let Some(receipt) = self.miner.pending_receipt(best_block, &hash) { @@ -793,15 +785,15 @@ impl Eth for EthClient< let receipt = self.client.transaction_receipt(TransactionId::Hash(hash)); let result = Ok(receipt.map(Into::into)) - .and_then(errors::check_block_gap(&*self.client, self.options.allow_missing_blocks)); + .and_then(errors::check_block_gap(&*self.client, self.options)); Box::new(future::done(result)) } - fn uncle_by_block_hash_and_index(&self, hash: RpcH256, index: Index) -> BoxFuture> { + fn uncle_by_block_hash_and_index(&self, hash: H256, index: Index) -> BoxFuture> { let result = self.uncle(PendingUncleId { - id: PendingOrBlock::Block(BlockId::Hash(hash.into())), + id: PendingOrBlock::Block(BlockId::Hash(hash)), position: index.value() - }).and_then(errors::check_block_gap(&*self.client, self.options.allow_missing_blocks)); + }).and_then(errors::check_block_gap(&*self.client, self.options)); Box::new(future::done(result)) } @@ -818,7 +810,7 @@ impl Eth for EthClient< .and_then(errors::check_block_number_existence( &*self.client, num, - self.options.allow_missing_blocks + self.options )); Box::new(future::done(result)) @@ -829,10 +821,10 @@ impl Eth for EthClient< } fn logs(&self, filter: Filter) -> BoxFuture> { - base_logs(&*self.client, &*self.miner, filter.into()) + base_logs(&*self.client, &*self.miner, filter) } - fn work(&self, no_new_work_timeout: Trailing) -> Result { + fn work(&self, no_new_work_timeout: Option) -> Result { let no_new_work_timeout = no_new_work_timeout.unwrap_or_default(); // check if we're still syncing and return empty strings in that case @@ -872,34 +864,34 @@ impl Eth for EthClient< Err(errors::no_new_work()) } else if self.options.send_block_number_in_get_work { Ok(Work { - pow_hash: pow_hash.into(), + pow_hash, seed_hash: seed_hash.into(), - target: target.into(), + target, number: Some(number), }) } else { Ok(Work { - pow_hash: pow_hash.into(), + pow_hash, seed_hash: seed_hash.into(), - target: target.into(), + target, number: None }) } } - fn submit_work(&self, nonce: RpcH64, pow_hash: RpcH256, mix_hash: RpcH256) -> Result { + fn submit_work(&self, nonce: H64, pow_hash: H256, mix_hash: H256) -> Result { match helpers::submit_work_detail(&self.client, &self.miner, nonce, pow_hash, mix_hash) { Ok(_) => Ok(true), Err(_) => Ok(false), } } - fn submit_hashrate(&self, rate: RpcU256, id: RpcH256) -> Result { - self.external_miner.submit_hashrate(rate.into(), id.into()); + fn submit_hashrate(&self, rate: U256, id: H256) -> Result { + self.external_miner.submit_hashrate(rate, id); Ok(true) } - fn send_raw_transaction(&self, raw: Bytes) -> Result { + fn send_raw_transaction(&self, raw: Bytes) -> Result { Rlp::new(&raw.into_vec()).as_val() .map_err(errors::rlp) .and_then(|tx| SignedTransaction::new(tx).map_err(errors::transaction)) @@ -914,11 +906,11 @@ impl Eth for EthClient< .map(Into::into) } - fn submit_transaction(&self, raw: Bytes) -> Result { + fn submit_transaction(&self, raw: Bytes) -> Result { self.send_raw_transaction(raw) } - fn call(&self, request: CallRequest, num: Trailing) -> BoxFuture { + fn call(&self, request: CallRequest, num: Option) -> BoxFuture { let request = CallRequest::into(request); let signed = try_bf!(fake_sign::sign_call(request)); @@ -926,8 +918,8 @@ impl Eth for EthClient< let (mut state, header) = if num == BlockNumber::Pending { let info = self.client.chain_info(); - let state = try_bf!(self.miner.pending_state(info.best_block_number).ok_or(errors::state_pruned())); - let header = try_bf!(self.miner.pending_block_header(info.best_block_number).ok_or(errors::state_pruned())); + let state = try_bf!(self.miner.pending_state(info.best_block_number).ok_or_else(errors::state_pruned)); + let header = try_bf!(self.miner.pending_block_header(info.best_block_number).ok_or_else(errors::state_pruned)); (state, header) } else { @@ -938,8 +930,8 @@ impl Eth for EthClient< BlockNumber::Pending => unreachable!(), // Already covered }; - let state = try_bf!(self.client.state_at(id).ok_or(errors::state_pruned())); - let header = try_bf!(self.client.block_header(id).ok_or(errors::state_pruned()).and_then(|h| h.decode().map_err(errors::decode))); + let state = try_bf!(self.client.state_at(id).ok_or_else(errors::state_pruned)); + let header = try_bf!(self.client.block_header(id).ok_or_else(errors::state_pruned).and_then(|h| h.decode().map_err(errors::decode))); (state, header) }; @@ -958,15 +950,17 @@ impl Eth for EthClient< )) } - fn estimate_gas(&self, request: CallRequest, num: Trailing) -> BoxFuture { + fn estimate_gas(&self, request: CallRequest, num: Option) -> BoxFuture { let request = CallRequest::into(request); let signed = try_bf!(fake_sign::sign_call(request)); let num = num.unwrap_or_default(); let (state, header) = if num == BlockNumber::Pending { let info = self.client.chain_info(); - let state = try_bf!(self.miner.pending_state(info.best_block_number).ok_or(errors::state_pruned())); - let header = try_bf!(self.miner.pending_block_header(info.best_block_number).ok_or(errors::state_pruned())); + let state = try_bf!(self.miner.pending_state(info.best_block_number) + .ok_or_else(errors::state_pruned)); + let header = try_bf!(self.miner.pending_block_header(info.best_block_number) + .ok_or_else(errors::state_pruned)); (state, header) } else { @@ -977,14 +971,15 @@ impl Eth for EthClient< BlockNumber::Pending => unreachable!(), // Already covered }; - let state = try_bf!(self.client.state_at(id).ok_or(errors::state_pruned())); - let header = try_bf!(self.client.block_header(id).ok_or(errors::state_pruned()).and_then(|h| h.decode().map_err(errors::decode))); - + let state = try_bf!(self.client.state_at(id) + .ok_or_else(errors::state_pruned)); + let header = try_bf!(self.client.block_header(id) + .ok_or_else(errors::state_pruned) + .and_then(|h| h.decode().map_err(errors::decode))); (state, header) }; Box::new(future::done(self.client.estimate_gas(&signed, &state, &header) - .map(Into::into) .map_err(errors::call) )) } diff --git a/rpc/src/v1/impls/eth_filter.rs b/rpc/src/v1/impls/eth_filter.rs index 20a0d27400..c51c85fb62 100644 --- a/rpc/src/v1/impls/eth_filter.rs +++ b/rpc/src/v1/impls/eth_filter.rs @@ -21,7 +21,7 @@ use std::collections::{BTreeSet, VecDeque}; use ethcore::client::{BlockChainClient, BlockId}; use ethcore::miner::{self, MinerService}; -use ethereum_types::H256; +use ethereum_types::{H256, U256}; use parking_lot::Mutex; use types::filter::Filter as EthcoreFilter; @@ -29,7 +29,7 @@ use jsonrpc_core::{BoxFuture, Result}; use jsonrpc_core::futures::{future, Future}; use jsonrpc_core::futures::future::Either; use v1::traits::EthFilter; -use v1::types::{BlockNumber, Index, Filter, FilterChanges, Log, H256 as RpcH256, U256 as RpcU256}; +use v1::types::{BlockNumber, Index, Filter, FilterChanges, Log}; use v1::helpers::{errors, SyncPollFilter, PollFilter, PollManager, limit_logs}; use v1::impls::eth::pending_logs; @@ -68,8 +68,8 @@ impl EthFilterClient { /// Creates new Eth filter client. pub fn new(client: Arc, miner: Arc, poll_lifetime: u32) -> Self { EthFilterClient { - client: client, - miner: miner, + client, + miner, polls: Mutex::new(PollManager::new(poll_lifetime)), } } @@ -137,7 +137,7 @@ impl Filterable for EthFilterClient where } impl EthFilter for T { - fn new_filter(&self, filter: Filter) -> Result { + fn new_filter(&self, filter: Filter) -> Result { let mut polls = self.polls().lock(); let block_number = self.best_block_number(); let include_pending = filter.to_block == Some(BlockNumber::Pending); @@ -150,7 +150,7 @@ impl EthFilter for T { Ok(id.into()) } - fn new_block_filter(&self) -> Result { + fn new_block_filter(&self) -> Result { let mut polls = self.polls().lock(); // +1, since we don't want to include the current block let id = polls.create_poll(SyncPollFilter::new(PollFilter::Block { @@ -160,7 +160,7 @@ impl EthFilter for T { Ok(id.into()) } - fn new_pending_transaction_filter(&self) -> Result { + fn new_pending_transaction_filter(&self) -> Result { let mut polls = self.polls().lock(); let pending_transactions = self.pending_transaction_hashes(); let id = polls.create_poll(SyncPollFilter::new(PollFilter::PendingTransaction(pending_transactions))); @@ -188,17 +188,14 @@ impl EthFilter for T { let mut hashes = Vec::new(); for n in (*last_block_number + 1)..=current_number { let block_number = BlockId::Number(n); - match self.block_hash(block_number) { - Some(hash) => { - *last_block_number = n; - hashes.push(RpcH256::from(hash)); - // Only keep the most recent history - if recent_reported_hashes.len() >= PollFilter::MAX_BLOCK_HISTORY_SIZE { - recent_reported_hashes.pop_back(); - } - recent_reported_hashes.push_front((n, hash)); - }, - None => (), + if let Some(hash) = self.block_hash(block_number) { + *last_block_number = n; + hashes.push(hash); + // Only keep the most recent history + if recent_reported_hashes.len() >= PollFilter::MAX_BLOCK_HISTORY_SIZE { + recent_reported_hashes.pop_back(); + } + recent_reported_hashes.push_front((n, hash)); } } diff --git a/rpc/src/v1/impls/eth_pubsub.rs b/rpc/src/v1/impls/eth_pubsub.rs index 86340d73d4..4507281578 100644 --- a/rpc/src/v1/impls/eth_pubsub.rs +++ b/rpc/src/v1/impls/eth_pubsub.rs @@ -21,9 +21,7 @@ use std::collections::BTreeMap; use jsonrpc_core::{BoxFuture, Result, Error}; use jsonrpc_core::futures::{self, Future, IntoFuture}; -use jsonrpc_macros::Trailing; -use jsonrpc_macros::pubsub::{Sink, Subscriber}; -use jsonrpc_pubsub::SubscriptionId; +use jsonrpc_pubsub::{SubscriptionId, typed::{Sink, Subscriber}}; use v1::helpers::{errors, limit_logs, Subscribers}; use v1::helpers::light_fetch::LightFetch; @@ -35,10 +33,12 @@ use ethcore::client::{BlockChainClient, ChainNotify, NewBlocks, ChainRouteType, use ethereum_types::H256; use light::cache::Cache; use light::client::{LightChainClient, LightChainNotify}; -use light::on_demand::OnDemand; +use light::on_demand::OnDemandRequester; use parity_runtime::Executor; use parking_lot::{RwLock, Mutex}; -use sync::LightSync; + +use sync::{LightSyncProvider, LightNetworkDispatcher, ManageNetwork}; + use types::encoded; use types::filter::Filter as EthFilter; @@ -89,12 +89,16 @@ impl EthPubSubClient { } } -impl EthPubSubClient { +impl EthPubSubClient> +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ /// Creates a new `EthPubSubClient` for `LightClient`. pub fn light( client: Arc, - on_demand: Arc, - sync: Arc, + on_demand: Arc, + sync: Arc, cache: Arc>, executor: Executor, gas_price_percentile: usize, @@ -131,10 +135,10 @@ impl ChainNotificationHandler { fn notify_heads(&self, headers: &[(encoded::Header, BTreeMap)]) { for subscriber in self.heads_subscribers.read().values() { for &(ref header, ref extra_info) in headers { - Self::notify(&self.executor, subscriber, pubsub::Result::Header(RichHeader { + Self::notify(&self.executor, subscriber, pubsub::Result::Header(Box::new(RichHeader { inner: header.into(), extra_info: extra_info.clone(), - })); + }))); } } } @@ -151,7 +155,7 @@ impl ChainNotificationHandler { .map(|&(hash, ref ex)| { let mut filter = filter.clone(); filter.from_block = BlockId::Hash(hash); - filter.to_block = filter.from_block.clone(); + filter.to_block = filter.from_block; logs(filter, ex).into_future() }) .collect::>() @@ -164,7 +168,7 @@ impl ChainNotificationHandler { let logs = logs.into_iter().flat_map(|log| log).collect(); for log in limit_logs(logs, limit) { - Self::notify(&executor, &subscriber, pubsub::Result::Log(log)) + Self::notify(&executor, &subscriber, pubsub::Result::Log(Box::new(log))) } }) .map_err(|e| warn!("Unable to fetch latest logs: {:?}", e)) @@ -176,7 +180,7 @@ impl ChainNotificationHandler { pub fn notify_new_transactions(&self, hashes: &[H256]) { for subscriber in self.transactions_subscribers.read().values() { for hash in hashes { - Self::notify(&self.executor, subscriber, pubsub::Result::TransactionHash((*hash).into())); + Self::notify(&self.executor, subscriber, pubsub::Result::TransactionHash(*hash)); } } } @@ -191,7 +195,11 @@ pub trait LightClient: Send + Sync { fn logs(&self, filter: EthFilter) -> BoxFuture>; } -impl LightClient for LightFetch { +impl LightClient for LightFetch +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ fn block_header(&self, id: BlockId) -> Option { self.client.block_header(id) } @@ -202,10 +210,7 @@ impl LightClient for LightFetch { } impl LightChainNotify for ChainNotificationHandler { - fn new_headers( - &self, - enacted: &[H256], - ) { + fn new_headers(&self, enacted: &[H256]) { let headers = enacted .iter() .filter_map(|hash| self.client.block_header(BlockId::Hash(*hash))) @@ -220,13 +225,13 @@ impl LightChainNotify for ChainNotificationHandler { impl ChainNotify for ChainNotificationHandler { fn new_blocks(&self, new_blocks: NewBlocks) { if self.heads_subscribers.read().is_empty() && self.logs_subscribers.read().is_empty() { return } - const EXTRA_INFO_PROOF: &'static str = "Object exists in in blockchain (fetched earlier), extra_info is always available if object exists; qed"; + const EXTRA_INFO_PROOF: &str = "Object exists in in blockchain (fetched earlier), extra_info is always available if object exists; qed"; let headers = new_blocks.route.route() .iter() .filter_map(|&(hash, ref typ)| { match typ { - &ChainRouteType::Retracted => None, - &ChainRouteType::Enacted => self.client.block_header(BlockId::Hash(hash)) + ChainRouteType::Retracted => None, + ChainRouteType::Enacted => self.client.block_header(BlockId::Hash(hash)) } }) .map(|header| { @@ -241,9 +246,9 @@ impl ChainNotify for ChainNotificationHandler { // We notify logs enacting and retracting as the order in route. self.notify_logs(new_blocks.route.route(), |filter, ex| { match ex { - &ChainRouteType::Enacted => + ChainRouteType::Enacted => Ok(self.client.logs(filter).unwrap_or_default().into_iter().map(Into::into).collect()), - &ChainRouteType::Retracted => + ChainRouteType::Retracted => Ok(self.client.logs(filter).unwrap_or_default().into_iter().map(Into::into).map(|mut log: Log| { log.log_type = "removed".into(); log.removed = true; @@ -262,9 +267,9 @@ impl EthPubSub for EthPubSubClient { _meta: Metadata, subscriber: Subscriber, kind: pubsub::Kind, - params: Trailing, + params: Option, ) { - let error = match (kind, params.into()) { + let error = match (kind, params) { (pubsub::Kind::NewHeads, None) => { self.heads_subscribers.write().push(subscriber); return; @@ -299,7 +304,7 @@ impl EthPubSub for EthPubSubClient { let _ = subscriber.reject(error); } - fn unsubscribe(&self, id: SubscriptionId) -> Result { + fn unsubscribe(&self, _: Option, id: SubscriptionId) -> Result { let res = self.heads_subscribers.write().remove(&id).is_some(); let res2 = self.logs_subscribers.write().remove(&id).is_some(); let res3 = self.transactions_subscribers.write().remove(&id).is_some(); diff --git a/rpc/src/v1/impls/light/eth.rs b/rpc/src/v1/impls/light/eth.rs index 87e87c3098..6467bfbc78 100644 --- a/rpc/src/v1/impls/light/eth.rs +++ b/rpc/src/v1/impls/light/eth.rs @@ -22,53 +22,55 @@ use std::sync::Arc; use jsonrpc_core::{Result, BoxFuture}; use jsonrpc_core::futures::{future, Future}; use jsonrpc_core::futures::future::Either; -use jsonrpc_macros::Trailing; use light::cache::Cache as LightDataCache; use light::client::LightChainClient; use light::{cht, TransactionQueue}; -use light::on_demand::{request, OnDemand}; +use light::on_demand::{request, OnDemandRequester}; -use ethcore::account_provider::AccountProvider; -use ethereum_types::U256; +use ethereum_types::{Address, H64, H160, H256, U64, U256}; use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY_LIST_RLP}; use parking_lot::{RwLock, Mutex}; use rlp::Rlp; -use sync::LightSync; use types::transaction::SignedTransaction; use types::encoded; use types::filter::Filter as EthcoreFilter; use types::ids::BlockId; use v1::impls::eth_filter::Filterable; -use v1::helpers::{errors, limit_logs}; -use v1::helpers::{SyncPollFilter, PollManager}; +use v1::helpers::{errors, limit_logs, SyncPollFilter, PollManager}; +use v1::helpers::deprecated::{self, DeprecationNotice}; use v1::helpers::light_fetch::{self, LightFetch}; use v1::traits::Eth; use v1::types::{ - RichBlock, Block, BlockTransactions, BlockNumber, LightBlockNumber, Bytes, SyncStatus, SyncInfo, - Transaction, CallRequest, Index, Filter, Log, Receipt, Work, EthAccount, - H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256, - U64 as RpcU64, + RichBlock, Block, BlockTransactions, BlockNumber, LightBlockNumber, Bytes, SyncStatus as RpcSyncStatus, + SyncInfo as RpcSyncInfo, Transaction, CallRequest, Index, Filter, Log, Receipt, Work, EthAccount }; use v1::metadata::Metadata; +use sync::{LightSyncInfo, LightSyncProvider, LightNetworkDispatcher, ManageNetwork}; + const NO_INVALID_BACK_REFS: &str = "Fails only on invalid back-references; back-references here known to be valid; qed"; /// Light client `ETH` (and filter) RPC. -pub struct EthClient { - sync: Arc, - client: Arc, - on_demand: Arc, +pub struct EthClient { + sync: Arc, + client: Arc, + on_demand: Arc, transaction_queue: Arc>, - accounts: Arc, + accounts: Arc Vec
+ Send + Sync>, cache: Arc>, polls: Mutex>, poll_lifetime: u32, gas_price_percentile: usize, + deprecation_notice: DeprecationNotice, } -impl Clone for EthClient { +impl Clone for EthClient +where + S: LightSyncProvider + LightNetworkDispatcher + 'static, + OD: OnDemandRequester + 'static +{ fn clone(&self) -> Self { // each instance should have its own poll manager. EthClient { @@ -81,19 +83,25 @@ impl Clone for EthClient { polls: Mutex::new(PollManager::new(self.poll_lifetime)), poll_lifetime: self.poll_lifetime, gas_price_percentile: self.gas_price_percentile, + deprecation_notice: Default::default(), } } } -impl EthClient { +impl EthClient +where + C: LightChainClient + 'static, + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ /// Create a new `EthClient` with a handle to the light sync instance, client, /// and on-demand request service, which is assumed to be attached as a handler. pub fn new( - sync: Arc, - client: Arc, - on_demand: Arc, + sync: Arc, + client: Arc, + on_demand: Arc, transaction_queue: Arc>, - accounts: Arc, + accounts: Arc Vec
+ Send + Sync>, cache: Arc>, gas_price_percentile: usize, poll_lifetime: u32 @@ -108,11 +116,13 @@ impl EthClient { polls: Mutex::new(PollManager::new(poll_lifetime)), poll_lifetime, gas_price_percentile, + deprecation_notice: Default::default(), } } /// Create a light data fetcher instance. - fn fetcher(&self) -> LightFetch { + fn fetcher(&self) -> LightFetch + { LightFetch { client: self.client.clone(), on_demand: self.on_demand.clone(), @@ -133,23 +143,23 @@ impl EthClient { let extra_info = engine.extra_info(&header); RichBlock { inner: Block { - hash: Some(header.hash().into()), + hash: Some(header.hash()), size: Some(block.rlp().as_raw().len().into()), - parent_hash: header.parent_hash().clone().into(), - uncles_hash: header.uncles_hash().clone().into(), - author: header.author().clone().into(), - miner: header.author().clone().into(), - state_root: header.state_root().clone().into(), - transactions_root: header.transactions_root().clone().into(), - receipts_root: header.receipts_root().clone().into(), + parent_hash: *header.parent_hash(), + uncles_hash: *header.uncles_hash(), + author: *header.author(), + miner: *header.author(), + state_root: *header.state_root(), + transactions_root: *header.transactions_root(), + receipts_root: *header.receipts_root(), number: Some(header.number().into()), - gas_used: header.gas_used().clone().into(), - gas_limit: header.gas_limit().clone().into(), - logs_bloom: Some(header.log_bloom().clone().into()), + gas_used: *header.gas_used(), + gas_limit: *header.gas_limit(), + logs_bloom: Some(*header.log_bloom()), timestamp: header.timestamp().into(), - difficulty: header.difficulty().clone().into(), + difficulty: *header.difficulty(), total_difficulty: score.map(Into::into), - seal_fields: header.seal().into_iter().cloned().map(Into::into).collect(), + seal_fields: header.seal().iter().cloned().map(Into::into).collect(), uncles: block.uncle_hashes().into_iter().map(Into::into).collect(), transactions: match include_txs { true => BlockTransactions::Full(block.view().localized_transactions().into_iter().map(Transaction::from_localized).collect()), @@ -157,7 +167,7 @@ impl EthClient { }, extra_data: Bytes::new(header.extra_data().clone()), }, - extra_info: extra_info + extra_info, } }; @@ -209,36 +219,41 @@ impl EthClient { } } -impl Eth for EthClient { +impl Eth for EthClient +where + C: LightChainClient + 'static, + S: LightSyncInfo + LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ type Metadata = Metadata; fn protocol_version(&self) -> Result { Ok(format!("{}", ::light::net::MAX_PROTOCOL_VERSION)) } - fn syncing(&self) -> Result { + fn syncing(&self) -> Result { if self.sync.is_major_importing() { let chain_info = self.client.chain_info(); let current_block = U256::from(chain_info.best_block_number); let highest_block = self.sync.highest_block().map(U256::from) .unwrap_or_else(|| current_block); - Ok(SyncStatus::Info(SyncInfo { - starting_block: U256::from(self.sync.start_block()).into(), - current_block: current_block.into(), - highest_block: highest_block.into(), + Ok(RpcSyncStatus::Info(RpcSyncInfo { + starting_block: U256::from(self.sync.start_block()), + current_block, + highest_block, warp_chunks_amount: None, warp_chunks_processed: None, })) } else { - Ok(SyncStatus::None) + Ok(RpcSyncStatus::None) } } - fn author(&self) -> Result { - self.accounts.accounts() - .ok() - .and_then(|a| a.first().cloned()) + fn author(&self) -> Result { + (self.accounts)() + .first() + .cloned() .map(From::from) .ok_or_else(|| errors::account("No accounts were found", "")) } @@ -247,122 +262,122 @@ impl Eth for EthClient { Ok(false) } - fn chain_id(&self) -> Result> { - Ok(self.client.signing_chain_id().map(RpcU64::from)) + fn chain_id(&self) -> Result> { + Ok(self.client.signing_chain_id().map(U64::from)) } - fn hashrate(&self) -> Result { + fn hashrate(&self) -> Result { Ok(Default::default()) } - fn gas_price(&self) -> Result { - Ok(self.cache.lock().gas_price_corpus() - .and_then(|c| c.percentile(self.gas_price_percentile).cloned()) - .map(RpcU256::from) - .unwrap_or_else(Default::default)) + fn gas_price(&self) -> BoxFuture { + Box::new(self.fetcher().gas_price()) } - fn accounts(&self) -> Result> { - self.accounts.accounts() - .map_err(|e| errors::account("Could not fetch accounts.", e)) - .map(|accs| accs.into_iter().map(Into::::into).collect()) + fn accounts(&self) -> Result> { + self.deprecation_notice.print("eth_accounts", deprecated::msgs::ACCOUNTS); + + Ok((self.accounts)() + .into_iter() + .map(Into::into) + .collect()) } - fn block_number(&self) -> Result { + fn block_number(&self) -> Result { Ok(self.client.chain_info().best_block_number.into()) } - fn balance(&self, address: RpcH160, num: Trailing) -> BoxFuture { - Box::new(self.fetcher().account(address.into(), num.unwrap_or_default().to_block_id()) - .map(|acc| acc.map_or(0.into(), |a| a.balance).into())) + fn balance(&self, address: H160, num: Option) -> BoxFuture { + Box::new(self.fetcher().account(address, num.unwrap_or_default().to_block_id(), self.transaction_queue.clone()) + .map(|acc| acc.map_or(0.into(), |a| a.balance))) } - fn storage_at(&self, _address: RpcH160, _key: RpcU256, _num: Trailing) -> BoxFuture { + fn storage_at(&self, _address: H160, _key: U256, _num: Option) -> BoxFuture { Box::new(future::err(errors::unimplemented(None))) } - fn block_by_hash(&self, hash: RpcH256, include_txs: bool) -> BoxFuture> { - Box::new(self.rich_block(BlockId::Hash(hash.into()), include_txs).map(Some)) + fn block_by_hash(&self, hash: H256, include_txs: bool) -> BoxFuture> { + Box::new(self.rich_block(BlockId::Hash(hash), include_txs).map(Some)) } fn block_by_number(&self, num: BlockNumber, include_txs: bool) -> BoxFuture> { Box::new(self.rich_block(num.to_block_id(), include_txs).map(Some)) } - fn transaction_count(&self, address: RpcH160, num: Trailing) -> BoxFuture { - Box::new(self.fetcher().account(address.into(), num.unwrap_or_default().to_block_id()) - .map(|acc| acc.map_or(0.into(), |a| a.nonce).into())) + fn transaction_count(&self, address: H160, num: Option) -> BoxFuture { + Box::new(self.fetcher().account(address, num.unwrap_or_default().to_block_id(), self.transaction_queue.clone()) + .map(|acc| acc.map_or(0.into(), |a| a.nonce))) } - fn block_transaction_count_by_hash(&self, hash: RpcH256) -> BoxFuture> { + fn block_transaction_count_by_hash(&self, hash: H256) -> BoxFuture> { let (sync, on_demand) = (self.sync.clone(), self.on_demand.clone()); - Box::new(self.fetcher().header(BlockId::Hash(hash.into())).and_then(move |hdr| { + Box::new(self.fetcher().header(BlockId::Hash(hash)).and_then(move |hdr| { if hdr.transactions_root() == KECCAK_NULL_RLP { - Either::A(future::ok(Some(U256::from(0).into()))) + Either::A(future::ok(Some(U256::from(0)))) } else { sync.with_context(|ctx| on_demand.request(ctx, request::Body(hdr.into()))) .map(|x| x.expect(NO_INVALID_BACK_REFS)) - .map(|x| x.map(|b| Some(U256::from(b.transactions_count()).into()))) + .map(|x| x.map(|b| Some(U256::from(b.transactions_count())))) .map(|x| Either::B(x.map_err(errors::on_demand_error))) .unwrap_or_else(|| Either::A(future::err(errors::network_disabled()))) } })) } - fn block_transaction_count_by_number(&self, num: BlockNumber) -> BoxFuture> { + fn block_transaction_count_by_number(&self, num: BlockNumber) -> BoxFuture> { let (sync, on_demand) = (self.sync.clone(), self.on_demand.clone()); Box::new(self.fetcher().header(num.to_block_id()).and_then(move |hdr| { if hdr.transactions_root() == KECCAK_NULL_RLP { - Either::A(future::ok(Some(U256::from(0).into()))) + Either::A(future::ok(Some(U256::from(0)))) } else { sync.with_context(|ctx| on_demand.request(ctx, request::Body(hdr.into()))) .map(|x| x.expect(NO_INVALID_BACK_REFS)) - .map(|x| x.map(|b| Some(U256::from(b.transactions_count()).into()))) + .map(|x| x.map(|b| Some(U256::from(b.transactions_count())))) .map(|x| Either::B(x.map_err(errors::on_demand_error))) .unwrap_or_else(|| Either::A(future::err(errors::network_disabled()))) } })) } - fn block_uncles_count_by_hash(&self, hash: RpcH256) -> BoxFuture> { + fn block_uncles_count_by_hash(&self, hash: H256) -> BoxFuture> { let (sync, on_demand) = (self.sync.clone(), self.on_demand.clone()); - Box::new(self.fetcher().header(BlockId::Hash(hash.into())).and_then(move |hdr| { + Box::new(self.fetcher().header(BlockId::Hash(hash)).and_then(move |hdr| { if hdr.uncles_hash() == KECCAK_EMPTY_LIST_RLP { - Either::A(future::ok(Some(U256::from(0).into()))) + Either::A(future::ok(Some(U256::from(0)))) } else { sync.with_context(|ctx| on_demand.request(ctx, request::Body(hdr.into()))) .map(|x| x.expect(NO_INVALID_BACK_REFS)) - .map(|x| x.map(|b| Some(U256::from(b.uncles_count()).into()))) + .map(|x| x.map(|b| Some(U256::from(b.uncles_count())))) .map(|x| Either::B(x.map_err(errors::on_demand_error))) .unwrap_or_else(|| Either::A(future::err(errors::network_disabled()))) } })) } - fn block_uncles_count_by_number(&self, num: BlockNumber) -> BoxFuture> { + fn block_uncles_count_by_number(&self, num: BlockNumber) -> BoxFuture> { let (sync, on_demand) = (self.sync.clone(), self.on_demand.clone()); Box::new(self.fetcher().header(num.to_block_id()).and_then(move |hdr| { if hdr.uncles_hash() == KECCAK_EMPTY_LIST_RLP { - Either::B(future::ok(Some(U256::from(0).into()))) + Either::B(future::ok(Some(U256::from(0)))) } else { sync.with_context(|ctx| on_demand.request(ctx, request::Body(hdr.into()))) .map(|x| x.expect(NO_INVALID_BACK_REFS)) - .map(|x| x.map(|b| Some(U256::from(b.uncles_count()).into()))) + .map(|x| x.map(|b| Some(U256::from(b.uncles_count())))) .map(|x| Either::A(x.map_err(errors::on_demand_error))) .unwrap_or_else(|| Either::B(future::err(errors::network_disabled()))) } })) } - fn code_at(&self, address: RpcH160, num: Trailing) -> BoxFuture { - Box::new(self.fetcher().code(address.into(), num.unwrap_or_default().to_block_id()).map(Into::into)) + fn code_at(&self, address: H160, num: Option) -> BoxFuture { + Box::new(self.fetcher().code(address, num.unwrap_or_default().to_block_id()).map(Into::into)) } - fn send_raw_transaction(&self, raw: Bytes) -> Result { + fn send_raw_transaction(&self, raw: Bytes) -> Result { let best_header = self.client.best_block_header().decode().map_err(errors::decode)?; Rlp::new(&raw.into_vec()).as_val() @@ -381,12 +396,12 @@ impl Eth for EthClient { .map(Into::into) } - fn submit_transaction(&self, raw: Bytes) -> Result { + fn submit_transaction(&self, raw: Bytes) -> Result { self.send_raw_transaction(raw) } - fn call(&self, req: CallRequest, num: Trailing) -> BoxFuture { - Box::new(self.fetcher().proved_read_only_execution(req, num).and_then(|res| { + fn call(&self, req: CallRequest, num: Option) -> BoxFuture { + Box::new(self.fetcher().proved_read_only_execution(req, num, self.transaction_queue.clone()).and_then(|res| { match res { Ok(exec) => Ok(exec.output.into()), Err(e) => Err(errors::execution(e)), @@ -394,33 +409,38 @@ impl Eth for EthClient { })) } - fn estimate_gas(&self, req: CallRequest, num: Trailing) -> BoxFuture { + fn estimate_gas(&self, req: CallRequest, num: Option) -> BoxFuture { // TODO: binary chop for more accurate estimates. - Box::new(self.fetcher().proved_read_only_execution(req, num).and_then(|res| { + Box::new(self.fetcher().proved_read_only_execution(req, num, self.transaction_queue.clone()).and_then(|res| { match res { - Ok(exec) => Ok((exec.refunded + exec.gas_used).into()), + Ok(exec) => Ok(exec.refunded + exec.gas_used), Err(e) => Err(errors::execution(e)), } })) } - fn transaction_by_hash(&self, hash: RpcH256) -> BoxFuture> { - let hash = hash.into(); + fn transaction_by_hash(&self, hash: H256) -> BoxFuture> { + let in_txqueue = self.transaction_queue.read().get(&hash).is_some(); - { - let tx_queue = self.transaction_queue.read(); - if let Some(tx) = tx_queue.get(&hash) { + // The transaction is in the `local txqueue` then fetch the latest state from the network and attempt + // to cull the transaction queue. + if in_txqueue { + // Note, this will block (relies on HTTP timeout) to make sure `cull` will finish to avoid having to call + // `eth_getTransactionByHash` more than once to ensure the `txqueue` is up to `date` when it is called + if let Err(e) = self.fetcher().light_cull(self.transaction_queue.clone()).wait() { + debug!(target: "cull", "failed because of: {:?}", e); + } + if let Some(tx) = self.transaction_queue.read().get(&hash) { return Box::new(future::ok(Some(Transaction::from_pending( tx.clone(), )))); } } - Box::new(self.fetcher().transaction_by_hash(hash).map(|x| x.map(|(tx, _)| tx))) } - fn transaction_by_block_hash_and_index(&self, hash: RpcH256, idx: Index) -> BoxFuture> { - Box::new(self.fetcher().block(BlockId::Hash(hash.into())).map(move |block| { + fn transaction_by_block_hash_and_index(&self, hash: H256, idx: Index) -> BoxFuture> { + Box::new(self.fetcher().block(BlockId::Hash(hash)).map(move |block| { light_fetch::extract_transaction_at_index(block, idx.value()) })) } @@ -431,16 +451,16 @@ impl Eth for EthClient { })) } - fn transaction_receipt(&self, hash: RpcH256) -> BoxFuture> { + fn transaction_receipt(&self, hash: H256) -> BoxFuture> { let fetcher = self.fetcher(); - Box::new(fetcher.transaction_by_hash(hash.clone().into()).and_then(move |tx| { + Box::new(fetcher.transaction_by_hash(hash).and_then(move |tx| { // the block hash included in the transaction object here has // already been checked for canonicality and whether it contains // the transaction. match tx { - Some((tx, index)) => match tx.block_hash.clone() { + Some((tx, index)) => match tx.block_hash { Some(block_hash) => { - let extract_receipt = fetcher.receipts(BlockId::Hash(block_hash.clone().into())) + let extract_receipt = fetcher.receipts(BlockId::Hash(block_hash)) .and_then(move |mut receipts| future::ok(receipts.swap_remove(index))) .map(Receipt::from) .map(move |mut receipt| { @@ -461,9 +481,9 @@ impl Eth for EthClient { })) } - fn uncle_by_block_hash_and_index(&self, hash: RpcH256, idx: Index) -> BoxFuture> { + fn uncle_by_block_hash_and_index(&self, hash: H256, idx: Index) -> BoxFuture> { let client = self.client.clone(); - Box::new(self.fetcher().block(BlockId::Hash(hash.into())).map(move |block| { + Box::new(self.fetcher().block(BlockId::Hash(hash)).map(move |block| { extract_uncle_at_index(block, idx, client) })) } @@ -475,7 +495,7 @@ impl Eth for EthClient { })) } - fn proof(&self, _address: RpcH160, _values:Vec, _num: Trailing) -> BoxFuture { + fn proof(&self, _address: H160, _values:Vec, _num: Option) -> BoxFuture { Box::new(future::err(errors::unimplemented(None))) } @@ -505,28 +525,33 @@ impl Eth for EthClient { }).map(move |logs| limit_logs(logs, limit))) } - fn work(&self, _timeout: Trailing) -> Result { + fn work(&self, _timeout: Option) -> Result { Err(errors::light_unimplemented(None)) } - fn submit_work(&self, _nonce: RpcH64, _pow_hash: RpcH256, _mix_hash: RpcH256) -> Result { + fn submit_work(&self, _nonce: H64, _pow_hash: H256, _mix_hash: H256) -> Result { Err(errors::light_unimplemented(None)) } - fn submit_hashrate(&self, _rate: RpcU256, _id: RpcH256) -> Result { + fn submit_hashrate(&self, _rate: U256, _id: H256) -> Result { Err(errors::light_unimplemented(None)) } } // This trait implementation triggers a blanked impl of `EthFilter`. -impl Filterable for EthClient { +impl Filterable for EthClient +where + C: LightChainClient + 'static, + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ fn best_block_number(&self) -> u64 { self.client.chain_info().best_block_number } - fn block_hash(&self, id: BlockId) -> Option<::ethereum_types::H256> { + fn block_hash(&self, id: BlockId) -> Option { self.client.block_hash(id) } - fn pending_transaction_hashes(&self) -> BTreeSet<::ethereum_types::H256> { + fn pending_transaction_hashes(&self) -> BTreeSet { BTreeSet::new() } @@ -556,27 +581,27 @@ fn extract_uncle_at_index(block: encoded::Block, index: Ind let extra_info = client.engine().extra_info(&uncle); Some(RichBlock { inner: Block { - hash: Some(uncle.hash().into()), + hash: Some(uncle.hash()), size: None, - parent_hash: uncle.parent_hash().clone().into(), - uncles_hash: uncle.uncles_hash().clone().into(), - author: uncle.author().clone().into(), - miner: uncle.author().clone().into(), - state_root: uncle.state_root().clone().into(), - transactions_root: uncle.transactions_root().clone().into(), + parent_hash: *uncle.parent_hash(), + uncles_hash: *uncle.uncles_hash(), + author: *uncle.author(), + miner: *uncle.author(), + state_root: *uncle.state_root(), + transactions_root: *uncle.transactions_root(), number: Some(uncle.number().into()), - gas_used: uncle.gas_used().clone().into(), - gas_limit: uncle.gas_limit().clone().into(), - logs_bloom: Some(uncle.log_bloom().clone().into()), + gas_used: *uncle.gas_used(), + gas_limit: *uncle.gas_limit(), + logs_bloom: Some(*uncle.log_bloom()), timestamp: uncle.timestamp().into(), - difficulty: uncle.difficulty().clone().into(), + difficulty: *uncle.difficulty(), total_difficulty: None, - receipts_root: uncle.receipts_root().clone().into(), + receipts_root: *uncle.receipts_root(), extra_data: uncle.extra_data().clone().into(), - seal_fields: uncle.seal().into_iter().cloned().map(Into::into).collect(), + seal_fields: uncle.seal().iter().cloned().map(Into::into).collect(), uncles: vec![], transactions: BlockTransactions::Hashes(vec![]), }, - extra_info: extra_info, + extra_info, }) } diff --git a/rpc/src/v1/impls/light/net.rs b/rpc/src/v1/impls/light/net.rs index 3f73e010b9..a9ab012e5a 100644 --- a/rpc/src/v1/impls/light/net.rs +++ b/rpc/src/v1/impls/light/net.rs @@ -29,7 +29,7 @@ impl NetClient where S: LightSyncProvider { /// Creates new NetClient. pub fn new(sync: Arc) -> Self { NetClient { - sync: sync, + sync, } } } diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index f179ab2367..0486366de6 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -16,40 +16,45 @@ //! Parity-specific rpc implementation. use std::sync::Arc; -use std::collections::{BTreeMap, HashSet}; +use std::collections::BTreeMap; use version::version_data; use crypto::DEFAULT_MAC; use ethkey::{crypto::ecies, Brain, Generator}; use ethstore::random_phrase; -use sync::LightSyncProvider; -use ethcore::account_provider::AccountProvider; +use sync::{LightSyncInfo, LightSyncProvider, LightNetworkDispatcher, ManageNetwork}; +use updater::VersionInfo as UpdaterVersionInfo; +use ethereum_types::{H64, H160, H256, H512, U64, U256}; use ethcore_logger::RotatingLogger; use jsonrpc_core::{Result, BoxFuture}; use jsonrpc_core::futures::{future, Future}; -use jsonrpc_macros::Trailing; -use v1::helpers::{self, errors, ipfs, SigningQueue, SignerService, NetworkSettings, verify_signature}; +use light::on_demand::OnDemandRequester; +use v1::helpers::{self, errors, ipfs, NetworkSettings, verify_signature}; +use v1::helpers::external_signer::{SignerService, SigningQueue}; use v1::helpers::dispatch::LightDispatcher; use v1::helpers::light_fetch::{LightFetch, light_all_transactions}; use v1::metadata::Metadata; use v1::traits::Parity; use v1::types::{ - Bytes, U256, U64, H64, H160, H256, H512, CallRequest, + Bytes, CallRequest, Peers, Transaction, RpcSettings, Histogram, TransactionStats, LocalTransactionStatus, LightBlockNumber, ChainStatus, Receipt, BlockNumber, ConsensusCapability, VersionInfo, - OperationsInfo, AccountInfo, HwAccountInfo, Header, RichHeader, RecoveredAccount, + OperationsInfo, Header, RichHeader, RecoveredAccount, Log, Filter, }; use Host; /// Parity implementation for light client. -pub struct ParityClient { - light_dispatch: Arc, - accounts: Arc, +pub struct ParityClient +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ + light_dispatch: Arc>, logger: Arc, settings: Arc, signer: Option>, @@ -57,11 +62,14 @@ pub struct ParityClient { gas_price_percentile: usize, } -impl ParityClient { +impl ParityClient +where + S: LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ /// Creates new `ParityClient`. pub fn new( - light_dispatch: Arc, - accounts: Arc, + light_dispatch: Arc>, logger: Arc, settings: Arc, signer: Option>, @@ -70,7 +78,6 @@ impl ParityClient { ) -> Self { ParityClient { light_dispatch, - accounts, logger, settings, signer, @@ -80,7 +87,8 @@ impl ParityClient { } /// Create a light blockchain data fetcher. - fn fetcher(&self) -> LightFetch { + fn fetcher(&self) -> LightFetch + { LightFetch { client: self.light_dispatch.client.clone(), on_demand: self.light_dispatch.on_demand.clone(), @@ -91,52 +99,13 @@ impl ParityClient { } } -impl Parity for ParityClient { +impl Parity for ParityClient +where + S: LightSyncInfo + LightSyncProvider + LightNetworkDispatcher + ManageNetwork + 'static, + OD: OnDemandRequester + 'static +{ type Metadata = Metadata; - fn accounts_info(&self) -> Result> { - let store = &self.accounts; - let dapp_accounts = store - .accounts() - .map_err(|e| errors::account("Could not fetch accounts.", e))? - .into_iter().collect::>(); - - let info = store.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e))?; - let other = store.addresses_info(); - - Ok(info - .into_iter() - .chain(other.into_iter()) - .filter(|&(ref a, _)| dapp_accounts.contains(a)) - .map(|(a, v)| (H160::from(a), AccountInfo { name: v.name })) - .collect() - ) - } - - fn hardware_accounts_info(&self) -> Result> { - let store = &self.accounts; - let info = store.hardware_accounts_info().map_err(|e| errors::account("Could not fetch account info.", e))?; - Ok(info - .into_iter() - .map(|(a, v)| (H160::from(a), HwAccountInfo { name: v.name, manufacturer: v.meta })) - .collect() - ) - } - - fn locked_hardware_accounts_info(&self) -> Result> { - let store = &self.accounts; - Ok(store.locked_hardware_accounts().map_err(|e| errors::account("Error communicating with hardware wallet.", e))?) - } - - fn default_account(&self) -> Result { - Ok(self.accounts - .accounts() - .ok() - .and_then(|accounts| accounts.get(0).cloned()) - .map(|acc| acc.into()) - .unwrap_or_default()) - } - fn transactions_limit(&self) -> Result { Ok(usize::max_value()) } @@ -178,7 +147,7 @@ impl Parity for ParityClient { active: peer_numbers.active, connected: peer_numbers.connected, max: peer_numbers.max as u32, - peers: peers, + peers, }) } @@ -195,7 +164,7 @@ impl Parity for ParityClient { if reg == Default::default() { Ok(None) } else { - Ok(Some(reg.into())) + Ok(Some(reg)) } } @@ -229,31 +198,31 @@ impl Parity for ParityClient { } fn phrase_to_address(&self, phrase: String) -> Result { - Ok(Brain::new(phrase).generate().unwrap().address().into()) + Ok(Brain::new(phrase).generate().expect("Brain::generate always returns Ok; qed").address()) } - fn list_accounts(&self, _: u64, _: Option, _: Trailing) -> Result>> { + fn list_accounts(&self, _: u64, _: Option, _: Option) -> Result>> { Err(errors::light_unimplemented(None)) } - fn list_storage_keys(&self, _: H160, _: u64, _: Option, _: Trailing) -> Result>> { + fn list_storage_keys(&self, _: H160, _: u64, _: Option, _: Option) -> Result>> { Err(errors::light_unimplemented(None)) } fn encrypt_message(&self, key: H512, phrase: Bytes) -> Result { - ecies::encrypt(&key.into(), &DEFAULT_MAC, &phrase.0) + ecies::encrypt(&key, &DEFAULT_MAC, &phrase.0) .map_err(errors::encryption) .map(Into::into) } - fn pending_transactions(&self, limit: Trailing) -> Result> { + fn pending_transactions(&self, limit: Option) -> Result> { let txq = self.light_dispatch.transaction_queue.read(); let chain_info = self.light_dispatch.client.chain_info(); Ok( txq.ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp) .into_iter() .take(limit.unwrap_or_else(usize::max_value)) - .map(|tx| Transaction::from_pending(tx)) + .map(Transaction::from_pending) .collect::>() ) } @@ -261,7 +230,7 @@ impl Parity for ParityClient { fn all_transactions(&self) -> Result> { Ok( light_all_transactions(&self.light_dispatch) - .map(|tx| Transaction::from_pending(tx)) + .map(Transaction::from_pending) .collect() ) } @@ -269,7 +238,7 @@ impl Parity for ParityClient { fn all_transaction_hashes(&self) -> Result> { Ok( light_all_transactions(&self.light_dispatch) - .map(|tx| tx.transaction.hash().into()) + .map(|tx| tx.transaction.hash()) .collect() ) } @@ -280,7 +249,7 @@ impl Parity for ParityClient { Ok( txq.future_transactions(chain_info.best_block_number, chain_info.best_block_timestamp) .into_iter() - .map(|tx| Transaction::from_pending(tx)) + .map(Transaction::from_pending) .collect::>() ) } @@ -288,7 +257,7 @@ impl Parity for ParityClient { fn pending_transactions_stats(&self) -> Result> { let stats = self.light_dispatch.sync.transactions_stats(); Ok(stats.into_iter() - .map(|(hash, stats)| (hash.into(), stats.into())) + .map(|(hash, stats)| (hash, stats.into())) .collect() ) } @@ -300,11 +269,11 @@ impl Parity for ParityClient { let txq = self.light_dispatch.transaction_queue.read(); for pending in txq.ready_transactions(best_num, best_tm) { - map.insert(pending.hash().into(), LocalTransactionStatus::Pending); + map.insert(pending.hash(), LocalTransactionStatus::Pending); } for future in txq.future_transactions(best_num, best_tm) { - map.insert(future.hash().into(), LocalTransactionStatus::Future); + map.insert(future.hash(), LocalTransactionStatus::Future); } // TODO: other types? @@ -314,11 +283,11 @@ impl Parity for ParityClient { fn ws_url(&self) -> Result { helpers::to_url(&self.ws_address) - .ok_or_else(|| errors::ws_disabled()) + .ok_or_else(errors::ws_disabled) } fn next_nonce(&self, address: H160) -> BoxFuture { - Box::new(self.light_dispatch.next_nonce(address.into()).map(Into::into)) + Box::new(self.light_dispatch.next_nonce(address)) } fn mode(&self) -> Result { @@ -338,7 +307,7 @@ impl Parity for ParityClient { } fn version_info(&self) -> Result { - Err(errors::light_unimplemented(None)) + Ok(UpdaterVersionInfo::this().into()) } fn releases_info(&self) -> Result> { @@ -352,7 +321,7 @@ impl Parity for ParityClient { .and_then(|first| chain_info.first_block_number.map(|last| (first, U256::from(last)))); Ok(ChainStatus { - block_gap: gap.map(|(x, y)| (x.into(), y.into())), + block_gap: gap, }) } @@ -365,7 +334,7 @@ impl Parity for ParityClient { }) } - fn block_header(&self, number: Trailing) -> BoxFuture { + fn block_header(&self, number: Option) -> BoxFuture { use types::encoded; let engine = self.light_dispatch.client.engine().clone(); @@ -374,32 +343,32 @@ impl Parity for ParityClient { let extra_info = engine.extra_info(&header); Ok(RichHeader { inner: Header { - hash: Some(header.hash().into()), + hash: Some(header.hash()), size: Some(encoded.rlp().as_raw().len().into()), - parent_hash: header.parent_hash().clone().into(), - uncles_hash: header.uncles_hash().clone().into(), - author: header.author().clone().into(), - miner: header.author().clone().into(), - state_root: header.state_root().clone().into(), - transactions_root: header.transactions_root().clone().into(), - receipts_root: header.receipts_root().clone().into(), + parent_hash: *header.parent_hash(), + uncles_hash: *header.uncles_hash(), + author: *header.author(), + miner: *header.author(), + state_root: *header.state_root(), + transactions_root: *header.transactions_root(), + receipts_root: *header.receipts_root(), number: Some(header.number().into()), - gas_used: header.gas_used().clone().into(), - gas_limit: header.gas_limit().clone().into(), - logs_bloom: header.log_bloom().clone().into(), + gas_used: *header.gas_used(), + gas_limit: *header.gas_limit(), + logs_bloom: *header.log_bloom(), timestamp: header.timestamp().into(), - difficulty: header.difficulty().clone().into(), + difficulty: *header.difficulty(), seal_fields: header.seal().iter().cloned().map(Into::into).collect(), extra_data: Bytes::new(header.extra_data().clone()), }, - extra_info: extra_info, + extra_info, }) }; let id = number.unwrap_or_default().to_block_id(); Box::new(self.fetcher().header(id).and_then(from_encoded)) } - fn block_receipts(&self, number: Trailing) -> BoxFuture> { + fn block_receipts(&self, number: Option) -> BoxFuture> { let id = number.unwrap_or_default().to_block_id(); Box::new(self.fetcher().receipts(id).and_then(|receipts| Ok(receipts.into_iter().map(Into::into).collect()))) } @@ -408,7 +377,7 @@ impl Parity for ParityClient { ipfs::cid(content) } - fn call(&self, _requests: Vec, _block: Trailing) -> Result> { + fn call(&self, _requests: Vec, _block: Option) -> Result> { Err(errors::light_unimplemented(None)) } @@ -418,7 +387,7 @@ impl Parity for ParityClient { fn status(&self) -> Result<()> { let has_peers = self.settings.is_dev_chain || self.light_dispatch.sync.peer_numbers().connected > 0; - let is_importing = self.light_dispatch.sync.is_major_importing(); + let is_importing = (*self.light_dispatch.sync).is_major_importing(); if has_peers && !is_importing { Ok(()) @@ -428,7 +397,7 @@ impl Parity for ParityClient { } fn logs_no_tx_hash(&self, filter: Filter) -> BoxFuture> { - let filter = match filter.try_into() { + let filter = match filter.try_into() { Ok(value) => value, Err(err) => return Box::new(future::err(err)), }; diff --git a/rpc/src/v1/impls/light/parity_set.rs b/rpc/src/v1/impls/light/parity_set.rs index 08e386fe5d..68fc212b2f 100644 --- a/rpc/src/v1/impls/light/parity_set.rs +++ b/rpc/src/v1/impls/light/parity_set.rs @@ -20,28 +20,32 @@ use std::io; use std::sync::Arc; -use sync::ManageNetwork; +use ethereum_types::{H160, H256, U256}; use fetch::{self, Fetch}; use hash::keccak_buffer; +use light::client::LightChainClient; +use sync::ManageNetwork; use jsonrpc_core::{Result, BoxFuture}; use jsonrpc_core::futures::Future; use v1::helpers::errors; use v1::traits::ParitySet; -use v1::types::{Bytes, H160, H256, U256, ReleaseInfo, Transaction}; +use v1::types::{Bytes, ReleaseInfo, Transaction}; /// Parity-specific rpc interface for operations altering the settings. pub struct ParitySetClient { + client: Arc, net: Arc, fetch: F, } impl ParitySetClient { /// Creates new `ParitySetClient` with given `Fetch`. - pub fn new(net: Arc, fetch: F) -> Self { + pub fn new(client: Arc, net: Arc, fetch: F) -> Self { ParitySetClient { - net: net, - fetch: fetch, + client, + net, + fetch, } } } @@ -67,7 +71,7 @@ impl ParitySet for ParitySetClient { Err(errors::light_unimplemented(None)) } - fn set_engine_signer(&self, _address: H160, _password: String) -> Result { + fn set_engine_signer_secret(&self, _secret: H256) -> Result { Err(errors::light_unimplemented(None)) } @@ -117,8 +121,8 @@ impl ParitySet for ParitySetClient { Err(errors::light_unimplemented(None)) } - fn set_spec_name(&self, _spec_name: String) -> Result { - Err(errors::light_unimplemented(None)) + fn set_spec_name(&self, spec_name: String) -> Result { + self.client.set_spec_name(spec_name).map(|_| true).map_err(|()| errors::cannot_restart()) } fn hash_content(&self, url: String) -> BoxFuture { diff --git a/rpc/src/v1/impls/light/trace.rs b/rpc/src/v1/impls/light/trace.rs index 092189b743..a560f980e7 100644 --- a/rpc/src/v1/impls/light/trace.rs +++ b/rpc/src/v1/impls/light/trace.rs @@ -16,12 +16,13 @@ //! Traces api implementation. +use ethereum_types::H256; use jsonrpc_core::Result; -use jsonrpc_macros::Trailing; use v1::Metadata; use v1::traits::Traces; use v1::helpers::errors; -use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, TraceResultsWithTransactionHash, TraceOptions, H256}; +use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, + TraceResultsWithTransactionHash, TraceOptions}; /// Traces api implementation. // TODO: all calling APIs should be possible w. proved remote TX execution. @@ -46,15 +47,15 @@ impl Traces for TracesClient { Err(errors::light_unimplemented(None)) } - fn call(&self, _request: CallRequest, _flags: TraceOptions, _block: Trailing) -> Result { + fn call(&self, _request: CallRequest, _flags: TraceOptions, _block: Option) -> Result { Err(errors::light_unimplemented(None)) } - fn call_many(&self, _request: Vec<(CallRequest, TraceOptions)>, _block: Trailing) -> Result> { + fn call_many(&self, _request: Vec<(CallRequest, TraceOptions)>, _block: Option) -> Result> { Err(errors::light_unimplemented(None)) } - fn raw_transaction(&self, _raw_transaction: Bytes, _flags: TraceOptions, _block: Trailing) -> Result { + fn raw_transaction(&self, _raw_transaction: Bytes, _flags: TraceOptions, _block: Option) -> Result { Err(errors::light_unimplemented(None)) } diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index 5e334a3b6d..ba1cc100e8 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -22,12 +22,15 @@ mod eth_filter; mod eth_pubsub; mod net; mod parity; +#[cfg(any(test, feature = "accounts"))] mod parity_accounts; mod parity_set; +#[cfg(any(test, feature = "accounts"))] mod personal; mod private; mod pubsub; mod rpc; +#[cfg(any(test, feature = "accounts"))] mod secretstore; mod signer; mod signing; @@ -43,12 +46,17 @@ pub use self::eth_filter::EthFilterClient; pub use self::eth_pubsub::EthPubSubClient; pub use self::net::NetClient; pub use self::parity::ParityClient; +#[cfg(any(test, feature = "accounts"))] pub use self::parity_accounts::ParityAccountsClient; pub use self::parity_set::ParitySetClient; +#[cfg(any(test, feature = "accounts"))] +pub use self::parity_set::accounts::ParitySetAccountsClient; +#[cfg(any(test, feature = "accounts"))] pub use self::personal::PersonalClient; pub use self::private::PrivateClient; pub use self::pubsub::PubSubClient; pub use self::rpc::RpcClient; +#[cfg(any(test, feature = "accounts"))] pub use self::secretstore::SecretStoreClient; pub use self::signer::SignerClient; pub use self::signing::SigningQueueClient; diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index 39948ce1a8..27a7037958 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -17,13 +17,10 @@ //! Parity-specific rpc implementation. use std::sync::Arc; use std::str::FromStr; -use std::collections::{BTreeMap, HashSet}; - -use ethereum_types::Address; -use version::version_data; +use std::collections::BTreeMap; use crypto::DEFAULT_MAC; -use ethcore::account_provider::AccountProvider; +use ethereum_types::{Address, H64, H160, H256, H512, U64, U256}; use ethcore::client::{BlockChainClient, StateClient, Call}; use ethcore::miner::{self, MinerService}; use ethcore::snapshot::{SnapshotService, RestorationStatus}; @@ -33,22 +30,23 @@ use ethkey::{crypto::ecies, Brain, Generator}; use ethstore::random_phrase; use jsonrpc_core::futures::future; use jsonrpc_core::{BoxFuture, Result}; -use jsonrpc_macros::Trailing; use sync::{SyncProvider, ManageNetwork}; use types::ids::BlockId; use updater::{Service as UpdateService}; +use version::version_data; use v1::helpers::block_import::is_major_importing; -use v1::helpers::{self, errors, fake_sign, ipfs, SigningQueue, SignerService, NetworkSettings, verify_signature}; +use v1::helpers::{self, errors, fake_sign, ipfs, NetworkSettings, verify_signature}; +use v1::helpers::external_signer::{SigningQueue, SignerService}; use v1::metadata::Metadata; use v1::traits::Parity; use v1::types::{ - Bytes, U256, H64, U64, H160, H256, H512, CallRequest, + Bytes, CallRequest, Peers, Transaction, RpcSettings, Histogram, TransactionStats, LocalTransactionStatus, BlockNumber, ConsensusCapability, VersionInfo, OperationsInfo, ChainStatus, Log, Filter, - AccountInfo, HwAccountInfo, RichHeader, Receipt, RecoveredAccount, + RichHeader, Receipt, RecoveredAccount, block_number_to_id }; use Host; @@ -60,7 +58,6 @@ pub struct ParityClient { updater: Arc, sync: Arc, net: Arc, - accounts: Arc, logger: Arc, settings: Arc, signer: Option>, @@ -78,7 +75,6 @@ impl ParityClient where sync: Arc, updater: Arc, net: Arc, - accounts: Arc, logger: Arc, settings: Arc, signer: Option>, @@ -91,7 +87,6 @@ impl ParityClient where sync, updater, net, - accounts, logger, settings, signer, @@ -109,49 +104,12 @@ impl Parity for ParityClient where { type Metadata = Metadata; - fn accounts_info(&self) -> Result> { - let dapp_accounts = self.accounts.accounts() - .map_err(|e| errors::account("Could not fetch accounts.", e))? - .into_iter().collect::>(); - - let info = self.accounts.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e))?; - let other = self.accounts.addresses_info(); - - Ok(info - .into_iter() - .chain(other.into_iter()) - .filter(|&(ref a, _)| dapp_accounts.contains(a)) - .map(|(a, v)| (H160::from(a), AccountInfo { name: v.name })) - .collect() - ) - } - - fn hardware_accounts_info(&self) -> Result> { - let info = self.accounts.hardware_accounts_info().map_err(|e| errors::account("Could not fetch account info.", e))?; - Ok(info - .into_iter() - .map(|(a, v)| (H160::from(a), HwAccountInfo { name: v.name, manufacturer: v.meta })) - .collect() - ) - } - - fn locked_hardware_accounts_info(&self) -> Result> { - self.accounts.locked_hardware_accounts().map_err(|e| errors::account("Error communicating with hardware wallet.", e)) - } - - fn default_account(&self) -> Result { - Ok(self.accounts.default_account() - .map(Into::into) - .ok() - .unwrap_or_default()) - } - fn transactions_limit(&self) -> Result { Ok(self.miner.queue_status().limits.max_count) } fn min_gas_price(&self) -> Result { - Ok(self.miner.queue_status().options.minimal_gas_price.into()) + Ok(self.miner.queue_status().options.minimal_gas_price) } fn extra_data(&self) -> Result { @@ -159,11 +117,11 @@ impl Parity for ParityClient where } fn gas_floor_target(&self) -> Result { - Ok(U256::from(self.miner.authoring_params().gas_range_target.0)) + Ok(self.miner.authoring_params().gas_range_target.0) } fn gas_ceil_target(&self) -> Result { - Ok(U256::from(self.miner.authoring_params().gas_range_target.1)) + Ok(self.miner.authoring_params().gas_range_target.1) } fn dev_logs(&self) -> Result> { @@ -187,14 +145,14 @@ impl Parity for ParityClient where fn net_peers(&self) -> Result { let sync_status = self.sync.status(); let num_peers_range = self.net.num_peers_range(); - debug_assert!(num_peers_range.end > num_peers_range.start); + debug_assert!(num_peers_range.end() >= num_peers_range.start()); let peers = self.sync.peers().into_iter().map(Into::into).collect(); Ok(Peers { active: sync_status.num_active_peers, connected: sync_status.num_peers, - max: sync_status.current_max_peers(num_peers_range.start, num_peers_range.end - 1), - peers: peers + max: sync_status.current_max_peers(*num_peers_range.start(), *num_peers_range.end()), + peers, }) } @@ -212,7 +170,6 @@ impl Parity for ParityClient where .additional_params() .get("registrar") .and_then(|s| Address::from_str(s).ok()) - .map(|s| H160::from(s)) ) } @@ -249,10 +206,10 @@ impl Parity for ParityClient where } fn phrase_to_address(&self, phrase: String) -> Result { - Ok(Brain::new(phrase).generate().unwrap().address().into()) + Ok(Brain::new(phrase).generate().expect("Brain::generate always returns Ok; qed").address()) } - fn list_accounts(&self, count: u64, after: Option, block_number: Trailing) -> Result>> { + fn list_accounts(&self, count: u64, after: Option, block_number: Option) -> Result>> { let number = match block_number.unwrap_or_default() { BlockNumber::Pending => { warn!("BlockNumber::Pending is unsupported"); @@ -267,7 +224,7 @@ impl Parity for ParityClient where .map(|a| a.into_iter().map(Into::into).collect())) } - fn list_storage_keys(&self, address: H160, count: u64, after: Option, block_number: Trailing) -> Result>> { + fn list_storage_keys(&self, address: H160, count: u64, after: Option, block_number: Option) -> Result>> { let number = match block_number.unwrap_or_default() { BlockNumber::Pending => { warn!("BlockNumber::Pending is unsupported"); @@ -278,17 +235,17 @@ impl Parity for ParityClient where }; Ok(self.client - .list_storage(number, &address.into(), after.map(Into::into).as_ref(), count) + .list_storage(number, &address, after.map(Into::into).as_ref(), count) .map(|a| a.into_iter().map(Into::into).collect())) } fn encrypt_message(&self, key: H512, phrase: Bytes) -> Result { - ecies::encrypt(&key.into(), &DEFAULT_MAC, &phrase.0) + ecies::encrypt(&key, &DEFAULT_MAC, &phrase.0) .map_err(errors::encryption) .map(Into::into) } - fn pending_transactions(&self, limit: Trailing) -> Result> { + fn pending_transactions(&self, limit: Option) -> Result> { let ready_transactions = self.miner.ready_transactions( &*self.client, limit.unwrap_or_else(usize::max_value), @@ -313,13 +270,7 @@ impl Parity for ParityClient where } fn all_transaction_hashes(&self) -> Result> { - let all_transaction_hashes = self.miner.queued_transaction_hashes(); - - Ok(all_transaction_hashes - .into_iter() - .map(|hash| hash.into()) - .collect() - ) + Ok(self.miner.queued_transaction_hashes()) } fn future_transactions(&self) -> Result> { @@ -329,7 +280,7 @@ impl Parity for ParityClient where fn pending_transactions_stats(&self) -> Result> { let stats = self.sync.transactions_stats(); Ok(stats.into_iter() - .map(|(hash, stats)| (hash.into(), stats.into())) + .map(|(hash, stats)| (hash, stats.into())) .collect() ) } @@ -338,7 +289,7 @@ impl Parity for ParityClient where let transactions = self.miner.local_transactions(); Ok(transactions .into_iter() - .map(|(hash, status)| (hash.into(), LocalTransactionStatus::from(status))) + .map(|(hash, status)| (hash, LocalTransactionStatus::from(status))) .collect() ) } @@ -349,9 +300,7 @@ impl Parity for ParityClient where } fn next_nonce(&self, address: H160) -> BoxFuture { - let address: Address = address.into(); - - Box::new(future::ok(self.miner.next_nonce(&*self.client, &address).into())) + Box::new(future::ok(self.miner.next_nonce(&*self.client, &address))) } fn mode(&self) -> Result { @@ -381,7 +330,7 @@ impl Parity for ParityClient where .and_then(|first| chain_info.first_block_number.map(|last| (first, U256::from(last)))); Ok(ChainStatus { - block_gap: gap.map(|(x, y)| (x.into(), y.into())), + block_gap: gap, }) } @@ -394,7 +343,7 @@ impl Parity for ParityClient where }) } - fn block_header(&self, number: Trailing) -> BoxFuture { + fn block_header(&self, number: Option) -> BoxFuture { const EXTRA_INFO_PROOF: &str = "Object exists in blockchain (fetched earlier), extra_info is always available if object exists; qed"; let number = number.unwrap_or_default(); @@ -412,7 +361,7 @@ impl Parity for ParityClient where BlockNumber::Pending => unreachable!(), // Already covered }; - let header = try_bf!(self.client.block_header(id.clone()).ok_or_else(errors::unknown_block)); + let header = try_bf!(self.client.block_header(id).ok_or_else(errors::unknown_block)); let info = self.client.block_extra_info(id).expect(EXTRA_INFO_PROOF); (header, Some(info)) @@ -424,7 +373,7 @@ impl Parity for ParityClient where })) } - fn block_receipts(&self, number: Trailing) -> BoxFuture> { + fn block_receipts(&self, number: Option) -> BoxFuture> { let number = number.unwrap_or_default(); let id = match number { @@ -449,7 +398,7 @@ impl Parity for ParityClient where ipfs::cid(content) } - fn call(&self, requests: Vec, num: Trailing) -> Result> { + fn call(&self, requests: Vec, num: Option) -> Result> { let requests = requests .into_iter() .map(|request| Ok(( @@ -509,7 +458,7 @@ impl Parity for ParityClient where fn logs_no_tx_hash(&self, filter: Filter) -> BoxFuture> { use v1::impls::eth::base_logs; // only specific impl for lightclient - base_logs(&*self.client, &*self.miner, filter.into()) + base_logs(&*self.client, &*self.miner, filter) } fn verify_signature(&self, is_prefixed: bool, message: Bytes, r: H256, s: H256, v: U64) -> Result { diff --git a/rpc/src/v1/impls/parity_accounts.rs b/rpc/src/v1/impls/parity_accounts.rs index f1038077e3..e52f8b7ac0 100644 --- a/rpc/src/v1/impls/parity_accounts.rs +++ b/rpc/src/v1/impls/parity_accounts.rs @@ -16,21 +16,26 @@ //! Account management (personal) rpc implementation use std::sync::Arc; -use std::collections::btree_map::{BTreeMap, Entry}; -use ethereum_types::Address; +use std::collections::{ + btree_map::{BTreeMap, Entry}, + HashSet, +}; +use ethereum_types::{Address, H160, H256, H520}; use ethkey::{Brain, Generator, Secret}; use ethstore::KeyFile; -use ethcore::account_provider::AccountProvider; +use accounts::AccountProvider; use jsonrpc_core::Result; +use v1::helpers::deprecated::{self, DeprecationNotice}; use v1::helpers::errors; -use v1::traits::ParityAccounts; -use v1::types::{H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, Derive, DeriveHierarchical, DeriveHash, ExtAccountInfo}; +use v1::traits::{ParityAccounts, ParityAccountsInfo}; +use v1::types::{Derive, DeriveHierarchical, DeriveHash,ExtAccountInfo, AccountInfo, HwAccountInfo}; use ethkey::Password; /// Account management (personal) rpc implementation. pub struct ParityAccountsClient { accounts: Arc, + deprecation_notice: DeprecationNotice, } impl ParityAccountsClient { @@ -38,12 +43,66 @@ impl ParityAccountsClient { pub fn new(store: &Arc) -> Self { ParityAccountsClient { accounts: store.clone(), + deprecation_notice: Default::default(), } } } +impl ParityAccountsClient { + fn deprecation_notice(&self, method: &'static str) { + self.deprecation_notice.print(method, deprecated::msgs::ACCOUNTS); + } +} + +impl ParityAccountsInfo for ParityAccountsClient { + fn accounts_info(&self) -> Result> { + self.deprecation_notice("parity_accountsInfo"); + + let dapp_accounts = self.accounts.accounts() + .map_err(|e| errors::account("Could not fetch accounts.", e))? + .into_iter().collect::>(); + + let info = self.accounts.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e))?; + let other = self.accounts.addresses_info(); + + Ok(info + .into_iter() + .chain(other.into_iter()) + .filter(|&(ref a, _)| dapp_accounts.contains(a)) + .map(|(a, v)| (H160::from(a), AccountInfo { name: v.name })) + .collect() + ) + } + + fn hardware_accounts_info(&self) -> Result> { + self.deprecation_notice("parity_hardwareAccountsInfo"); + + let info = self.accounts.hardware_accounts_info().map_err(|e| errors::account("Could not fetch account info.", e))?; + Ok(info + .into_iter() + .map(|(a, v)| (H160::from(a), HwAccountInfo { name: v.name, manufacturer: v.meta })) + .collect() + ) + } + + fn locked_hardware_accounts_info(&self) -> Result> { + self.deprecation_notice("parity_lockedHardwareAccountsInfo"); + + self.accounts.locked_hardware_accounts().map_err(|e| errors::account("Error communicating with hardware wallet.", e)) + } + + fn default_account(&self) -> Result { + self.deprecation_notice("parity_defaultAccount"); + + Ok(self.accounts.default_account() + .map(Into::into) + .ok() + .unwrap_or_default()) + } +} + impl ParityAccounts for ParityAccountsClient { - fn all_accounts_info(&self) -> Result> { + fn all_accounts_info(&self) -> Result> { let info = self.accounts.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e))?; let other = self.accounts.addresses_info(); @@ -56,7 +115,7 @@ impl ParityAccounts for ParityAccountsClient { uuid: v.uuid.map(|uuid| uuid.to_string()) })); - let mut accounts: BTreeMap = BTreeMap::new(); + let mut accounts: BTreeMap = BTreeMap::new(); for (address, account) in account_iter { match accounts.entry(address) { @@ -74,21 +133,24 @@ impl ParityAccounts for ParityAccountsClient { Ok(accounts) } - fn new_account_from_phrase(&self, phrase: String, pass: Password) -> Result { + fn new_account_from_phrase(&self, phrase: String, pass: Password) -> Result { + self.deprecation_notice("parity_newAccountFromPhrase"); let brain = Brain::new(phrase).generate().unwrap(); self.accounts.insert_account(brain.secret().clone(), &pass) .map(Into::into) .map_err(|e| errors::account("Could not create account.", e)) } - fn new_account_from_wallet(&self, json: String, pass: Password) -> Result { + fn new_account_from_wallet(&self, json: String, pass: Password) -> Result { + self.deprecation_notice("parity_newAccountFromWallet"); self.accounts.import_presale(json.as_bytes(), &pass) .or_else(|_| self.accounts.import_wallet(json.as_bytes(), &pass, true)) .map(Into::into) .map_err(|e| errors::account("Could not create account.", e)) } - fn new_account_from_secret(&self, secret: RpcH256, pass: Password) -> Result { + fn new_account_from_secret(&self, secret: H256, pass: Password) -> Result { + self.deprecation_notice("parity_newAccountFromSecret"); let secret = Secret::from_unsafe_slice(&secret.0) .map_err(|e| errors::account("Could not create account.", e))?; self.accounts.insert_account(secret, &pass) @@ -96,7 +158,8 @@ impl ParityAccounts for ParityAccountsClient { .map_err(|e| errors::account("Could not create account.", e)) } - fn test_password(&self, account: RpcH160, password: Password) -> Result { + fn test_password(&self, account: H160, password: Password) -> Result { + self.deprecation_notice("parity_testPassword"); let account: Address = account.into(); self.accounts @@ -104,7 +167,8 @@ impl ParityAccounts for ParityAccountsClient { .map_err(|e| errors::account("Could not fetch account info.", e)) } - fn change_password(&self, account: RpcH160, password: Password, new_password: Password) -> Result { + fn change_password(&self, account: H160, password: Password, new_password: Password) -> Result { + self.deprecation_notice("parity_changePassword"); let account: Address = account.into(); self.accounts .change_password(&account, password, new_password) @@ -112,7 +176,8 @@ impl ParityAccounts for ParityAccountsClient { .map_err(|e| errors::account("Could not fetch account info.", e)) } - fn kill_account(&self, account: RpcH160, password: Password) -> Result { + fn kill_account(&self, account: H160, password: Password) -> Result { + self.deprecation_notice("parity_killAccount"); let account: Address = account.into(); self.accounts .kill_account(&account, &password) @@ -120,14 +185,16 @@ impl ParityAccounts for ParityAccountsClient { .map_err(|e| errors::account("Could not delete account.", e)) } - fn remove_address(&self, addr: RpcH160) -> Result { + fn remove_address(&self, addr: H160) -> Result { + self.deprecation_notice("parity_removeAddresss"); let addr: Address = addr.into(); self.accounts.remove_address(addr); Ok(true) } - fn set_account_name(&self, addr: RpcH160, name: String) -> Result { + fn set_account_name(&self, addr: H160, name: String) -> Result { + self.deprecation_notice("parity_setAccountName"); let addr: Address = addr.into(); self.accounts.set_account_name(addr.clone(), name.clone()) @@ -135,7 +202,8 @@ impl ParityAccounts for ParityAccountsClient { Ok(true) } - fn set_account_meta(&self, addr: RpcH160, meta: String) -> Result { + fn set_account_meta(&self, addr: H160, meta: String) -> Result { + self.deprecation_notice("parity_setAccountMeta"); let addr: Address = addr.into(); self.accounts.set_account_meta(addr.clone(), meta.clone()) @@ -143,18 +211,22 @@ impl ParityAccounts for ParityAccountsClient { Ok(true) } - fn import_geth_accounts(&self, addresses: Vec) -> Result> { + fn import_geth_accounts(&self, addresses: Vec) -> Result> { + self.deprecation_notice("parity_importGethAccounts"); self.accounts .import_geth_accounts(into_vec(addresses), false) .map(into_vec) .map_err(|e| errors::account("Couldn't import Geth accounts", e)) } - fn geth_accounts(&self) -> Result> { + fn geth_accounts(&self) -> Result> { + self.deprecation_notice("parity_listGethAccounts"); Ok(into_vec(self.accounts.list_geth_accounts(false))) } fn create_vault(&self, name: String, password: Password) -> Result { + self.deprecation_notice("parity_newVault"); + self.accounts .create_vault(&name, &password) .map_err(|e| errors::account("Could not create vault.", e)) @@ -162,6 +234,8 @@ impl ParityAccounts for ParityAccountsClient { } fn open_vault(&self, name: String, password: Password) -> Result { + self.deprecation_notice("parity_openVault"); + self.accounts .open_vault(&name, &password) .map_err(|e| errors::account("Could not open vault.", e)) @@ -169,6 +243,8 @@ impl ParityAccounts for ParityAccountsClient { } fn close_vault(&self, name: String) -> Result { + self.deprecation_notice("parity_closeVault"); + self.accounts .close_vault(&name) .map_err(|e| errors::account("Could not close vault.", e)) @@ -176,25 +252,32 @@ impl ParityAccounts for ParityAccountsClient { } fn list_vaults(&self) -> Result> { + self.deprecation_notice("parity_listVaults"); + self.accounts .list_vaults() .map_err(|e| errors::account("Could not list vaults.", e)) } fn list_opened_vaults(&self) -> Result> { + self.deprecation_notice("parity_listOpenedVaults"); + self.accounts .list_opened_vaults() .map_err(|e| errors::account("Could not list vaults.", e)) } fn change_vault_password(&self, name: String, new_password: Password) -> Result { + self.deprecation_notice("parity_changeVaultPassword"); + self.accounts .change_vault_password(&name, &new_password) .map_err(|e| errors::account("Could not change vault password.", e)) .map(|_| true) } - fn change_vault(&self, address: RpcH160, new_vault: String) -> Result { + fn change_vault(&self, address: H160, new_vault: String) -> Result { + self.deprecation_notice("parity_changeVault"); self.accounts .change_vault(address.into(), &new_vault) .map_err(|e| errors::account("Could not change vault.", e)) @@ -202,19 +285,24 @@ impl ParityAccounts for ParityAccountsClient { } fn get_vault_meta(&self, name: String) -> Result { + self.deprecation_notice("parity_getVaultMeta"); + self.accounts .get_vault_meta(&name) .map_err(|e| errors::account("Could not get vault metadata.", e)) } fn set_vault_meta(&self, name: String, meta: String) -> Result { + self.deprecation_notice("parity_setVaultMeta"); + self.accounts .set_vault_meta(&name, &meta) .map_err(|e| errors::account("Could not update vault metadata.", e)) .map(|_| true) } - fn derive_key_index(&self, addr: RpcH160, password: Password, derivation: DeriveHierarchical, save_as_account: bool) -> Result { + fn derive_key_index(&self, addr: H160, password: Password, derivation: DeriveHierarchical, save_as_account: bool) -> Result { + self.deprecation_notice("parity_deriveAddressIndex"); let addr: Address = addr.into(); self.accounts .derive_account( @@ -227,7 +315,8 @@ impl ParityAccounts for ParityAccountsClient { .map_err(|e| errors::account("Could not derive account.", e)) } - fn derive_key_hash(&self, addr: RpcH160, password: Password, derivation: DeriveHash, save_as_account: bool) -> Result { + fn derive_key_hash(&self, addr: H160, password: Password, derivation: DeriveHash, save_as_account: bool) -> Result { + self.deprecation_notice("parity_deriveAddressHash"); let addr: Address = addr.into(); self.accounts .derive_account( @@ -240,7 +329,8 @@ impl ParityAccounts for ParityAccountsClient { .map_err(|e| errors::account("Could not derive account.", e)) } - fn export_account(&self, addr: RpcH160, password: Password) -> Result { + fn export_account(&self, addr: H160, password: Password) -> Result { + self.deprecation_notice("parity_exportAccount"); let addr = addr.into(); self.accounts .export_account( @@ -251,7 +341,8 @@ impl ParityAccounts for ParityAccountsClient { .map_err(|e| errors::account("Could not export account.", e)) } - fn sign_message(&self, addr: RpcH160, password: Password, message: RpcH256) -> Result { + fn sign_message(&self, addr: H160, password: Password, message: H256) -> Result { + self.deprecation_notice("parity_signMessage"); self.accounts .sign( addr.into(), @@ -263,6 +354,8 @@ impl ParityAccounts for ParityAccountsClient { } fn hardware_pin_matrix_ack(&self, path: String, pin: String) -> Result { + self.deprecation_notice("parity_hardwarePinMatrixAck"); + self.accounts.hardware_pin_matrix_ack(&path, &pin).map_err(|e| errors::account("Error communicating with hardware wallet.", e)) } } diff --git a/rpc/src/v1/impls/parity_set.rs b/rpc/src/v1/impls/parity_set.rs index fbd69230aa..b7cef6c6b8 100644 --- a/rpc/src/v1/impls/parity_set.rs +++ b/rpc/src/v1/impls/parity_set.rs @@ -20,17 +20,66 @@ use std::sync::Arc; use std::time::Duration; use ethcore::client::{BlockChainClient, Mode}; -use ethcore::miner::MinerService; -use sync::ManageNetwork; +use ethcore::miner::{self, MinerService}; +use ethereum_types::{H160, H256, U256}; +use ethkey; use fetch::{self, Fetch}; use hash::keccak_buffer; +use sync::ManageNetwork; use updater::{Service as UpdateService}; use jsonrpc_core::{BoxFuture, Result}; use jsonrpc_core::futures::Future; use v1::helpers::errors; use v1::traits::ParitySet; -use v1::types::{Bytes, H160, H256, U256, ReleaseInfo, Transaction}; +use v1::types::{Bytes, ReleaseInfo, Transaction}; + +#[cfg(any(test, feature = "accounts"))] +pub mod accounts { + use super::*; + use accounts::AccountProvider; + use v1::traits::ParitySetAccounts; + use v1::helpers::deprecated::DeprecationNotice; + use v1::helpers::engine_signer::EngineSigner; + + /// Parity-specific account-touching RPC interfaces. + pub struct ParitySetAccountsClient { + miner: Arc, + accounts: Arc, + deprecation_notice: DeprecationNotice, + } + + impl ParitySetAccountsClient { + /// Creates new ParitySetAccountsClient + pub fn new( + accounts: &Arc, + miner: &Arc, + ) -> Self { + ParitySetAccountsClient { + accounts: accounts.clone(), + miner: miner.clone(), + deprecation_notice: Default::default(), + } + } + } + + impl ParitySetAccounts for ParitySetAccountsClient { + fn set_engine_signer(&self, address: H160, password: String) -> Result { + self.deprecation_notice.print( + "parity_setEngineSigner", + "use `parity_setEngineSignerSecret` instead. See #9997 for context." + ); + + let signer = Box::new(EngineSigner::new( + self.accounts.clone(), + address.clone().into(), + password.into(), + )); + self.miner.set_author(miner::Author::Sealer(signer)); + Ok(true) + } + } +} /// Parity-specific rpc interface for operations altering the settings. pub struct ParitySetClient { @@ -57,7 +106,7 @@ impl ParitySetClient miner: miner.clone(), updater: updater.clone(), net: net.clone(), - fetch: fetch, + fetch, } } } @@ -69,9 +118,11 @@ impl ParitySet for ParitySetClient where F: Fetch + 'static, { - fn set_min_gas_price(&self, _gas_price: U256) -> Result { - warn!("setMinGasPrice is deprecated. Ignoring request."); - Ok(false) + fn set_min_gas_price(&self, gas_price: U256) -> Result { + match self.miner.set_minimal_gas_price(gas_price) { + Ok(success) => Ok(success), + Err(e) => Err(errors::unsupported(e, None)), + } } fn set_transactions_limit(&self, _limit: usize) -> Result { @@ -85,15 +136,15 @@ impl ParitySet for ParitySetClient where } fn set_gas_floor_target(&self, target: U256) -> Result { - let mut range = self.miner.authoring_params().gas_range_target.clone(); - range.0 = target.into(); + let mut range = self.miner.authoring_params().gas_range_target; + range.0 = target; self.miner.set_gas_range_target(range); Ok(true) } fn set_gas_ceil_target(&self, target: U256) -> Result { - let mut range = self.miner.authoring_params().gas_range_target.clone(); - range.1 = target.into(); + let mut range = self.miner.authoring_params().gas_range_target; + range.1 = target; self.miner.set_gas_range_target(range); Ok(true) } @@ -104,12 +155,13 @@ impl ParitySet for ParitySetClient where } fn set_author(&self, address: H160) -> Result { - self.miner.set_author(address.into(), None).map_err(Into::into).map_err(errors::password)?; + self.miner.set_author(miner::Author::External(address)); Ok(true) } - fn set_engine_signer(&self, address: H160, password: String) -> Result { - self.miner.set_author(address.into(), Some(password.into())).map_err(Into::into).map_err(errors::password)?; + fn set_engine_signer_secret(&self, secret: H256) -> Result { + let keypair = ethkey::KeyPair::from_secret(secret.into()).map_err(|e| errors::account("Invalid secret", e))?; + self.miner.set_author(miner::Author::Sealer(ethcore::engines::signer::from_keypair(keypair))); Ok(true) } @@ -159,8 +211,7 @@ impl ParitySet for ParitySetClient where } fn set_spec_name(&self, spec_name: String) -> Result { - self.client.set_spec_name(spec_name); - Ok(true) + self.client.set_spec_name(spec_name).map(|_| true).map_err(|()| errors::cannot_restart()) } fn hash_content(&self, url: String) -> BoxFuture { @@ -185,10 +236,8 @@ impl ParitySet for ParitySetClient where } fn remove_transaction(&self, hash: H256) -> Result> { - let hash = hash.into(); - Ok(self.miner.remove_transaction(&hash) - .map(|t| Transaction::from_pending(t.pending().clone())) + .map(|t| Transaction::from_pending(t.pending().clone())) ) } } diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index e413903c59..b6af1f81e5 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -18,20 +18,22 @@ use std::sync::Arc; use std::time::Duration; +use accounts::AccountProvider; use bytes::Bytes; -use ethcore::account_provider::AccountProvider; -use types::transaction::PendingTransaction; -use types::transaction::SignedTransaction; -use ethereum_types::{H520, U128, Address}; +use eip_712::{EIP712, hash_structured_data}; +use ethereum_types::{H160, H256, H520, U128, Address}; use ethkey::{public_to_address, recover, Signature}; +use types::transaction::{PendingTransaction, SignedTransaction}; -use jsonrpc_core::{BoxFuture, Result}; use jsonrpc_core::futures::{future, Future}; -use v1::helpers::{errors, eip191}; +use jsonrpc_core::types::Value; +use jsonrpc_core::{BoxFuture, Result}; +use v1::helpers::deprecated::{self, DeprecationNotice}; use v1::helpers::dispatch::{self, eth_data_hash, Dispatcher, SignWith, PostSign, WithToken}; +use v1::helpers::{errors, eip191}; +use v1::metadata::Metadata; use v1::traits::Personal; use v1::types::{ - H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, U128 as RpcU128, Bytes as RpcBytes, ConfirmationPayload as RpcConfirmationPayload, ConfirmationResponse as RpcConfirmationResponse, @@ -39,9 +41,6 @@ use v1::types::{ RichRawTransaction as RpcRichRawTransaction, EIP191Version, }; -use v1::metadata::Metadata; -use eip_712::{EIP712, hash_structured_data}; -use jsonrpc_core::types::Value; /// Account management (personal) rpc implementation. pub struct PersonalClient { @@ -49,6 +48,7 @@ pub struct PersonalClient { dispatcher: D, allow_perm_unlock: bool, allow_experimental_rpcs: bool, + deprecation_notice: DeprecationNotice, } impl PersonalClient { @@ -64,6 +64,7 @@ impl PersonalClient { dispatcher, allow_perm_unlock, allow_experimental_rpcs, + deprecation_notice: DeprecationNotice::default(), } } } @@ -94,9 +95,10 @@ impl PersonalClient { Err(e) => return Box::new(future::err(e)), }; + let accounts = Arc::new(dispatch::Signer::new(accounts)) as _; Box::new(dispatcher.fill_optional_fields(request.into(), default, false) .and_then(move |filled| { - dispatcher.sign(accounts, filled, SignWith::Password(password.into()), post_sign) + dispatcher.sign(filled, &accounts, SignWith::Password(password.into()), post_sign) }) ) } @@ -105,18 +107,21 @@ impl PersonalClient { impl Personal for PersonalClient { type Metadata = Metadata; - fn accounts(&self) -> Result> { + fn accounts(&self) -> Result> { + self.deprecation_notice.print("personal_accounts", deprecated::msgs::ACCOUNTS); let accounts = self.accounts.accounts().map_err(|e| errors::account("Could not fetch accounts.", e))?; - Ok(accounts.into_iter().map(Into::into).collect::>()) + Ok(accounts.into_iter().map(Into::into).collect::>()) } - fn new_account(&self, pass: String) -> Result { + fn new_account(&self, pass: String) -> Result { + self.deprecation_notice.print("personal_newAccount", deprecated::msgs::ACCOUNTS); self.accounts.new_account(&pass.into()) .map(Into::into) .map_err(|e| errors::account("Could not create account.", e)) } - fn unlock_account(&self, account: RpcH160, account_pass: String, duration: Option) -> Result { + fn unlock_account(&self, account: H160, account_pass: String, duration: Option) -> Result { + self.deprecation_notice.print("personal_unlockAccount", deprecated::msgs::ACCOUNTS); let account: Address = account.into(); let store = self.accounts.clone(); let duration = match duration { @@ -135,8 +140,8 @@ impl Personal for PersonalClient { let r = match (self.allow_perm_unlock, duration) { (false, None) => store.unlock_account_temporarily(account, account_pass.into()), (false, _) => return Err(errors::unsupported( - "Time-unlocking is only supported in --geth compatibility mode.", - Some("Restart your client with --geth flag or use personal_sendTransaction instead."), + "Time-unlocking is not supported when permanent unlock is disabled.", + Some("Use personal_sendTransaction or enable permanent unlocking, instead."), )), (true, Some(0)) => store.unlock_account_permanently(account, account_pass.into()), (true, Some(d)) => store.unlock_account_timed(account, account_pass.into(), Duration::from_secs(d.into())), @@ -148,15 +153,16 @@ impl Personal for PersonalClient { } } - fn sign(&self, data: RpcBytes, account: RpcH160, password: String) -> BoxFuture { + fn sign(&self, data: RpcBytes, account: H160, password: String) -> BoxFuture { + self.deprecation_notice.print("personal_sign", deprecated::msgs::ACCOUNTS); let dispatcher = self.dispatcher.clone(); - let accounts = self.accounts.clone(); + let accounts = Arc::new(dispatch::Signer::new(self.accounts.clone())) as _; let payload = RpcConfirmationPayload::EthSignMessage((account.clone(), data).into()); Box::new(dispatch::from_rpc(payload, account.into(), &dispatcher) - .and_then(|payload| { - dispatch::execute(dispatcher, accounts, payload, dispatch::SignWith::Password(password.into())) + .and_then(move |payload| { + dispatch::execute(dispatcher, &accounts, payload, dispatch::SignWith::Password(password.into())) }) .map(|v| v.into_value()) .then(|res| match res { @@ -166,18 +172,19 @@ impl Personal for PersonalClient { })) } - fn sign_191(&self, version: EIP191Version, data: Value, account: RpcH160, password: String) -> BoxFuture { + fn sign_191(&self, version: EIP191Version, data: Value, account: H160, password: String) -> BoxFuture { + self.deprecation_notice.print("personal_sign191", deprecated::msgs::ACCOUNTS); try_bf!(errors::require_experimental(self.allow_experimental_rpcs, "191")); let data = try_bf!(eip191::hash_message(version, data)); let dispatcher = self.dispatcher.clone(); - let accounts = self.accounts.clone(); + let accounts = Arc::new(dispatch::Signer::new(self.accounts.clone())) as _; let payload = RpcConfirmationPayload::EIP191SignMessage((account.clone(), data.into()).into()); Box::new(dispatch::from_rpc(payload, account.into(), &dispatcher) - .and_then(|payload| { - dispatch::execute(dispatcher, accounts, payload, dispatch::SignWith::Password(password.into())) + .and_then(move |payload| { + dispatch::execute(dispatcher, &accounts, payload, dispatch::SignWith::Password(password.into())) }) .map(|v| v.into_value()) .then(|res| match res { @@ -188,7 +195,8 @@ impl Personal for PersonalClient { ) } - fn sign_typed_data(&self, typed_data: EIP712, account: RpcH160, password: String) -> BoxFuture { + fn sign_typed_data(&self, typed_data: EIP712, account: H160, password: String) -> BoxFuture { + self.deprecation_notice.print("personal_signTypedData", deprecated::msgs::ACCOUNTS); try_bf!(errors::require_experimental(self.allow_experimental_rpcs, "712")); let data = match hash_structured_data(typed_data) { @@ -196,13 +204,13 @@ impl Personal for PersonalClient { Err(err) => return Box::new(future::err(errors::invalid_call_data(err.kind()))), }; let dispatcher = self.dispatcher.clone(); - let accounts = self.accounts.clone(); + let accounts = Arc::new(dispatch::Signer::new(self.accounts.clone())) as _; let payload = RpcConfirmationPayload::EIP191SignMessage((account.clone(), data.into()).into()); Box::new(dispatch::from_rpc(payload, account.into(), &dispatcher) - .and_then(|payload| { - dispatch::execute(dispatcher, accounts, payload, dispatch::SignWith::Password(password.into())) + .and_then(move |payload| { + dispatch::execute(dispatcher, &accounts, payload, dispatch::SignWith::Password(password.into())) }) .map(|v| v.into_value()) .then(|res| match res { @@ -213,7 +221,7 @@ impl Personal for PersonalClient { ) } - fn ec_recover(&self, data: RpcBytes, signature: RpcH520) -> BoxFuture { + fn ec_recover(&self, data: RpcBytes, signature: H520) -> BoxFuture { let signature: H520 = signature.into(); let signature = Signature::from_electrum(&signature); let data: Bytes = data.into(); @@ -229,6 +237,8 @@ impl Personal for PersonalClient { } fn sign_transaction(&self, meta: Metadata, request: TransactionRequest, password: String) -> BoxFuture { + self.deprecation_notice.print("personal_signTransaction", deprecated::msgs::ACCOUNTS); + let condition = request.condition.clone().map(Into::into); let dispatcher = self.dispatcher.clone(); Box::new(self.do_sign_transaction(meta, request, password, ()) @@ -236,24 +246,24 @@ impl Personal for PersonalClient { .map(move |pending_tx| dispatcher.enrich(pending_tx.transaction))) } - fn send_transaction(&self, meta: Metadata, request: TransactionRequest, password: String) -> BoxFuture { + fn send_transaction(&self, meta: Metadata, request: TransactionRequest, password: String) -> BoxFuture { + self.deprecation_notice.print("personal_sendTransaction", deprecated::msgs::ACCOUNTS); let condition = request.condition.clone().map(Into::into); let dispatcher = self.dispatcher.clone(); - Box::new(self.do_sign_transaction(meta, request, password, move |signed: WithToken| { - dispatcher.dispatch_transaction( - PendingTransaction::new( - signed.into_value(), - condition + Box::new( + self.do_sign_transaction(meta, request, password, move |signed: WithToken| { + dispatcher.dispatch_transaction( + PendingTransaction::new( + signed.into_value(), + condition + ) ) - ) - }) - .and_then(|hash| { - Ok(RpcH256::from(hash)) }) ) } - fn sign_and_send_transaction(&self, meta: Metadata, request: TransactionRequest, password: String) -> BoxFuture { + fn sign_and_send_transaction(&self, meta: Metadata, request: TransactionRequest, password: String) -> BoxFuture { + self.deprecation_notice.print("personal_signAndSendTransaction", Some("use personal_sendTransaction instead.")); warn!("Using deprecated personal_signAndSendTransaction, use personal_sendTransaction instead."); self.send_transaction(meta, request, password) } diff --git a/rpc/src/v1/impls/private.rs b/rpc/src/v1/impls/private.rs index 8744390ba2..c3be3f9150 100644 --- a/rpc/src/v1/impls/private.rs +++ b/rpc/src/v1/impls/private.rs @@ -21,11 +21,11 @@ use std::sync::Arc; use rlp::Rlp; use ethcore_private_tx::Provider as PrivateTransactionManager; -use ethereum_types::Address; +use ethereum_types::{Address, H160, H256, U256}; use types::transaction::SignedTransaction; use jsonrpc_core::{Error}; -use v1::types::{Bytes, PrivateTransactionReceipt, H160, H256, TransactionRequest, U256, +use v1::types::{Bytes, PrivateTransactionReceipt, TransactionRequest, BlockNumber, PrivateTransactionReceiptAndTransaction, CallRequest, block_number_to_id}; use v1::traits::Private; use v1::metadata::Metadata; @@ -60,7 +60,7 @@ impl Private for PrivateClient { .map_err(errors::rlp) .and_then(|tx| SignedTransaction::new(tx).map_err(errors::transaction))?; let client = self.unwrap_manager()?; - let receipt = client.create_private_transaction(signed_transaction).map_err(|e| errors::private_message(e))?; + let receipt = client.create_private_transaction(signed_transaction).map_err(errors::private_message)?; Ok(receipt.into()) } @@ -76,16 +76,17 @@ impl Private for PrivateClient { num => block_number_to_id(num) }; - let (transaction, contract_address) = client.public_creation_transaction(id, &signed_transaction, addresses.as_slice(), gas_price.into()) - .map_err(|e| errors::private_message(e))?; + let (transaction, contract_address) = client + .public_creation_transaction(id, &signed_transaction, addresses.as_slice(), gas_price) + .map_err(errors::private_message)?; let tx_hash = transaction.hash(None); let request = TransactionRequest { - from: Some(signed_transaction.sender().into()), + from: Some(signed_transaction.sender()), to: None, - nonce: Some(transaction.nonce.into()), - gas_price: Some(transaction.gas_price.into()), - gas: Some(transaction.gas.into()), - value: Some(transaction.value.into()), + nonce: Some(transaction.nonce), + gas_price: Some(transaction.gas_price), + gas: Some(transaction.gas), + value: Some(transaction.value), data: Some(transaction.data.into()), condition: None, }; @@ -93,8 +94,8 @@ impl Private for PrivateClient { Ok(PrivateTransactionReceiptAndTransaction { transaction: request, receipt: PrivateTransactionReceipt { - transaction_hash: tx_hash.into(), - contract_address: contract_address.map(|address| address.into()), + transaction_hash: tx_hash, + contract_address, status_code: 0, } }) @@ -109,13 +110,13 @@ impl Private for PrivateClient { let request = CallRequest::into(request); let signed = fake_sign::sign_call(request)?; let client = self.unwrap_manager()?; - let executed_result = client.private_call(id, &signed).map_err(|e| errors::private_message(e))?; + let executed_result = client.private_call(id, &signed).map_err(errors::private_message)?; Ok(executed_result.output.into()) } fn private_contract_key(&self, contract_address: H160) -> Result { let client = self.unwrap_manager()?; - let key = client.contract_key_id(&contract_address.into()).map_err(|e| errors::private_message(e))?; - Ok(key.into()) + let key = client.contract_key_id(&contract_address).map_err(errors::private_message)?; + Ok(key) } } diff --git a/rpc/src/v1/impls/pubsub.rs b/rpc/src/v1/impls/pubsub.rs index fb147768dd..1575aacdd6 100644 --- a/rpc/src/v1/impls/pubsub.rs +++ b/rpc/src/v1/impls/pubsub.rs @@ -22,8 +22,7 @@ use parking_lot::RwLock; use jsonrpc_core::{self as core, Result, MetaIoHandler}; use jsonrpc_core::futures::{future, Future, Stream, Sink}; -use jsonrpc_macros::Trailing; -use jsonrpc_macros::pubsub::Subscriber; +use jsonrpc_pubsub::typed::Subscriber; use jsonrpc_pubsub::SubscriptionId; use tokio_timer; @@ -81,8 +80,8 @@ impl PubSubClient { impl> PubSub for PubSubClient { type Metadata = Metadata; - fn parity_subscribe(&self, mut meta: Metadata, subscriber: Subscriber, method: String, params: Trailing) { - let params = params.unwrap_or(core::Params::Array(vec![])); + fn parity_subscribe(&self, mut meta: Metadata, subscriber: Subscriber, method: String, params: Option) { + let params = params.unwrap_or_else(|| core::Params::Array(vec![])); // Make sure to get rid of PubSub session otherwise it will never be dropped. meta.session = None; @@ -100,7 +99,7 @@ impl> PubSub for PubSubClient { } } - fn parity_unsubscribe(&self, id: SubscriptionId) -> Result { + fn parity_unsubscribe(&self, _: Option, id: SubscriptionId) -> Result { let res = self.poll_manager.write().unsubscribe(&id); Ok(res) } diff --git a/rpc/src/v1/impls/rpc.rs b/rpc/src/v1/impls/rpc.rs index f218c5ade6..0c2afd57ca 100644 --- a/rpc/src/v1/impls/rpc.rs +++ b/rpc/src/v1/impls/rpc.rs @@ -32,8 +32,8 @@ impl RpcClient { let valid_apis = vec!["web3", "eth", "net", "personal", "rpc"]; RpcClient { - modules: modules, - valid_apis: valid_apis.into_iter().map(|x| x.to_owned()).collect(), + modules, + valid_apis: valid_apis.into_iter().map(ToOwned::to_owned).collect(), } } } diff --git a/rpc/src/v1/impls/secretstore.rs b/rpc/src/v1/impls/secretstore.rs index f71de4e19f..b6526b85d5 100644 --- a/rpc/src/v1/impls/secretstore.rs +++ b/rpc/src/v1/impls/secretstore.rs @@ -19,16 +19,17 @@ use std::collections::BTreeSet; use std::sync::Arc; +use accounts::AccountProvider; use crypto::DEFAULT_MAC; +use ethereum_types::{H160, H256, H512}; use ethkey::Secret; -use ethcore::account_provider::AccountProvider; use jsonrpc_core::Result; use v1::helpers::errors; use v1::helpers::secretstore::{generate_document_key, encrypt_document, decrypt_document, decrypt_document_with_shadow, ordered_servers_keccak}; use v1::traits::SecretStore; -use v1::types::{H160, H256, H512, Bytes, EncryptedDocumentKey}; +use v1::types::{Bytes, EncryptedDocumentKey}; use ethkey::Password; /// Parity implementation. diff --git a/rpc/src/v1/impls/signer.rs b/rpc/src/v1/impls/signer.rs index 8f83547ab2..4edac1144a 100644 --- a/rpc/src/v1/impls/signer.rs +++ b/rpc/src/v1/impls/signer.rs @@ -18,7 +18,7 @@ use std::sync::Arc; -use ethcore::account_provider::AccountProvider; +use ethereum_types::U256; use ethkey; use parity_runtime::Executor; use parking_lot::Mutex; @@ -28,26 +28,28 @@ use types::transaction::{SignedTransaction, PendingTransaction}; use jsonrpc_core::{Result, BoxFuture, Error}; use jsonrpc_core::futures::{future, Future, IntoFuture}; use jsonrpc_core::futures::future::Either; -use jsonrpc_pubsub::SubscriptionId; -use jsonrpc_macros::pubsub::{Sink, Subscriber}; +use jsonrpc_pubsub::{SubscriptionId, typed::{Sink, Subscriber}}; +use v1::helpers::deprecated::{self, DeprecationNotice}; use v1::helpers::dispatch::{self, Dispatcher, WithToken, eth_data_hash}; -use v1::helpers::{errors, SignerService, SigningQueue, ConfirmationPayload, FilledTransactionRequest, Subscribers}; +use v1::helpers::{errors, ConfirmationPayload, FilledTransactionRequest, Subscribers}; +use v1::helpers::external_signer::{SigningQueue, SignerService}; use v1::metadata::Metadata; use v1::traits::Signer; -use v1::types::{TransactionModification, ConfirmationRequest, ConfirmationResponse, ConfirmationResponseWithToken, U256, Bytes}; +use v1::types::{TransactionModification, ConfirmationRequest, ConfirmationResponse, ConfirmationResponseWithToken, Bytes}; /// Transactions confirmation (personal) rpc implementation. pub struct SignerClient { signer: Arc, - accounts: Arc, + accounts: Arc, dispatcher: D, subscribers: Arc>>>>, + deprecation_notice: DeprecationNotice, } impl SignerClient { /// Create new instance of signer client. pub fn new( - store: &Arc, + accounts: Arc, dispatcher: D, signer: &Arc, executor: Executor, @@ -71,18 +73,18 @@ impl SignerClient { SignerClient { signer: signer.clone(), - accounts: store.clone(), + accounts: accounts.clone(), dispatcher, subscribers, + deprecation_notice: Default::default(), } } fn confirm_internal(&self, id: U256, modification: TransactionModification, f: F) -> BoxFuture> where - F: FnOnce(D, Arc, ConfirmationPayload) -> T, + F: FnOnce(D, &Arc, ConfirmationPayload) -> T, T: IntoFuture, Error=Error>, T::Future: Send + 'static { - let id = id.into(); let dispatcher = self.dispatcher.clone(); let signer = self.signer.clone(); @@ -91,21 +93,21 @@ impl SignerClient { // Modify payload if let ConfirmationPayload::SendTransaction(ref mut request) = payload { if let Some(sender) = modification.sender { - request.from = sender.into(); + request.from = sender; // Altering sender should always reset the nonce. request.nonce = None; } if let Some(gas_price) = modification.gas_price { - request.gas_price = gas_price.into(); + request.gas_price = gas_price; } if let Some(gas) = modification.gas { - request.gas = gas.into(); + request.gas = gas; } if let Some(ref condition) = modification.condition { request.condition = condition.clone().map(Into::into); } } - let fut = f(dispatcher, self.accounts.clone(), payload); + let fut = f(dispatcher, &self.accounts, payload); Either::A(fut.into_future().then(move |result| { // Execute if let Ok(ref response) = result { @@ -156,6 +158,8 @@ impl Signer for SignerClient { type Metadata = Metadata; fn requests_to_confirm(&self) -> Result> { + self.deprecation_notice.print("signer_requestsToConfirm", deprecated::msgs::ACCOUNTS); + Ok(self.signer.requests() .into_iter() .map(Into::into) @@ -168,27 +172,31 @@ impl Signer for SignerClient { fn confirm_request(&self, id: U256, modification: TransactionModification, pass: String) -> BoxFuture { + self.deprecation_notice.print("signer_confirmRequest", deprecated::msgs::ACCOUNTS); + Box::new(self.confirm_internal(id, modification, move |dis, accounts, payload| { dispatch::execute(dis, accounts, payload, dispatch::SignWith::Password(pass.into())) - }).map(|v| v.into_value())) + }).map(dispatch::WithToken::into_value)) } fn confirm_request_with_token(&self, id: U256, modification: TransactionModification, token: String) -> BoxFuture { + self.deprecation_notice.print("signer_confirmRequestWithToken", deprecated::msgs::ACCOUNTS); + Box::new(self.confirm_internal(id, modification, move |dis, accounts, payload| { dispatch::execute(dis, accounts, payload, dispatch::SignWith::Token(token.into())) }).and_then(|v| match v { WithToken::No(_) => Err(errors::internal("Unexpected response without token.", "")), WithToken::Yes(response, token) => Ok(ConfirmationResponseWithToken { result: response, - token: token, + token, }), })) } fn confirm_request_raw(&self, id: U256, bytes: Bytes) -> Result { - let id = id.into(); + self.deprecation_notice.print("signer_confirmRequestRaw", deprecated::msgs::ACCOUNTS); self.signer.take(&id).map(|sender| { let payload = sender.request.payload.clone(); @@ -238,24 +246,26 @@ impl Signer for SignerClient { } fn reject_request(&self, id: U256) -> Result { - let res = self.signer.take(&id.into()).map(|sender| self.signer.request_rejected(sender)); + self.deprecation_notice.print("signer_rejectRequest", deprecated::msgs::ACCOUNTS); + + let res = self.signer.take(&id).map(|sender| self.signer.request_rejected(sender)); Ok(res.is_some()) } fn generate_token(&self) -> Result { - self.signer.generate_token() - .map_err(|e| errors::token(e)) - } + self.deprecation_notice.print("signer_generateAuthorizationToken", deprecated::msgs::ACCOUNTS); - fn generate_web_proxy_token(&self, domain: String) -> Result { - Ok(self.signer.generate_web_proxy_access_token(domain.into())) + self.signer.generate_token() + .map_err(errors::token) } fn subscribe_pending(&self, _meta: Self::Metadata, sub: Subscriber>) { + self.deprecation_notice.print("signer_subscribePending", deprecated::msgs::ACCOUNTS); + self.subscribers.lock().push(sub) } - fn unsubscribe_pending(&self, id: SubscriptionId) -> Result { + fn unsubscribe_pending(&self, _: Option, id: SubscriptionId) -> Result { let res = self.subscribers.lock().remove(&id).is_some(); Ok(res) } diff --git a/rpc/src/v1/impls/signing.rs b/rpc/src/v1/impls/signing.rs index c0ba955b7e..38ca6d59c9 100644 --- a/rpc/src/v1/impls/signing.rs +++ b/rpc/src/v1/impls/signing.rs @@ -18,24 +18,26 @@ use std::sync::Arc; use transient_hashmap::TransientHashMap; -use ethereum_types::U256; use parking_lot::Mutex; -use ethcore::account_provider::AccountProvider; +use ethereum_types::{H160, H256, H520, U256}; use jsonrpc_core::{BoxFuture, Result, Error}; use jsonrpc_core::futures::{future, Future, Poll, Async}; use jsonrpc_core::futures::future::Either; -use v1::helpers::{ - errors, DefaultAccount, SignerService, SigningQueue, + +use v1::helpers::deprecated::{self, DeprecationNotice}; +use v1::helpers::dispatch::{self, Dispatcher}; +use v1::helpers::errors; +use v1::helpers::external_signer::{ + SignerService, SigningQueue, ConfirmationReceiver as RpcConfirmationReceiver, ConfirmationResult as RpcConfirmationResult, }; -use v1::helpers::dispatch::{self, Dispatcher}; use v1::metadata::Metadata; use v1::traits::{EthSigning, ParitySigning}; use v1::types::{ - H160 as RpcH160, H256 as RpcH256, U256 as RpcU256, Bytes as RpcBytes, H520 as RpcH520, + Bytes as RpcBytes, Either as RpcEither, RichRawTransaction as RpcRichRawTransaction, TransactionRequest as RpcTransactionRequest, @@ -73,7 +75,7 @@ fn schedule(executor: Executor, future: RpcConfirmationReceiver) { { let mut confirmations = confirmations.lock(); - confirmations.insert(id.clone(), None); + confirmations.insert(id, None); } let future = future.then(move |result| { @@ -89,39 +91,38 @@ fn schedule(executor: Executor, /// Implementation of functions that require signing when no trusted signer is used. pub struct SigningQueueClient { signer: Arc, - accounts: Arc, + accounts: Arc, dispatcher: D, executor: Executor, // None here means that the request hasn't yet been confirmed confirmations: Arc>>>, + deprecation_notice: DeprecationNotice, } impl SigningQueueClient { /// Creates a new signing queue client given shared signing queue. - pub fn new(signer: &Arc, dispatcher: D, executor: Executor, accounts: &Arc) -> Self { + pub fn new(signer: &Arc, dispatcher: D, executor: Executor, accounts: &Arc) -> Self { SigningQueueClient { signer: signer.clone(), accounts: accounts.clone(), dispatcher, executor, confirmations: Arc::new(Mutex::new(TransientHashMap::new(MAX_PENDING_DURATION_SEC))), + deprecation_notice: Default::default(), } } - fn dispatch(&self, payload: RpcConfirmationPayload, default_account: DefaultAccount, origin: Origin) -> BoxFuture { + fn dispatch(&self, payload: RpcConfirmationPayload, origin: Origin) -> BoxFuture { + let default_account = self.accounts.default_account(); let accounts = self.accounts.clone(); - let default_account = match default_account { - DefaultAccount::Provided(acc) => acc, - }; - let dispatcher = self.dispatcher.clone(); let signer = self.signer.clone(); Box::new(dispatch::from_rpc(payload, default_account, &dispatcher) .and_then(move |payload| { let sender = payload.sender(); if accounts.is_unlocked(&sender) { - Either::A(dispatch::execute(dispatcher, accounts, payload, dispatch::SignWith::Nothing) - .map(|v| v.into_value()) + Either::A(dispatch::execute(dispatcher, &accounts, payload, dispatch::SignWith::Nothing) + .map(dispatch::WithToken::into_value) .map(DispatchResult::Value)) } else { Either::B(future::done( @@ -138,43 +139,44 @@ impl ParitySigning for SigningQueueClient { type Metadata = Metadata; fn compose_transaction(&self, _meta: Metadata, transaction: RpcTransactionRequest) -> BoxFuture { - let default_account = self.accounts.default_account().ok().unwrap_or_default(); + let default_account = self.accounts.default_account(); Box::new(self.dispatcher.fill_optional_fields(transaction.into(), default_account, true).map(Into::into)) } - fn post_sign(&self, meta: Metadata, address: RpcH160, data: RpcBytes) -> BoxFuture> { + fn post_sign(&self, meta: Metadata, address: H160, data: RpcBytes) -> BoxFuture> { + self.deprecation_notice.print("parity_postSign", deprecated::msgs::ACCOUNTS); let executor = self.executor.clone(); let confirmations = self.confirmations.clone(); Box::new(self.dispatch( - RpcConfirmationPayload::EthSignMessage((address.clone(), data).into()), - DefaultAccount::Provided(address.into()), + RpcConfirmationPayload::EthSignMessage((address, data).into()), meta.origin ).map(move |result| match result { DispatchResult::Value(v) => RpcEither::Or(v), DispatchResult::Future(id, future) => { schedule(executor, confirmations, id, future); - RpcEither::Either(id.into()) + RpcEither::Either(id) }, })) } - fn post_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture> { + fn post_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture> { + self.deprecation_notice.print("parity_postTransaction", deprecated::msgs::ACCOUNTS); let executor = self.executor.clone(); let confirmations = self.confirmations.clone(); - Box::new(self.dispatch(RpcConfirmationPayload::SendTransaction(request), DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default()), meta.origin) + Box::new(self.dispatch(RpcConfirmationPayload::SendTransaction(request), meta.origin) .map(|result| match result { DispatchResult::Value(v) => RpcEither::Or(v), DispatchResult::Future(id, future) => { schedule(executor, confirmations, id, future); - RpcEither::Either(id.into()) + RpcEither::Either(id) }, })) } - fn check_request(&self, id: RpcU256) -> Result> { - let id: U256 = id.into(); + fn check_request(&self, id: U256) -> Result> { + self.deprecation_notice.print("parity_checkRequest", deprecated::msgs::ACCOUNTS); match self.confirmations.lock().get(&id) { None => Err(errors::request_not_found()), // Request info has been dropped, or even never been there Some(&None) => Ok(None), // No confirmation yet, request is known, confirmation is pending @@ -182,10 +184,10 @@ impl ParitySigning for SigningQueueClient { } } - fn decrypt_message(&self, meta: Metadata, address: RpcH160, data: RpcBytes) -> BoxFuture { + fn decrypt_message(&self, meta: Metadata, address: H160, data: RpcBytes) -> BoxFuture { + self.deprecation_notice.print("parity_decryptMessage", deprecated::msgs::ACCOUNTS); let res = self.dispatch( - RpcConfirmationPayload::Decrypt((address.clone(), data).into()), - address.into(), + RpcConfirmationPayload::Decrypt((address, data).into()), meta.origin, ); @@ -202,10 +204,10 @@ impl ParitySigning for SigningQueueClient { impl EthSigning for SigningQueueClient { type Metadata = Metadata; - fn sign(&self, meta: Metadata, address: RpcH160, data: RpcBytes) -> BoxFuture { + fn sign(&self, meta: Metadata, address: H160, data: RpcBytes) -> BoxFuture { + self.deprecation_notice.print("eth_sign", deprecated::msgs::ACCOUNTS); let res = self.dispatch( - RpcConfirmationPayload::EthSignMessage((address.clone(), data).into()), - address.into(), + RpcConfirmationPayload::EthSignMessage((address, data).into()), meta.origin, ); @@ -217,10 +219,10 @@ impl EthSigning for SigningQueueClient { })) } - fn send_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture { + fn send_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture { + self.deprecation_notice.print("eth_sendTransaction", deprecated::msgs::ACCOUNTS); let res = self.dispatch( RpcConfirmationPayload::SendTransaction(request), - DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default()), meta.origin, ); @@ -233,9 +235,10 @@ impl EthSigning for SigningQueueClient { } fn sign_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture { + self.deprecation_notice.print("eth_signTransaction", deprecated::msgs::ACCOUNTS); + let res = self.dispatch( RpcConfirmationPayload::SignTransaction(request), - DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default()), meta.origin, ); diff --git a/rpc/src/v1/impls/signing_unsafe.rs b/rpc/src/v1/impls/signing_unsafe.rs index eab2489f12..f08a9ffbe6 100644 --- a/rpc/src/v1/impls/signing_unsafe.rs +++ b/rpc/src/v1/impls/signing_unsafe.rs @@ -18,17 +18,16 @@ use std::sync::Arc; -use ethcore::account_provider::AccountProvider; - +use ethereum_types::{Address, H160, H256, H520, U256}; use jsonrpc_core::{BoxFuture, Result}; use jsonrpc_core::futures::{future, Future}; -use v1::helpers::{errors, DefaultAccount}; +use v1::helpers::{errors}; +use v1::helpers::deprecated::{self, DeprecationNotice}; use v1::helpers::dispatch::{self, Dispatcher}; use v1::metadata::Metadata; use v1::traits::{EthSigning, ParitySigning}; use v1::types::{ - U256 as RpcU256, - H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, Bytes as RpcBytes, + Bytes as RpcBytes, Either as RpcEither, RichRawTransaction as RpcRichRawTransaction, TransactionRequest as RpcTransactionRequest, @@ -38,31 +37,30 @@ use v1::types::{ /// Implementation of functions that require signing when no trusted signer is used. pub struct SigningUnsafeClient { - accounts: Arc, + accounts: Arc, dispatcher: D, + deprecation_notice: DeprecationNotice, } impl SigningUnsafeClient { /// Creates new SigningUnsafeClient. - pub fn new(accounts: &Arc, dispatcher: D) -> Self { + pub fn new(accounts: &Arc, dispatcher: D) -> Self { SigningUnsafeClient { accounts: accounts.clone(), - dispatcher: dispatcher, + dispatcher, + deprecation_notice: Default::default(), } } - fn handle(&self, payload: RpcConfirmationPayload, account: DefaultAccount) -> BoxFuture { + fn handle(&self, payload: RpcConfirmationPayload, account: Address) -> BoxFuture { let accounts = self.accounts.clone(); - let default = match account { - DefaultAccount::Provided(acc) => acc, - }; let dis = self.dispatcher.clone(); - Box::new(dispatch::from_rpc(payload, default, &dis) + Box::new(dispatch::from_rpc(payload, account, &dis) .and_then(move |payload| { - dispatch::execute(dis, accounts, payload, dispatch::SignWith::Nothing) + dispatch::execute(dis, &accounts, payload, dispatch::SignWith::Nothing) }) - .map(|v| v.into_value())) + .map(dispatch::WithToken::into_value)) } } @@ -70,8 +68,9 @@ impl EthSigning for SigningUnsafeClient { type Metadata = Metadata; - fn sign(&self, _: Metadata, address: RpcH160, data: RpcBytes) -> BoxFuture { - Box::new(self.handle(RpcConfirmationPayload::EthSignMessage((address.clone(), data).into()), address.into()) + fn sign(&self, _: Metadata, address: H160, data: RpcBytes) -> BoxFuture { + self.deprecation_notice.print("eth_sign", deprecated::msgs::ACCOUNTS); + Box::new(self.handle(RpcConfirmationPayload::EthSignMessage((address, data).into()), address) .then(|res| match res { Ok(RpcConfirmationResponse::Signature(signature)) => Ok(signature), Err(e) => Err(e), @@ -79,8 +78,9 @@ impl EthSigning for SigningUnsafeClient })) } - fn send_transaction(&self, _meta: Metadata, request: RpcTransactionRequest) -> BoxFuture { - Box::new(self.handle(RpcConfirmationPayload::SendTransaction(request), DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default())) + fn send_transaction(&self, _meta: Metadata, request: RpcTransactionRequest) -> BoxFuture { + self.deprecation_notice.print("eth_sendTransaction", deprecated::msgs::ACCOUNTS); + Box::new(self.handle(RpcConfirmationPayload::SendTransaction(request), self.accounts.default_account()) .then(|res| match res { Ok(RpcConfirmationResponse::SendTransaction(hash)) => Ok(hash), Err(e) => Err(e), @@ -89,7 +89,9 @@ impl EthSigning for SigningUnsafeClient } fn sign_transaction(&self, _meta: Metadata, request: RpcTransactionRequest) -> BoxFuture { - Box::new(self.handle(RpcConfirmationPayload::SignTransaction(request), DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default())) + self.deprecation_notice.print("eth_signTransaction", deprecated::msgs::ACCOUNTS); + + Box::new(self.handle(RpcConfirmationPayload::SignTransaction(request), self.accounts.default_account()) .then(|res| match res { Ok(RpcConfirmationResponse::SignTransaction(tx)) => Ok(tx), Err(e) => Err(e), @@ -103,12 +105,13 @@ impl ParitySigning for SigningUnsafeClient { fn compose_transaction(&self, _meta: Metadata, transaction: RpcTransactionRequest) -> BoxFuture { let accounts = self.accounts.clone(); - let default_account = accounts.default_account().ok().unwrap_or_default(); + let default_account = accounts.default_account(); Box::new(self.dispatcher.fill_optional_fields(transaction.into(), default_account, true).map(Into::into)) } - fn decrypt_message(&self, _: Metadata, address: RpcH160, data: RpcBytes) -> BoxFuture { - Box::new(self.handle(RpcConfirmationPayload::Decrypt((address.clone(), data).into()), address.into()) + fn decrypt_message(&self, _: Metadata, address: H160, data: RpcBytes) -> BoxFuture { + self.deprecation_notice.print("parity_decryptMessage", deprecated::msgs::ACCOUNTS); + Box::new(self.handle(RpcConfirmationPayload::Decrypt((address, data).into()), address) .then(|res| match res { Ok(RpcConfirmationResponse::Decrypt(data)) => Ok(data), Err(e) => Err(e), @@ -116,17 +119,17 @@ impl ParitySigning for SigningUnsafeClient { })) } - fn post_sign(&self, _: Metadata, _: RpcH160, _: RpcBytes) -> BoxFuture> { + fn post_sign(&self, _: Metadata, _: H160, _: RpcBytes) -> BoxFuture> { // We don't support this in non-signer mode. Box::new(future::err(errors::signer_disabled())) } - fn post_transaction(&self, _: Metadata, _: RpcTransactionRequest) -> BoxFuture> { + fn post_transaction(&self, _: Metadata, _: RpcTransactionRequest) -> BoxFuture> { // We don't support this in non-signer mode. Box::new(future::err(errors::signer_disabled())) } - fn check_request(&self, _: RpcU256) -> Result> { + fn check_request(&self, _: U256) -> Result> { // We don't support this in non-signer mode. Err(errors::signer_disabled()) } diff --git a/rpc/src/v1/impls/traces.rs b/rpc/src/v1/impls/traces.rs index 92bf045f4c..a6301eda53 100644 --- a/rpc/src/v1/impls/traces.rs +++ b/rpc/src/v1/impls/traces.rs @@ -19,15 +19,16 @@ use std::sync::Arc; use ethcore::client::{BlockChainClient, CallAnalytics, TransactionId, TraceId, StateClient, StateInfo, Call, BlockId}; +use ethereum_types::H256; use rlp::Rlp; use types::transaction::SignedTransaction; use jsonrpc_core::Result; -use jsonrpc_macros::Trailing; use v1::Metadata; use v1::traits::Traces; use v1::helpers::{errors, fake_sign}; -use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, TraceResultsWithTransactionHash, TraceOptions, H256, block_number_to_id}; +use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, + TraceResultsWithTransactionHash, TraceOptions, block_number_to_id}; fn to_call_analytics(flags: TraceOptions) -> CallAnalytics { CallAnalytics { @@ -73,13 +74,13 @@ impl Traces for TracesClient where } fn transaction_traces(&self, transaction_hash: H256) -> Result>> { - Ok(self.client.transaction_traces(TransactionId::Hash(transaction_hash.into())) + Ok(self.client.transaction_traces(TransactionId::Hash(transaction_hash)) .map(|traces| traces.into_iter().map(LocalizedTrace::from).collect())) } fn trace(&self, transaction_hash: H256, address: Vec) -> Result> { let id = TraceId { - transaction: TransactionId::Hash(transaction_hash.into()), + transaction: TransactionId::Hash(transaction_hash), address: address.into_iter().map(|i| i.value()).collect() }; @@ -87,7 +88,7 @@ impl Traces for TracesClient where .map(LocalizedTrace::from)) } - fn call(&self, request: CallRequest, flags: TraceOptions, block: Trailing) -> Result { + fn call(&self, request: CallRequest, flags: TraceOptions, block: Option) -> Result { let block = block.unwrap_or_default(); let request = CallRequest::into(request); @@ -101,15 +102,15 @@ impl Traces for TracesClient where BlockNumber::Pending => return Err(errors::invalid_params("`BlockNumber::Pending` is not supported", ())), }; - let mut state = self.client.state_at(id).ok_or(errors::state_pruned())?; - let header = self.client.block_header(id).ok_or(errors::state_pruned())?; + let mut state = self.client.state_at(id).ok_or_else(errors::state_pruned)?; + let header = self.client.block_header(id).ok_or_else(errors::state_pruned)?; self.client.call(&signed, to_call_analytics(flags), &mut state, &header.decode().map_err(errors::decode)?) .map(TraceResults::from) .map_err(errors::call) } - fn call_many(&self, requests: Vec<(CallRequest, TraceOptions)>, block: Trailing) -> Result> { + fn call_many(&self, requests: Vec<(CallRequest, TraceOptions)>, block: Option) -> Result> { let block = block.unwrap_or_default(); let requests = requests.into_iter() @@ -128,15 +129,15 @@ impl Traces for TracesClient where BlockNumber::Pending => return Err(errors::invalid_params("`BlockNumber::Pending` is not supported", ())), }; - let mut state = self.client.state_at(id).ok_or(errors::state_pruned())?; - let header = self.client.block_header(id).ok_or(errors::state_pruned())?; + let mut state = self.client.state_at(id).ok_or_else(errors::state_pruned)?; + let header = self.client.block_header(id).ok_or_else(errors::state_pruned)?; self.client.call_many(&requests, &mut state, &header.decode().map_err(errors::decode)?) .map(|results| results.into_iter().map(TraceResults::from).collect()) .map_err(errors::call) } - fn raw_transaction(&self, raw_transaction: Bytes, flags: TraceOptions, block: Trailing) -> Result { + fn raw_transaction(&self, raw_transaction: Bytes, flags: TraceOptions, block: Option) -> Result { let block = block.unwrap_or_default(); let tx = Rlp::new(&raw_transaction.into_vec()).as_val().map_err(|e| errors::invalid_params("Transaction is not valid RLP", e))?; @@ -150,8 +151,8 @@ impl Traces for TracesClient where BlockNumber::Pending => return Err(errors::invalid_params("`BlockNumber::Pending` is not supported", ())), }; - let mut state = self.client.state_at(id).ok_or(errors::state_pruned())?; - let header = self.client.block_header(id).ok_or(errors::state_pruned())?; + let mut state = self.client.state_at(id).ok_or_else(errors::state_pruned)?; + let header = self.client.block_header(id).ok_or_else(errors::state_pruned)?; self.client.call(&signed, to_call_analytics(flags), &mut state, &header.decode().map_err(errors::decode)?) .map(TraceResults::from) @@ -159,7 +160,7 @@ impl Traces for TracesClient where } fn replay_transaction(&self, transaction_hash: H256, flags: TraceOptions) -> Result { - self.client.replay(TransactionId::Hash(transaction_hash.into()), to_call_analytics(flags)) + self.client.replay(TransactionId::Hash(transaction_hash), to_call_analytics(flags)) .map(TraceResults::from) .map_err(errors::call) } @@ -174,7 +175,7 @@ impl Traces for TracesClient where }; self.client.replay_block_transactions(id, to_call_analytics(flags)) - .map(|results| results.into_iter().map(TraceResultsWithTransactionHash::from).collect()) + .map(|results| results.map(TraceResultsWithTransactionHash::from).collect()) .map_err(errors::call) } } diff --git a/rpc/src/v1/impls/web3.rs b/rpc/src/v1/impls/web3.rs index 3dfe2a6653..5ffda51b66 100644 --- a/rpc/src/v1/impls/web3.rs +++ b/rpc/src/v1/impls/web3.rs @@ -15,26 +15,23 @@ // along with Parity Ethereum. If not, see . //! Web3 rpc implementation. +use ethereum_types::H256; use hash::keccak; use jsonrpc_core::Result; use version::version; use v1::traits::Web3; -use v1::types::{H256, Bytes}; +use v1::types::Bytes; /// Web3 rpc implementation. +#[derive(Default)] pub struct Web3Client; -impl Web3Client { - /// Creates new Web3Client. - pub fn new() -> Self { Web3Client } -} - impl Web3 for Web3Client { fn client_version(&self) -> Result { Ok(version().to_owned().replacen("/", "//", 1)) } fn sha3(&self, data: Bytes) -> Result { - Ok(keccak(&data.0).into()) + Ok(keccak(&data.0)) } } diff --git a/rpc/src/v1/informant.rs b/rpc/src/v1/informant.rs index 9455fa9ebb..945378390b 100644 --- a/rpc/src/v1/informant.rs +++ b/rpc/src/v1/informant.rs @@ -135,7 +135,7 @@ impl StatsCalculator { #[derive(Default, Debug)] pub struct RpcStats { requests: RwLock, - roundtrips: RwLock>, + roundtrips: RwLock>, active_sessions: AtomicUsize, } @@ -157,7 +157,7 @@ impl RpcStats { } /// Add roundtrip time (microseconds) - pub fn add_roundtrip(&self, microseconds: u32) { + pub fn add_roundtrip(&self, microseconds: u128) { self.roundtrips.write().add(microseconds) } @@ -172,7 +172,7 @@ impl RpcStats { } /// Returns approximated roundtrip in microseconds - pub fn approximated_roundtrip(&self) -> u32 { + pub fn approximated_roundtrip(&self) -> u128 { self.roundtrips.read().approximated_median() } } @@ -197,10 +197,6 @@ impl Middleware { notifier, } } - - fn as_micro(dur: time::Duration) -> u32 { - (dur.as_secs() * 1_000_000) as u32 + dur.subsec_nanos() / 1_000 - } } impl core::Middleware for Middleware { @@ -223,7 +219,7 @@ impl core::Middleware for Middleware< let stats = self.stats.clone(); let future = process(request, meta).map(move |res| { - let time = Self::as_micro(start.elapsed()); + let time = start.elapsed().as_micros(); if time > 10_000 { debug!(target: "rpc", "[{:?}] Took {}ms", id, time / 1_000); } diff --git a/rpc/src/v1/mod.rs b/rpc/src/v1/mod.rs index 91915cacc6..8b8afacdb1 100644 --- a/rpc/src/v1/mod.rs +++ b/rpc/src/v1/mod.rs @@ -41,7 +41,7 @@ pub mod informant; pub mod metadata; pub mod traits; -pub use self::traits::{Debug, Eth, EthFilter, EthPubSub, EthSigning, Net, Parity, ParityAccounts, ParitySet, ParitySigning, Personal, PubSub, Private, Rpc, SecretStore, Signer, Traces, Web3}; +pub use self::traits::{Debug, Eth, EthFilter, EthPubSub, EthSigning, Net, Parity, ParityAccountsInfo, ParityAccounts, ParitySet, ParitySetAccounts, ParitySigning, Personal, PubSub, Private, Rpc, SecretStore, Signer, Traces, Web3}; pub use self::impls::*; pub use self::helpers::{NetworkSettings, block_import, dispatch}; pub use self::metadata::Metadata; @@ -50,6 +50,8 @@ pub use self::extractors::{RpcExtractor, WsExtractor, WsStats, WsDispatcher}; /// Signer utilities pub mod signer { - pub use super::helpers::{SigningQueue, SignerService, ConfirmationsQueue}; - pub use super::types::{ConfirmationRequest, TransactionModification, U256, TransactionCondition}; + #[cfg(any(test, feature = "accounts"))] + pub use super::helpers::engine_signer::EngineSigner; + pub use super::helpers::external_signer::{SignerService, ConfirmationsQueue}; + pub use super::types::{ConfirmationRequest, TransactionModification, TransactionCondition}; } diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 538b9cf318..9c2273746f 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -18,7 +18,7 @@ use std::env; use std::sync::Arc; -use ethcore::account_provider::AccountProvider; +use accounts::AccountProvider; use ethcore::client::{BlockChainClient, Client, ClientConfig, ChainInfo, ImportBlock}; use ethcore::ethereum; use ethcore::miner::Miner; @@ -26,7 +26,7 @@ use ethcore::spec::{Genesis, Spec}; use ethcore::test_helpers; use ethcore::verification::VerifierType; use ethcore::verification::queue::kind::blocks::Unverified; -use ethereum_types::{H256, Address}; +use ethereum_types::{Address, H256, U256}; use ethjson::blockchain::BlockChain; use ethjson::spec::ForkSpec; use io::IoChannel; @@ -36,14 +36,12 @@ use parking_lot::Mutex; use types::ids::BlockId; use jsonrpc_core::IoHandler; -use v1::helpers::dispatch::FullDispatcher; +use v1::helpers::dispatch::{self, FullDispatcher}; use v1::helpers::nonce; use v1::impls::{EthClient, EthClientOptions, SigningUnsafeClient}; use v1::metadata::Metadata; use v1::tests::helpers::{TestSnapshotService, TestSyncProvider, Config}; -use v1::traits::eth::Eth; -use v1::traits::eth_signing::EthSigning; -use v1::types::U256 as NU256; +use v1::traits::{Eth, EthSigning}; fn account_provider() -> Arc { Arc::new(AccountProvider::transient_provider()) @@ -56,8 +54,8 @@ fn sync_provider() -> Arc { })) } -fn miner_service(spec: &Spec, accounts: Arc) -> Arc { - Arc::new(Miner::new_for_tests(spec, Some(accounts))) +fn miner_service(spec: &Spec) -> Arc { + Arc::new(Miner::new_for_tests(spec, None)) } fn snapshot_service() -> Arc { @@ -75,11 +73,11 @@ fn make_spec(chain: &BlockChain) -> Spec { } struct EthTester { - _runtime: Runtime, - client: Arc, _miner: Arc, + _runtime: Runtime, _snapshot: Arc, accounts: Arc, + client: Arc, handler: IoHandler, } @@ -115,11 +113,11 @@ impl EthTester { } fn from_spec_conf(spec: Spec, config: ClientConfig) -> Self { - let runtime = Runtime::with_thread_count(1); let account_provider = account_provider(); - let opt_account_provider = account_provider.clone(); - let miner_service = miner_service(&spec, account_provider.clone()); + let ap = account_provider.clone(); + let accounts = Arc::new(move || ap.accounts().unwrap_or_default()) as _; + let miner_service = miner_service(&spec); let snapshot_service = snapshot_service(); let client = Client::new( @@ -136,7 +134,7 @@ impl EthTester { &client, &snapshot_service, &sync_provider, - &opt_account_provider, + &accounts, &miner_service, &external_miner, EthClientOptions { @@ -145,15 +143,17 @@ impl EthTester { send_block_number_in_get_work: true, gas_price_percentile: 50, allow_experimental_rpcs: true, - allow_missing_blocks: false + allow_missing_blocks: false, + no_ancient_blocks: false }, ); let reservations = Arc::new(Mutex::new(nonce::Reservations::new(runtime.executor()))); let dispatcher = FullDispatcher::new(client.clone(), miner_service.clone(), reservations, 50); + let signer = Arc::new(dispatch::Signer::new(account_provider.clone())) as _; let eth_sign = SigningUnsafeClient::new( - &opt_account_provider, + &signer, dispatcher, ); @@ -162,11 +162,11 @@ impl EthTester { handler.extend_with(eth_sign.to_delegate()); EthTester { - _runtime: runtime, _miner: miner_service, + _runtime: runtime, _snapshot: snapshot_service, - client: client, accounts: account_provider, + client: client, handler: handler, } } @@ -326,7 +326,6 @@ const POSITIVE_NONCE_SPEC: &'static [u8] = br#"{ "difficultyBoundDivisor": "0x0800", "blockReward": "0x4563918244F40000", "durationLimit": "0x0d", - "blockReward": "0x4563918244F40000", "homesteadTransition": "0xffffffffffffffff", "daoHardforkTransition": "0xffffffffffffffff", "daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000", @@ -460,7 +459,7 @@ fn verify_transaction_counts(name: String, chain: BlockChain) { "jsonrpc": "2.0", "method": "eth_getBlockTransactionCountByNumber", "params": [ - "#.to_owned() + &::serde_json::to_string(&NU256::from(num)).unwrap() + r#" + "#.to_owned() + &::serde_json::to_string(&U256::from(num)).unwrap() + r#" ], "id": "# + format!("{}", *id).as_ref() + r#" }"#; diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 4392716548..b16651bd9c 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -20,14 +20,12 @@ use std::sync::Arc; use std::collections::{BTreeMap, BTreeSet, HashMap}; use bytes::Bytes; -use ethcore::account_provider::SignError as AccountError; -use ethcore::block::{SealedBlock, IsBlock}; +use ethcore::block::SealedBlock; use ethcore::client::{Nonce, PrepareOpenBlock, StateClient, EngineInfo}; -use ethcore::engines::EthEngine; +use ethcore::engines::{EthEngine, signer::EngineSigner}; use ethcore::error::Error; use ethcore::miner::{self, MinerService, AuthoringParams}; use ethereum_types::{H256, U256, Address}; -use ethkey::Password; use miner::pool::local_transactions::Status as LocalTransactionStatus; use miner::pool::{verifier, VerifiedTransaction, QueueStatus}; use parking_lot::{RwLock, Mutex}; @@ -51,8 +49,10 @@ pub struct TestMinerService { pub pending_receipts: Mutex>, /// Next nonces. pub next_nonces: RwLock>, - /// Password held by Engine. - pub password: RwLock, + /// Minimum gas price + pub min_gas_price: RwLock>, + /// Signer (if any) + pub signer: RwLock>>, authoring_params: RwLock, } @@ -65,12 +65,13 @@ impl Default for TestMinerService { local_transactions: Default::default(), pending_receipts: Default::default(), next_nonces: Default::default(), - password: RwLock::new("".into()), + min_gas_price: RwLock::new(Some(0.into())), authoring_params: RwLock::new(AuthoringParams { author: Address::zero(), gas_range_target: (12345.into(), 54321.into()), extra_data: vec![1, 2, 3, 4], }), + signer: RwLock::new(None), } } } @@ -122,12 +123,11 @@ impl MinerService for TestMinerService { self.authoring_params.read().clone() } - fn set_author(&self, author: Address, password: Option) -> Result<(), AccountError> { - self.authoring_params.write().author = author; - if let Some(password) = password { - *self.password.write() = password; + fn set_author(&self, author: miner::Author) { + self.authoring_params.write().author = author.address(); + if let miner::Author::Sealer(signer) = author { + *self.signer.write() = Some(signer); } - Ok(()) } fn set_extra_data(&self, extra_data: Bytes) { @@ -193,7 +193,7 @@ impl MinerService for TestMinerService { let params = self.authoring_params(); let open_block = chain.prepare_open_block(params.author, params.gas_range_target, params.extra_data).unwrap(); let closed = open_block.close().unwrap(); - let header = closed.header(); + let header = &closed.header; Some((header.hash(), header.number(), header.timestamp(), *header.difficulty())) } @@ -282,4 +282,18 @@ impl MinerService for TestMinerService { fn sensible_gas_limit(&self) -> U256 { 0x5208.into() } + + fn set_minimal_gas_price(&self, gas_price: U256) -> Result { + let mut new_price = self.min_gas_price.write(); + match *new_price { + Some(ref mut v) => { + *v = gas_price; + Ok(true) + }, + None => { + let error_msg = "Can't update fixed gas price while automatic gas calibration is enabled."; + Err(error_msg) + }, + } + } } diff --git a/rpc/src/v1/tests/helpers/snapshot_service.rs b/rpc/src/v1/tests/helpers/snapshot_service.rs index 5450886bb4..881c434e17 100644 --- a/rpc/src/v1/tests/helpers/snapshot_service.rs +++ b/rpc/src/v1/tests/helpers/snapshot_service.rs @@ -48,6 +48,7 @@ impl SnapshotService for TestSnapshotService { fn status(&self) -> RestorationStatus { self.status.lock().clone() } fn begin_restore(&self, _manifest: ManifestData) { } fn abort_restore(&self) { } + fn abort_snapshot(&self) {} fn restore_state_chunk(&self, _hash: H256, _chunk: Bytes) { } fn restore_block_chunk(&self, _hash: H256, _chunk: Bytes) { } fn shutdown(&self) { } diff --git a/rpc/src/v1/tests/helpers/sync_provider.rs b/rpc/src/v1/tests/helpers/sync_provider.rs index 0ef87cd8fb..37c2f93553 100644 --- a/rpc/src/v1/tests/helpers/sync_provider.rs +++ b/rpc/src/v1/tests/helpers/sync_provider.rs @@ -20,6 +20,7 @@ use std::collections::BTreeMap; use ethereum_types::H256; use parking_lot::RwLock; use sync::{SyncProvider, EthProtocolInfo, SyncStatus, SyncState, PeerInfo, TransactionStats}; +use network::client_version::ClientVersion; /// TestSyncProvider config. pub struct Config { @@ -75,7 +76,7 @@ impl SyncProvider for TestSyncProvider { vec![ PeerInfo { id: Some("node1".to_owned()), - client_version: "Parity-Ethereum/1".to_owned(), + client_version: ClientVersion::from("Parity-Ethereum/1/v2.4.0/linux/rustc"), capabilities: vec!["eth/62".to_owned(), "eth/63".to_owned()], remote_address: "127.0.0.1:7777".to_owned(), local_address: "127.0.0.1:8888".to_owned(), @@ -88,7 +89,7 @@ impl SyncProvider for TestSyncProvider { }, PeerInfo { id: None, - client_version: "Parity-Ethereum/2".to_owned(), + client_version: ClientVersion::from("Parity-Ethereum/2/v2.4.0/linux/rustc"), capabilities: vec!["eth/63".to_owned(), "eth/64".to_owned()], remote_address: "Handshake".to_owned(), local_address: "127.0.0.1:3333".to_owned(), diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index f920996d1a..75e05ce467 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -19,11 +19,10 @@ use std::collections::HashMap; use std::sync::Arc; use std::time::{Instant, Duration, SystemTime, UNIX_EPOCH}; -use ethcore::account_provider::AccountProvider; +use accounts::AccountProvider; use ethcore::client::{BlockChainClient, BlockId, EachBlockWith, Executed, TestBlockChainClient, TransactionId}; -use ethcore::miner::MinerService; +use ethcore::miner::{self, MinerService}; use ethereum_types::{H160, H256, U256, Address}; -use ethkey::Secret; use miner::external::ExternalMiner; use parity_runtime::Runtime; use parking_lot::Mutex; @@ -35,9 +34,7 @@ use types::log_entry::{LocalizedLogEntry, LogEntry}; use types::receipt::{LocalizedReceipt, TransactionOutcome}; use jsonrpc_core::IoHandler; -use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient, EthSigning, SigningUnsafeClient}; -use v1::helpers::nonce; -use v1::helpers::dispatch::FullDispatcher; +use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient}; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestSnapshotService}; use v1::metadata::Metadata; @@ -88,21 +85,17 @@ impl EthTester { let client = blockchain_client(); let sync = sync_provider(); let ap = accounts_provider(); - let opt_ap = ap.clone(); + let ap2 = ap.clone(); + let opt_ap = Arc::new(move || ap2.accounts().unwrap_or_default()) as _; let miner = miner_service(); let snapshot = snapshot_service(); let hashrates = Arc::new(Mutex::new(HashMap::new())); let external_miner = Arc::new(ExternalMiner::new(hashrates.clone())); - let gas_price_percentile = options.gas_price_percentile; let eth = EthClient::new(&client, &snapshot, &sync, &opt_ap, &miner, &external_miner, options).to_delegate(); let filter = EthFilterClient::new(client.clone(), miner.clone(), 60).to_delegate(); - let reservations = Arc::new(Mutex::new(nonce::Reservations::new(runtime.executor()))); - let dispatcher = FullDispatcher::new(client.clone(), miner.clone(), reservations, gas_price_percentile); - let sign = SigningUnsafeClient::new(&opt_ap, dispatcher).to_delegate(); let mut io: IoHandler = IoHandler::default(); io.extend_with(eth); - io.extend_with(sign); io.extend_with(filter); EthTester { @@ -360,28 +353,6 @@ fn rpc_eth_submit_hashrate() { U256::from(0x500_000)); } -#[test] -fn rpc_eth_sign() { - let tester = EthTester::default(); - - let account = tester.accounts_provider.insert_account(Secret::from([69u8; 32]), &"abcd".into()).unwrap(); - tester.accounts_provider.unlock_account_permanently(account, "abcd".into()).unwrap(); - let _message = "0cc175b9c0f1b6a831c399e26977266192eb5ffee6ae2fec3ad71c777531578f".from_hex().unwrap(); - - let req = r#"{ - "jsonrpc": "2.0", - "method": "eth_sign", - "params": [ - ""#.to_owned() + &format!("0x{:x}", account) + r#"", - "0x0cc175b9c0f1b6a831c399e26977266192eb5ffee6ae2fec3ad71c777531578f" - ], - "id": 1 - }"#; - let res = r#"{"jsonrpc":"2.0","result":"0xa2870db1d0c26ef93c7b72d2a0830fa6b841e0593f7186bc6c7cc317af8cf3a42fda03bd589a49949aa05db83300cdb553116274518dbe9d90c65d0213f4af491b","id":1}"#; - - assert_eq!(tester.io.handle_request_sync(&req), Some(res.into())); -} - #[test] fn rpc_eth_author() { let make_res = |addr| r#"{"jsonrpc":"2.0","result":""#.to_owned() + &format!("0x{:x}", addr) + r#"","id":1}"#; @@ -405,7 +376,7 @@ fn rpc_eth_author() { for i in 0..20 { let addr = tester.accounts_provider.new_account(&format!("{}", i).into()).unwrap(); - tester.miner.set_author(addr.clone(), None).unwrap(); + tester.miner.set_author(miner::Author::External(addr)); assert_eq!(tester.io.handle_request_sync(request), Some(make_res(addr))); } @@ -414,7 +385,7 @@ fn rpc_eth_author() { #[test] fn rpc_eth_mining() { let tester = EthTester::default(); - tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(), None).unwrap(); + tester.miner.set_author(miner::Author::External(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap())); let request = r#"{"jsonrpc": "2.0", "method": "eth_mining", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":false,"id":1}"#; @@ -824,157 +795,6 @@ fn rpc_eth_estimate_gas_default_block() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } -#[test] -fn rpc_eth_send_transaction() { - let tester = EthTester::default(); - let address = tester.accounts_provider.new_account(&"".into()).unwrap(); - tester.accounts_provider.unlock_account_permanently(address, "".into()).unwrap(); - let request = r#"{ - "jsonrpc": "2.0", - "method": "eth_sendTransaction", - "params": [{ - "from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"", - "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", - "gas": "0x76c0", - "gasPrice": "0x9184e72a000", - "value": "0x9184e72a" - }], - "id": 1 - }"#; - - let t = Transaction { - nonce: U256::zero(), - gas_price: U256::from(0x9184e72a000u64), - gas: U256::from(0x76c0), - action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), - value: U256::from(0x9184e72au64), - data: vec![] - }; - let signature = tester.accounts_provider.sign(address, None, t.hash(None)).unwrap(); - let t = t.with_signature(signature, None); - - let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:x}", t.hash()).as_ref() + r#"","id":1}"#; - - assert_eq!(tester.io.handle_request_sync(&request), Some(response)); - - tester.miner.increment_nonce(&address); - - let t = Transaction { - nonce: U256::one(), - gas_price: U256::from(0x9184e72a000u64), - gas: U256::from(0x76c0), - action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), - value: U256::from(0x9184e72au64), - data: vec![] - }; - let signature = tester.accounts_provider.sign(address, None, t.hash(None)).unwrap(); - let t = t.with_signature(signature, None); - - let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:x}", t.hash()).as_ref() + r#"","id":1}"#; - - assert_eq!(tester.io.handle_request_sync(&request), Some(response)); -} - -#[test] -fn rpc_eth_sign_transaction() { - let tester = EthTester::default(); - let address = tester.accounts_provider.new_account(&"".into()).unwrap(); - tester.accounts_provider.unlock_account_permanently(address, "".into()).unwrap(); - let request = r#"{ - "jsonrpc": "2.0", - "method": "eth_signTransaction", - "params": [{ - "from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"", - "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", - "gas": "0x76c0", - "gasPrice": "0x9184e72a000", - "value": "0x9184e72a" - }], - "id": 1 - }"#; - - let t = Transaction { - nonce: U256::one(), - gas_price: U256::from(0x9184e72a000u64), - gas: U256::from(0x76c0), - action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), - value: U256::from(0x9184e72au64), - data: vec![] - }; - let signature = tester.accounts_provider.sign(address, None, t.hash(None)).unwrap(); - let t = t.with_signature(signature, None); - let signature = t.signature(); - let rlp = rlp::encode(&t); - - let response = r#"{"jsonrpc":"2.0","result":{"#.to_owned() + - r#""raw":"0x"# + &rlp.to_hex() + r#"","# + - r#""tx":{"# + - r#""blockHash":null,"blockNumber":null,"# + - &format!("\"chainId\":{},", t.chain_id().map_or("null".to_owned(), |n| format!("{}", n))) + - r#""condition":null,"creates":null,"# + - &format!("\"from\":\"0x{:x}\",", &address) + - r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# + - &format!("\"hash\":\"0x{:x}\",", t.hash()) + - r#""input":"0x","# + - r#""nonce":"0x1","# + - &format!("\"publicKey\":\"0x{:x}\",", t.recover_public().unwrap()) + - &format!("\"r\":\"0x{:x}\",", U256::from(signature.r())) + - &format!("\"raw\":\"0x{}\",", rlp.to_hex()) + - &format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) + - &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) + - r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# + - &format!("\"v\":\"0x{:x}\",", U256::from(t.original_v())) + - r#""value":"0x9184e72a""# + - r#"}},"id":1}"#; - - tester.miner.increment_nonce(&address); - - assert_eq!(tester.io.handle_request_sync(&request), Some(response)); -} - -#[test] -fn rpc_eth_send_transaction_with_bad_to() { - let tester = EthTester::default(); - let address = tester.accounts_provider.new_account(&"".into()).unwrap(); - let request = r#"{ - "jsonrpc": "2.0", - "method": "eth_sendTransaction", - "params": [{ - "from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"", - "to": "", - "gas": "0x76c0", - "gasPrice": "0x9184e72a000", - "value": "0x9184e72a" - }], - "id": 1 - }"#; - - let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params: expected a hex-encoded hash with 0x prefix."},"id":1}"#; - - assert_eq!(tester.io.handle_request_sync(&request), Some(response.into())); -} - -#[test] -fn rpc_eth_send_transaction_error() { - let tester = EthTester::default(); - let address = tester.accounts_provider.new_account(&"".into()).unwrap(); - let request = r#"{ - "jsonrpc": "2.0", - "method": "eth_sendTransaction", - "params": [{ - "from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"", - "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", - "gas": "0x76c0", - "gasPrice": "0x9184e72a000", - "value": "0x9184e72a" - }], - "id": 1 - }"#; - - let response = r#"{"jsonrpc":"2.0","error":{"code":-32020,"message":"Your account is locked. Unlock the account via CLI, personal_unlockAccount or use Trusted Signer.","data":"NotUnlocked"},"id":1}"#; - assert_eq!(tester.io.handle_request_sync(&request), Some(response.into())); -} - #[test] fn rpc_eth_send_raw_transaction_error() { let tester = EthTester::default(); @@ -1141,7 +961,7 @@ fn rpc_get_work_returns_no_work_if_cant_mine() { #[test] fn rpc_get_work_returns_correct_work_package() { let eth_tester = EthTester::default(); - eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(), None).unwrap(); + eth_tester.miner.set_author(miner::Author::External(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap())); let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":["0x76c7bd86693aee93d1a80a408a09a0585b1a1292afcb56192f171d925ea18e2d","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000800000000000000000000000000000000000000000000000000000000000","0x1"],"id":1}"#; @@ -1154,7 +974,7 @@ fn rpc_get_work_should_not_return_block_number() { let eth_tester = EthTester::new_with_options(EthClientOptions::with(|options| { options.send_block_number_in_get_work = false; })); - eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(), None).unwrap(); + eth_tester.miner.set_author(miner::Author::External(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap())); let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":["0x76c7bd86693aee93d1a80a408a09a0585b1a1292afcb56192f171d925ea18e2d","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000800000000000000000000000000000000000000000000000000000000000"],"id":1}"#; @@ -1165,7 +985,7 @@ fn rpc_get_work_should_not_return_block_number() { #[test] fn rpc_get_work_should_timeout() { let eth_tester = EthTester::default(); - eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(), None).unwrap(); + eth_tester.miner.set_author(miner::Author::External(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap())); let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() - 1000; // Set latest block to 1000 seconds ago eth_tester.client.set_latest_block_timestamp(timestamp); let hash = eth_tester.miner.work_package(&*eth_tester.client).unwrap().0; diff --git a/rpc/src/v1/tests/mocked/manage_network.rs b/rpc/src/v1/tests/mocked/manage_network.rs index 560ed89ff2..d327a8743c 100644 --- a/rpc/src/v1/tests/mocked/manage_network.rs +++ b/rpc/src/v1/tests/mocked/manage_network.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use std::ops::Range; +use std::ops::RangeInclusive; use sync::ManageNetwork; use self::ethcore_network::{ProtocolId, NetworkContext}; @@ -30,6 +30,6 @@ impl ManageNetwork for TestManageNetwork { fn add_reserved_peer(&self, _peer: String) -> Result<(), String> { Ok(()) } fn start_network(&self) {} fn stop_network(&self) {} - fn num_peers_range(&self) -> Range { 25 .. 51 } + fn num_peers_range(&self) -> RangeInclusive { 25..=50 } fn with_proto_context(&self, _: ProtocolId, _: &mut FnMut(&NetworkContext)) { } } diff --git a/rpc/src/v1/tests/mocked/mod.rs b/rpc/src/v1/tests/mocked/mod.rs index 80766ca437..35d109b171 100644 --- a/rpc/src/v1/tests/mocked/mod.rs +++ b/rpc/src/v1/tests/mocked/mod.rs @@ -23,13 +23,19 @@ mod eth_pubsub; mod manage_network; mod net; mod parity; +#[cfg(any(test, feature = "accounts"))] mod parity_accounts; mod parity_set; +#[cfg(any(test, feature = "accounts"))] mod personal; mod pubsub; mod rpc; +#[cfg(any(test, feature = "accounts"))] mod secretstore; mod signer; +#[cfg(any(test, feature = "accounts"))] mod signing; +#[cfg(any(test, feature = "accounts"))] +mod signing_unsafe; mod traces; mod web3; diff --git a/rpc/src/v1/tests/mocked/parity.rs b/rpc/src/v1/tests/mocked/parity.rs index f83ded550d..6608589f55 100644 --- a/rpc/src/v1/tests/mocked/parity.rs +++ b/rpc/src/v1/tests/mocked/parity.rs @@ -15,7 +15,6 @@ // along with Parity Ethereum. If not, see . use std::sync::Arc; -use ethcore::account_provider::AccountProvider; use ethcore::client::{TestBlockChainClient, Executed, TransactionId}; use ethcore_logger::RotatingLogger; use ethereum_types::{Address, U256, H256}; @@ -27,7 +26,8 @@ use types::receipt::{LocalizedReceipt, TransactionOutcome}; use jsonrpc_core::IoHandler; use v1::{Parity, ParityClient}; use v1::metadata::Metadata; -use v1::helpers::{SignerService, NetworkSettings}; +use v1::helpers::NetworkSettings; +use v1::helpers::external_signer::SignerService; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestUpdater}; use super::manage_network::TestManageNetwork; use Host; @@ -42,7 +42,6 @@ pub struct Dependencies { pub logger: Arc, pub settings: Arc, pub network: Arc, - pub accounts: Arc, pub ws_address: Option, } @@ -67,7 +66,6 @@ impl Dependencies { rpc_port: 8545, }), network: Arc::new(TestManageNetwork), - accounts: Arc::new(AccountProvider::transient_provider()), ws_address: Some("127.0.0.1:18546".into()), } } @@ -79,7 +77,6 @@ impl Dependencies { self.sync.clone(), self.updater.clone(), self.network.clone(), - self.accounts.clone(), self.logger.clone(), self.settings.clone(), signer, @@ -101,47 +98,6 @@ impl Dependencies { } } -#[test] -fn rpc_parity_accounts_info() { - let deps = Dependencies::new(); - let io = deps.default_client(); - - deps.accounts.new_account(&"".into()).unwrap(); - let accounts = deps.accounts.accounts().unwrap(); - assert_eq!(accounts.len(), 1); - let address = accounts[0]; - - deps.accounts.set_address_name(1.into(), "XX".into()); - deps.accounts.set_account_name(address.clone(), "Test".into()).unwrap(); - deps.accounts.set_account_meta(address.clone(), "{foo: 69}".into()).unwrap(); - - let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#; - let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{:x}\":{{\"name\":\"Test\"}}}},\"id\":1}}", address); - assert_eq!(io.handle_request_sync(request), Some(response)); -} - -#[test] -fn rpc_parity_default_account() { - let deps = Dependencies::new(); - let io = deps.default_client(); - - // Check empty - let address = Address::default(); - let request = r#"{"jsonrpc": "2.0", "method": "parity_defaultAccount", "params": [], "id": 1}"#; - let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":\"0x{:x}\",\"id\":1}}", address); - assert_eq!(io.handle_request_sync(request), Some(response)); - - // With account - deps.accounts.new_account(&"".into()).unwrap(); - let accounts = deps.accounts.accounts().unwrap(); - assert_eq!(accounts.len(), 1); - let address = accounts[0]; - - let request = r#"{"jsonrpc": "2.0", "method": "parity_defaultAccount", "params": [], "id": 1}"#; - let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":\"0x{:x}\",\"id\":1}}", address); - assert_eq!(io.handle_request_sync(request), Some(response)); -} - #[test] fn rpc_parity_consensus_capability() { let deps = Dependencies::new(); @@ -295,7 +251,7 @@ fn rpc_parity_net_peers() { let io = deps.default_client(); let request = r#"{"jsonrpc": "2.0", "method": "parity_netPeers", "params":[], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":{"active":0,"connected":120,"max":50,"peers":[{"caps":["eth/62","eth/63"],"id":"node1","name":"Parity-Ethereum/1","network":{"localAddress":"127.0.0.1:8888","remoteAddress":"127.0.0.1:7777"},"protocols":{"eth":{"difficulty":"0x28","head":"0000000000000000000000000000000000000000000000000000000000000032","version":62},"pip":null}},{"caps":["eth/63","eth/64"],"id":null,"name":"Parity-Ethereum/2","network":{"localAddress":"127.0.0.1:3333","remoteAddress":"Handshake"},"protocols":{"eth":{"difficulty":null,"head":"000000000000000000000000000000000000000000000000000000000000003c","version":64},"pip":null}}]},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"active":0,"connected":120,"max":50,"peers":[{"caps":["eth/62","eth/63"],"id":"node1","name":{"ParityClient":{"can_handle_large_requests":true,"compiler":"rustc","identity":"1","name":"Parity-Ethereum","os":"linux","semver":"2.4.0"}},"network":{"localAddress":"127.0.0.1:8888","remoteAddress":"127.0.0.1:7777"},"protocols":{"eth":{"difficulty":"0x28","head":"0000000000000000000000000000000000000000000000000000000000000032","version":62},"pip":null}},{"caps":["eth/63","eth/64"],"id":null,"name":{"ParityClient":{"can_handle_large_requests":true,"compiler":"rustc","identity":"2","name":"Parity-Ethereum","os":"linux","semver":"2.4.0"}},"network":{"localAddress":"127.0.0.1:3333","remoteAddress":"Handshake"},"protocols":{"eth":{"difficulty":null,"head":"000000000000000000000000000000000000000000000000000000000000003c","version":64},"pip":null}}]},"id":1}"#; assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } diff --git a/rpc/src/v1/tests/mocked/parity_accounts.rs b/rpc/src/v1/tests/mocked/parity_accounts.rs index 794d7f9cad..5b2e0762b1 100644 --- a/rpc/src/v1/tests/mocked/parity_accounts.rs +++ b/rpc/src/v1/tests/mocked/parity_accounts.rs @@ -16,13 +16,14 @@ use std::sync::Arc; -use ethcore::account_provider::{AccountProvider, AccountProviderSettings}; +use accounts::{AccountProvider, AccountProviderSettings}; +use ethereum_types::Address; use ethstore::EthStore; use ethstore::accounts_dir::RootDiskDirectory; use tempdir::TempDir; use jsonrpc_core::IoHandler; -use v1::{ParityAccounts, ParityAccountsClient}; +use v1::{ParityAccounts, ParityAccountsInfo, ParityAccountsClient}; struct ParityAccountsTester { accounts: Arc, @@ -42,8 +43,10 @@ fn accounts_provider_with_vaults_support(temp_path: &str) -> Arc) -> ParityAccountsTester { let opt_ap = accounts_provider.clone(); let parity_accounts = ParityAccountsClient::new(&opt_ap); + let parity_accounts2 = ParityAccountsClient::new(&opt_ap); let mut io = IoHandler::default(); - io.extend_with(parity_accounts.to_delegate()); + io.extend_with(ParityAccounts::to_delegate(parity_accounts)); + io.extend_with(ParityAccountsInfo::to_delegate(parity_accounts2)); let tester = ParityAccountsTester { accounts: accounts_provider, @@ -61,6 +64,47 @@ fn setup_with_vaults_support(temp_path: &str) -> ParityAccountsTester { setup_with_accounts_provider(accounts_provider_with_vaults_support(temp_path)) } +#[test] +fn rpc_parity_accounts_info() { + let tester = setup(); + let io = tester.io; + + tester.accounts.new_account(&"".into()).unwrap(); + let accounts = tester.accounts.accounts().unwrap(); + assert_eq!(accounts.len(), 1); + let address = accounts[0]; + + tester.accounts.set_address_name(1.into(), "XX".into()); + tester.accounts.set_account_name(address.clone(), "Test".into()).unwrap(); + tester.accounts.set_account_meta(address.clone(), "{foo: 69}".into()).unwrap(); + + let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#; + let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{:x}\":{{\"name\":\"Test\"}}}},\"id\":1}}", address); + assert_eq!(io.handle_request_sync(request), Some(response)); +} + +#[test] +fn rpc_parity_default_account() { + let tester = setup(); + let io = tester.io; + + // Check empty + let address = Address::default(); + let request = r#"{"jsonrpc": "2.0", "method": "parity_defaultAccount", "params": [], "id": 1}"#; + let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":\"0x{:x}\",\"id\":1}}", address); + assert_eq!(io.handle_request_sync(request), Some(response)); + + // With account + tester.accounts.new_account(&"".into()).unwrap(); + let accounts = tester.accounts.accounts().unwrap(); + assert_eq!(accounts.len(), 1); + let address = accounts[0]; + + let request = r#"{"jsonrpc": "2.0", "method": "parity_defaultAccount", "params": [], "id": 1}"#; + let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":\"0x{:x}\",\"id\":1}}", address); + assert_eq!(io.handle_request_sync(request), Some(response)); +} + #[test] fn should_be_able_to_get_account_info() { let tester = setup(); diff --git a/rpc/src/v1/tests/mocked/parity_set.rs b/rpc/src/v1/tests/mocked/parity_set.rs index 91a4c6c95a..25c13fb1cb 100644 --- a/rpc/src/v1/tests/mocked/parity_set.rs +++ b/rpc/src/v1/tests/mocked/parity_set.rs @@ -54,7 +54,13 @@ fn parity_set_client( updater: &Arc, net: &Arc, ) -> TestParitySetClient { - ParitySetClient::new(client, miner, updater, &(net.clone() as Arc), FakeFetch::new(Some(1))) + ParitySetClient::new( + client, + miner, + updater, + &(net.clone() as Arc), + FakeFetch::new(Some(1)), + ) } #[test] @@ -106,14 +112,16 @@ fn rpc_parity_set_min_gas_price() { io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":false,"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] -fn rpc_parity_set_gas_floor_target() { +fn rpc_parity_set_min_gas_price_with_automated_calibration_enabled() { let miner = miner_service(); + *miner.min_gas_price.write() = None; + let client = client_service(); let network = network_service(); let updater = updater_service(); @@ -121,15 +129,14 @@ fn rpc_parity_set_gas_floor_target() { let mut io = IoHandler::new(); io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); - let request = r#"{"jsonrpc": "2.0", "method": "parity_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; + let request = r#"{"jsonrpc": "2.0", "method": "parity_setMinGasPrice", "params":["0xdeadbeef"], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Can't update fixed gas price while automatic gas calibration is enabled."},"id":1}"#; assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); - assert_eq!(miner.authoring_params().gas_range_target.0, U256::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); } #[test] -fn rpc_parity_set_extra_data() { +fn rpc_parity_set_gas_floor_target() { let miner = miner_service(); let client = client_service(); let network = network_service(); @@ -138,31 +145,32 @@ fn rpc_parity_set_extra_data() { let mut io = IoHandler::new(); io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); - let request = r#"{"jsonrpc": "2.0", "method": "parity_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; + let request = r#"{"jsonrpc": "2.0", "method": "parity_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); - assert_eq!(miner.authoring_params().extra_data, "cd1722f3947def4cf144679da39c4c32bdc35681".from_hex().unwrap()); + assert_eq!(miner.authoring_params().gas_range_target.0, U256::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); } #[test] -fn rpc_parity_set_author() { +fn rpc_parity_set_extra_data() { let miner = miner_service(); let client = client_service(); let network = network_service(); let updater = updater_service(); + let mut io = IoHandler::new(); io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); - let request = r#"{"jsonrpc": "2.0", "method": "parity_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; + let request = r#"{"jsonrpc": "2.0", "method": "parity_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); - assert_eq!(miner.authoring_params().author, Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); + assert_eq!(miner.authoring_params().extra_data, "cd1722f3947def4cf144679da39c4c32bdc35681".from_hex().unwrap()); } #[test] -fn rpc_parity_set_engine_signer() { +fn rpc_parity_set_author() { let miner = miner_service(); let client = client_service(); let network = network_service(); @@ -170,12 +178,11 @@ fn rpc_parity_set_engine_signer() { let mut io = IoHandler::new(); io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); - let request = r#"{"jsonrpc": "2.0", "method": "parity_setEngineSigner", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681", "password"], "id": 1}"#; + let request = r#"{"jsonrpc": "2.0", "method": "parity_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(miner.authoring_params().author, Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); - assert_eq!(*miner.password.read(), "password".into()); } #[test] @@ -236,3 +243,29 @@ fn rpc_parity_remove_transaction() { miner.pending_transactions.lock().insert(hash, signed); assert_eq!(io.handle_request_sync(&request), Some(response.to_owned())); } + +#[test] +fn rpc_parity_set_engine_signer() { + use accounts::AccountProvider; + use bytes::ToPretty; + use v1::impls::ParitySetAccountsClient; + use v1::traits::ParitySetAccounts; + + let account_provider = Arc::new(AccountProvider::transient_provider()); + account_provider.insert_account(::hash::keccak("cow").into(), &"password".into()).unwrap(); + + let miner = miner_service(); + let mut io = IoHandler::new(); + io.extend_with( + ParitySetAccountsClient::new(&account_provider, &miner).to_delegate() + ); + + let request = r#"{"jsonrpc": "2.0", "method": "parity_setEngineSigner", "params":["0xcd2a3d9f938e13cd947ec05abc7fe734df8dd826", "password"], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; + + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); + assert_eq!(miner.authoring_params().author, Address::from_str("cd2a3d9f938e13cd947ec05abc7fe734df8dd826").unwrap()); + let signature = miner.signer.read().as_ref().unwrap().sign(::hash::keccak("x")).unwrap().to_vec(); + assert_eq!(&format!("{}", signature.pretty()), "6f46069ded2154af6e806706e4f7f6fd310ac45f3c6dccb85f11c0059ee20a09245df0a0008bb84a10882b1298284bc93058e7bc5938ea728e77620061687a6401"); +} + diff --git a/rpc/src/v1/tests/mocked/personal.rs b/rpc/src/v1/tests/mocked/personal.rs index b74553bc7f..a2d6b87ce2 100644 --- a/rpc/src/v1/tests/mocked/personal.rs +++ b/rpc/src/v1/tests/mocked/personal.rs @@ -18,8 +18,8 @@ use std::sync::Arc; use std::str::FromStr; use bytes::ToPretty; -use ethereum_types::{U256, Address}; -use ethcore::account_provider::AccountProvider; +use accounts::AccountProvider; +use ethereum_types::{Address, H520, U256}; use ethcore::client::TestBlockChainClient; use jsonrpc_core::IoHandler; use parking_lot::Mutex; @@ -31,7 +31,7 @@ use v1::{PersonalClient, Personal, Metadata}; use v1::helpers::{nonce, eip191}; use v1::helpers::dispatch::{eth_data_hash, FullDispatcher}; use v1::tests::helpers::TestMinerService; -use v1::types::{EIP191Version, PresignedTransaction, H520}; +use v1::types::{EIP191Version, PresignedTransaction}; use rustc_hex::ToHex; use serde_json::to_value; use ethkey::Secret; @@ -156,7 +156,7 @@ fn sign() { let hash = eth_data_hash(data); let signature = H520(tester.accounts.sign(address, Some("password123".into()), hash).unwrap().into_electrum()); - let signature = format!("0x{:?}", signature); + let signature = format!("{:?}", signature); let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + &signature + r#"","id":1}"#; @@ -264,7 +264,7 @@ fn ec_recover() { let hash = eth_data_hash(data.clone()); let signature = H520(tester.accounts.sign(address, Some("password123".into()), hash).unwrap().into_electrum()); - let signature = format!("0x{:?}", signature); + let signature = format!("{:?}", signature); let request = r#"{ "jsonrpc": "2.0", @@ -303,7 +303,7 @@ fn ec_recover_invalid_signature() { } #[test] -fn should_unlock_not_account_temporarily_if_allow_perm_is_disabled() { +fn should_not_unlock_account_temporarily_if_allow_perm_is_disabled() { let tester = setup(); let address = tester.accounts.new_account(&"password123".into()).unwrap(); @@ -317,7 +317,7 @@ fn should_unlock_not_account_temporarily_if_allow_perm_is_disabled() { ], "id": 1 }"#; - let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Time-unlocking is only supported in --geth compatibility mode.","data":"Restart your client with --geth flag or use personal_sendTransaction instead."},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Time-unlocking is not supported when permanent unlock is disabled.","data":"Use personal_sendTransaction or enable permanent unlocking, instead."},"id":1}"#; assert_eq!(tester.io.handle_request_sync(&request), Some(response.into())); assert!(tester.accounts.sign(address, None, Default::default()).is_err(), "Should not unlock account."); diff --git a/rpc/src/v1/tests/mocked/secretstore.rs b/rpc/src/v1/tests/mocked/secretstore.rs index 3e4f284a2f..96e20d0028 100644 --- a/rpc/src/v1/tests/mocked/secretstore.rs +++ b/rpc/src/v1/tests/mocked/secretstore.rs @@ -17,7 +17,8 @@ use std::sync::Arc; use crypto::DEFAULT_MAC; -use ethcore::account_provider::AccountProvider; +use accounts::AccountProvider; +use ethereum_types::H256; use ethkey::{KeyPair, Signature, verify_public}; use serde_json; @@ -26,7 +27,7 @@ use v1::metadata::Metadata; use v1::SecretStoreClient; use v1::traits::secretstore::SecretStore; use v1::helpers::secretstore::ordered_servers_keccak; -use v1::types::{H256, EncryptedDocumentKey}; +use v1::types::EncryptedDocumentKey; struct Dependencies { pub accounts: Arc, diff --git a/rpc/src/v1/tests/mocked/signer.rs b/rpc/src/v1/tests/mocked/signer.rs index 78f2e00098..e22c5b8d24 100644 --- a/rpc/src/v1/tests/mocked/signer.rs +++ b/rpc/src/v1/tests/mocked/signer.rs @@ -16,10 +16,10 @@ use std::sync::Arc; use std::str::FromStr; -use ethereum_types::{U256, Address}; +use ethereum_types::{H520, U256, Address}; use bytes::ToPretty; -use ethcore::account_provider::AccountProvider; +use accounts::AccountProvider; use ethcore::client::TestBlockChainClient; use parity_runtime::Runtime; use parking_lot::Mutex; @@ -31,9 +31,10 @@ use jsonrpc_core::IoHandler; use v1::{SignerClient, Signer, Origin}; use v1::metadata::Metadata; use v1::tests::helpers::TestMinerService; -use v1::types::{Bytes as RpcBytes, H520}; -use v1::helpers::{nonce, SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload}; -use v1::helpers::dispatch::{FullDispatcher, eth_data_hash}; +use v1::types::Bytes as RpcBytes; +use v1::helpers::{nonce, FilledTransactionRequest, ConfirmationPayload}; +use v1::helpers::external_signer::{SigningQueue, SignerService}; +use v1::helpers::dispatch::{self, FullDispatcher, eth_data_hash}; struct SignerTester { _runtime: Runtime, @@ -60,13 +61,14 @@ fn signer_tester() -> SignerTester { let runtime = Runtime::with_thread_count(1); let signer = Arc::new(SignerService::new_test(false)); let accounts = accounts_provider(); + let account_signer = Arc::new(dispatch::Signer::new(accounts.clone())); let client = blockchain_client(); let miner = miner_service(); let reservations = Arc::new(Mutex::new(nonce::Reservations::new(runtime.executor()))); let dispatcher = FullDispatcher::new(client, miner.clone(), reservations, 50); let mut io = IoHandler::default(); - io.extend_with(SignerClient::new(&accounts, dispatcher, &signer, runtime.executor()).to_delegate()); + io.extend_with(SignerClient::new(account_signer, dispatcher, &signer, runtime.executor()).to_delegate()); SignerTester { _runtime: runtime, @@ -493,7 +495,7 @@ fn should_confirm_data_sign_with_signature() { let data_hash = eth_data_hash(vec![1, 2, 3, 4].into()); let signature = H520(tester.accounts.sign(address, Some("test".into()), data_hash).unwrap().into_electrum()); - let signature = format!("0x{:?}", signature); + let signature = format!("{:?}", signature); // when let request = r#"{ @@ -555,29 +557,3 @@ fn should_generate_new_token() { // then assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned())); } - -#[test] -fn should_generate_new_web_proxy_token() { - use jsonrpc_core::{Response, Output, Value}; - // given - let tester = signer_tester(); - - // when - let request = r#"{ - "jsonrpc":"2.0", - "method":"signer_generateWebProxyAccessToken", - "params":["https://parity.io"], - "id":1 - }"#; - let response = tester.io.handle_request_sync(&request).unwrap(); - let result = serde_json::from_str(&response).unwrap(); - - if let Response::Single(Output::Success(ref success)) = result { - if let Value::String(ref token) = success.result { - assert_eq!(tester.signer.web_proxy_access_token_domain(&token), Some("https://parity.io".into())); - return; - } - } - - assert!(false, "Expected successful response, got: {:?}", result); -} diff --git a/rpc/src/v1/tests/mocked/signing.rs b/rpc/src/v1/tests/mocked/signing.rs index a142a40a53..39385d19bd 100644 --- a/rpc/src/v1/tests/mocked/signing.rs +++ b/rpc/src/v1/tests/mocked/signing.rs @@ -25,14 +25,15 @@ use jsonrpc_core::futures::Future; use v1::impls::SigningQueueClient; use v1::metadata::Metadata; use v1::traits::{EthSigning, ParitySigning, Parity}; -use v1::helpers::{nonce, SignerService, SigningQueue, FullDispatcher}; +use v1::helpers::{nonce, dispatch, FullDispatcher}; +use v1::helpers::external_signer::{SignerService, SigningQueue}; use v1::types::{ConfirmationResponse, RichRawTransaction}; use v1::tests::helpers::TestMinerService; use v1::tests::mocked::parity; -use ethereum_types::{U256, Address}; +use accounts::AccountProvider; use bytes::ToPretty; -use ethcore::account_provider::AccountProvider; +use ethereum_types::{U256, Address}; use ethcore::client::TestBlockChainClient; use ethkey::Secret; use ethstore::ethkey::{Generator, Random}; @@ -57,6 +58,7 @@ impl Default for SigningTester { let client = Arc::new(TestBlockChainClient::default()); let miner = Arc::new(TestMinerService::default()); let accounts = Arc::new(AccountProvider::transient_provider()); + let account_signer = Arc::new(dispatch::Signer::new(accounts.clone())) as _; let reservations = Arc::new(Mutex::new(nonce::Reservations::new(runtime.executor()))); let mut io = IoHandler::default(); @@ -64,9 +66,9 @@ impl Default for SigningTester { let executor = Executor::new_thread_per_future(); - let rpc = SigningQueueClient::new(&signer, dispatcher.clone(), executor.clone(), &accounts); + let rpc = SigningQueueClient::new(&signer, dispatcher.clone(), executor.clone(), &account_signer); io.extend_with(EthSigning::to_delegate(rpc)); - let rpc = SigningQueueClient::new(&signer, dispatcher, executor, &accounts); + let rpc = SigningQueueClient::new(&signer, dispatcher, executor, &account_signer); io.extend_with(ParitySigning::to_delegate(rpc)); SigningTester { @@ -84,6 +86,30 @@ fn eth_signing() -> SigningTester { SigningTester::default() } +#[test] +fn rpc_eth_sign() { + use rustc_hex::FromHex; + + let tester = eth_signing(); + + let account = tester.accounts.insert_account(Secret::from([69u8; 32]), &"abcd".into()).unwrap(); + tester.accounts.unlock_account_permanently(account, "abcd".into()).unwrap(); + let _message = "0cc175b9c0f1b6a831c399e26977266192eb5ffee6ae2fec3ad71c777531578f".from_hex().unwrap(); + + let req = r#"{ + "jsonrpc": "2.0", + "method": "eth_sign", + "params": [ + ""#.to_owned() + &format!("0x{:x}", account) + r#"", + "0x0cc175b9c0f1b6a831c399e26977266192eb5ffee6ae2fec3ad71c777531578f" + ], + "id": 1 + }"#; + let res = r#"{"jsonrpc":"2.0","result":"0xa2870db1d0c26ef93c7b72d2a0830fa6b841e0593f7186bc6c7cc317af8cf3a42fda03bd589a49949aa05db83300cdb553116274518dbe9d90c65d0213f4af491b","id":1}"#; + + assert_eq!(tester.io.handle_request_sync(&req), Some(res.into())); +} + #[test] fn should_add_sign_to_queue() { // given diff --git a/rpc/src/v1/tests/mocked/signing_unsafe.rs b/rpc/src/v1/tests/mocked/signing_unsafe.rs new file mode 100644 index 0000000000..a91a85ea1f --- /dev/null +++ b/rpc/src/v1/tests/mocked/signing_unsafe.rs @@ -0,0 +1,237 @@ +// 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::str::FromStr; +use std::sync::Arc; + +use accounts::AccountProvider; +use ethcore::client::TestBlockChainClient; +use ethereum_types::{U256, Address}; +use parity_runtime::Runtime; +use parking_lot::Mutex; +use rlp; +use rustc_hex::ToHex; +use types::transaction::{Transaction, Action}; + +use jsonrpc_core::IoHandler; +use v1::{EthClientOptions, EthSigning, SigningUnsafeClient}; +use v1::helpers::nonce; +use v1::helpers::dispatch::{self, FullDispatcher}; +use v1::tests::helpers::{TestMinerService}; +use v1::metadata::Metadata; + +fn blockchain_client() -> Arc { + let client = TestBlockChainClient::new(); + Arc::new(client) +} + +fn accounts_provider() -> Arc { + Arc::new(AccountProvider::transient_provider()) +} + +fn miner_service() -> Arc { + Arc::new(TestMinerService::default()) +} + +struct EthTester { + pub runtime: Runtime, + pub client: Arc, + pub accounts_provider: Arc, + pub miner: Arc, + pub io: IoHandler, +} + +impl Default for EthTester { + fn default() -> Self { + Self::new_with_options(Default::default()) + } +} + +impl EthTester { + pub fn new_with_options(options: EthClientOptions) -> Self { + let runtime = Runtime::with_thread_count(1); + let client = blockchain_client(); + let accounts_provider = accounts_provider(); + let ap = Arc::new(dispatch::Signer::new(accounts_provider.clone())) as _; + let miner = miner_service(); + let gas_price_percentile = options.gas_price_percentile; + let reservations = Arc::new(Mutex::new(nonce::Reservations::new(runtime.executor()))); + + let dispatcher = FullDispatcher::new(client.clone(), miner.clone(), reservations, gas_price_percentile); + let sign = SigningUnsafeClient::new(&ap, dispatcher).to_delegate(); + let mut io: IoHandler = IoHandler::default(); + io.extend_with(sign); + + EthTester { + runtime, + client, + miner, + io, + accounts_provider, + } + } +} + +#[test] +fn rpc_eth_send_transaction() { + let tester = EthTester::default(); + let address = tester.accounts_provider.new_account(&"".into()).unwrap(); + tester.accounts_provider.unlock_account_permanently(address, "".into()).unwrap(); + let request = r#"{ + "jsonrpc": "2.0", + "method": "eth_sendTransaction", + "params": [{ + "from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"", + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "gas": "0x76c0", + "gasPrice": "0x9184e72a000", + "value": "0x9184e72a" + }], + "id": 1 + }"#; + + let t = Transaction { + nonce: U256::zero(), + gas_price: U256::from(0x9184e72a000u64), + gas: U256::from(0x76c0), + action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), + value: U256::from(0x9184e72au64), + data: vec![] + }; + let signature = tester.accounts_provider.sign(address, None, t.hash(None)).unwrap(); + let t = t.with_signature(signature, None); + + let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:x}", t.hash()).as_ref() + r#"","id":1}"#; + + assert_eq!(tester.io.handle_request_sync(&request), Some(response)); + + tester.miner.increment_nonce(&address); + + let t = Transaction { + nonce: U256::one(), + gas_price: U256::from(0x9184e72a000u64), + gas: U256::from(0x76c0), + action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), + value: U256::from(0x9184e72au64), + data: vec![] + }; + let signature = tester.accounts_provider.sign(address, None, t.hash(None)).unwrap(); + let t = t.with_signature(signature, None); + + let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:x}", t.hash()).as_ref() + r#"","id":1}"#; + + assert_eq!(tester.io.handle_request_sync(&request), Some(response)); +} + +#[test] +fn rpc_eth_sign_transaction() { + let tester = EthTester::default(); + let address = tester.accounts_provider.new_account(&"".into()).unwrap(); + tester.accounts_provider.unlock_account_permanently(address, "".into()).unwrap(); + let request = r#"{ + "jsonrpc": "2.0", + "method": "eth_signTransaction", + "params": [{ + "from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"", + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "gas": "0x76c0", + "gasPrice": "0x9184e72a000", + "value": "0x9184e72a" + }], + "id": 1 + }"#; + + let t = Transaction { + nonce: U256::one(), + gas_price: U256::from(0x9184e72a000u64), + gas: U256::from(0x76c0), + action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), + value: U256::from(0x9184e72au64), + data: vec![] + }; + let signature = tester.accounts_provider.sign(address, None, t.hash(None)).unwrap(); + let t = t.with_signature(signature, None); + let signature = t.signature(); + let rlp = rlp::encode(&t); + + let response = r#"{"jsonrpc":"2.0","result":{"#.to_owned() + + r#""raw":"0x"# + &rlp.to_hex() + r#"","# + + r#""tx":{"# + + r#""blockHash":null,"blockNumber":null,"# + + &format!("\"chainId\":{},", t.chain_id().map_or("null".to_owned(), |n| format!("{}", n))) + + r#""condition":null,"creates":null,"# + + &format!("\"from\":\"0x{:x}\",", &address) + + r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# + + &format!("\"hash\":\"0x{:x}\",", t.hash()) + + r#""input":"0x","# + + r#""nonce":"0x1","# + + &format!("\"publicKey\":\"0x{:x}\",", t.recover_public().unwrap()) + + &format!("\"r\":\"0x{:x}\",", U256::from(signature.r())) + + &format!("\"raw\":\"0x{}\",", rlp.to_hex()) + + &format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) + + &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) + + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# + + &format!("\"v\":\"0x{:x}\",", U256::from(t.original_v())) + + r#""value":"0x9184e72a""# + + r#"}},"id":1}"#; + + tester.miner.increment_nonce(&address); + + assert_eq!(tester.io.handle_request_sync(&request), Some(response)); +} + +#[test] +fn rpc_eth_send_transaction_with_bad_to() { + let tester = EthTester::default(); + let address = tester.accounts_provider.new_account(&"".into()).unwrap(); + let request = r#"{ + "jsonrpc": "2.0", + "method": "eth_sendTransaction", + "params": [{ + "from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"", + "to": "", + "gas": "0x76c0", + "gasPrice": "0x9184e72a000", + "value": "0x9184e72a" + }], + "id": 1 + }"#; + + let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params: prefix is missing."},"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(&request), Some(response.into())); +} + +#[test] +fn rpc_eth_send_transaction_error() { + let tester = EthTester::default(); + let address = tester.accounts_provider.new_account(&"".into()).unwrap(); + let request = r#"{ + "jsonrpc": "2.0", + "method": "eth_sendTransaction", + "params": [{ + "from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"", + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "gas": "0x76c0", + "gasPrice": "0x9184e72a000", + "value": "0x9184e72a" + }], + "id": 1 + }"#; + + let response = r#"{"jsonrpc":"2.0","error":{"code":-32020,"message":"Your account is locked. Unlock the account via CLI, personal_unlockAccount or use Trusted Signer.","data":"NotUnlocked"},"id":1}"#; + assert_eq!(tester.io.handle_request_sync(&request), Some(response.into())); +} diff --git a/rpc/src/v1/tests/mocked/web3.rs b/rpc/src/v1/tests/mocked/web3.rs index 79bcfe01db..5590d5d283 100644 --- a/rpc/src/v1/tests/mocked/web3.rs +++ b/rpc/src/v1/tests/mocked/web3.rs @@ -20,7 +20,7 @@ use v1::{Web3, Web3Client}; #[test] fn rpc_web3_version() { - let web3 = Web3Client::new().to_delegate(); + let web3 = Web3Client::default().to_delegate(); let mut io = IoHandler::new(); io.extend_with(web3); @@ -34,7 +34,7 @@ fn rpc_web3_version() { #[test] fn rpc_web3_sha3() { - let web3 = Web3Client::new().to_delegate(); + let web3 = Web3Client::default().to_delegate(); let mut io = IoHandler::new(); io.extend_with(web3); @@ -46,7 +46,7 @@ fn rpc_web3_sha3() { #[test] fn rpc_web3_sha3_wiki() { - let web3 = Web3Client::new().to_delegate(); + let web3 = Web3Client::default().to_delegate(); let mut io = IoHandler::new(); io.extend_with(web3); diff --git a/rpc/src/v1/traits/debug.rs b/rpc/src/v1/traits/debug.rs index 3b490e6f2a..5d332d434a 100644 --- a/rpc/src/v1/traits/debug.rs +++ b/rpc/src/v1/traits/debug.rs @@ -17,14 +17,14 @@ //! Debug RPC interface. use jsonrpc_core::Result; +use jsonrpc_derive::rpc; use v1::types::RichBlock; -build_rpc_trait! { - /// Debug RPC interface. - pub trait Debug { - /// Returns recently seen bad blocks. - #[rpc(name = "debug_getBadBlocks")] - fn bad_blocks(&self) -> Result>; - } +/// Debug RPC interface. +#[rpc] +pub trait Debug { + /// Returns recently seen bad blocks. + #[rpc(name = "debug_getBadBlocks")] + fn bad_blocks(&self) -> Result>; } diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs index cf5469773b..69a37ae526 100644 --- a/rpc/src/v1/traits/eth.rs +++ b/rpc/src/v1/traits/eth.rs @@ -16,203 +16,202 @@ //! Eth rpc interface. use jsonrpc_core::{Result, BoxFuture}; -use jsonrpc_macros::Trailing; +use jsonrpc_derive::rpc; +use ethereum_types::{H64, H160, H256, U64, U256}; use v1::types::{RichBlock, BlockNumber, Bytes, CallRequest, Filter, FilterChanges, Index, EthAccount}; use v1::types::{Log, Receipt, SyncStatus, Transaction, Work}; -use v1::types::{H64, H160, H256, U256, U64}; -build_rpc_trait! { - /// Eth rpc interface. - pub trait Eth { - type Metadata; +/// Eth rpc interface. +#[rpc] +pub trait Eth { + /// RPC Metadata + type Metadata; - /// Returns protocol version encoded as a string (quotes are necessary). - #[rpc(name = "eth_protocolVersion")] - fn protocol_version(&self) -> Result; + /// Returns protocol version encoded as a string (quotes are necessary). + #[rpc(name = "eth_protocolVersion")] + fn protocol_version(&self) -> Result; - /// Returns an object with data about the sync status or false. (wtf?) - #[rpc(name = "eth_syncing")] - fn syncing(&self) -> Result; + /// Returns an object with data about the sync status or false. (wtf?) + #[rpc(name = "eth_syncing")] + fn syncing(&self) -> Result; - /// Returns the number of hashes per second that the node is mining with. - #[rpc(name = "eth_hashrate")] - fn hashrate(&self) -> Result; + /// Returns the number of hashes per second that the node is mining with. + #[rpc(name = "eth_hashrate")] + fn hashrate(&self) -> Result; - /// Returns block author. - #[rpc(name = "eth_coinbase")] - fn author(&self) -> Result; + /// Returns block author. + #[rpc(name = "eth_coinbase")] + fn author(&self) -> Result; - /// Returns true if client is actively mining new blocks. - #[rpc(name = "eth_mining")] - fn is_mining(&self) -> Result; + /// Returns true if client is actively mining new blocks. + #[rpc(name = "eth_mining")] + fn is_mining(&self) -> Result; - /// Returns the chain ID used for transaction signing at the - /// current best block. None is returned if not - /// available. - #[rpc(name = "eth_chainId")] - fn chain_id(&self) -> Result>; - - /// Returns current gas_price. - #[rpc(name = "eth_gasPrice")] - fn gas_price(&self) -> Result; - - /// Returns accounts list. - #[rpc(name = "eth_accounts")] - fn accounts(&self) -> Result>; - - /// Returns highest block number. - #[rpc(name = "eth_blockNumber")] - fn block_number(&self) -> Result; - - /// Returns balance of the given account. - #[rpc(name = "eth_getBalance")] - fn balance(&self, H160, Trailing) -> BoxFuture; - - /// Returns the account- and storage-values of the specified account including the Merkle-proof - #[rpc(name = "eth_getProof")] - fn proof(&self, H160, Vec, Trailing) -> BoxFuture; - - /// Returns content of the storage at given address. - #[rpc(name = "eth_getStorageAt")] - fn storage_at(&self, H160, U256, Trailing) -> BoxFuture; - - /// Returns block with given hash. - #[rpc(name = "eth_getBlockByHash")] - fn block_by_hash(&self, H256, bool) -> BoxFuture>; - - /// Returns block with given number. - #[rpc(name = "eth_getBlockByNumber")] - fn block_by_number(&self, BlockNumber, bool) -> BoxFuture>; - - /// Returns the number of transactions sent from given address at given time (block number). - #[rpc(name = "eth_getTransactionCount")] - fn transaction_count(&self, H160, Trailing) -> BoxFuture; - - /// Returns the number of transactions in a block with given hash. - #[rpc(name = "eth_getBlockTransactionCountByHash")] - fn block_transaction_count_by_hash(&self, H256) -> BoxFuture>; - - /// Returns the number of transactions in a block with given block number. - #[rpc(name = "eth_getBlockTransactionCountByNumber")] - fn block_transaction_count_by_number(&self, BlockNumber) -> BoxFuture>; - - /// Returns the number of uncles in a block with given hash. - #[rpc(name = "eth_getUncleCountByBlockHash")] - fn block_uncles_count_by_hash(&self, H256) -> BoxFuture>; - - /// Returns the number of uncles in a block with given block number. - #[rpc(name = "eth_getUncleCountByBlockNumber")] - fn block_uncles_count_by_number(&self, BlockNumber) -> BoxFuture>; - - /// Returns the code at given address at given time (block number). - #[rpc(name = "eth_getCode")] - fn code_at(&self, H160, Trailing) -> BoxFuture; - - /// Sends signed transaction, returning its hash. - #[rpc(name = "eth_sendRawTransaction")] - fn send_raw_transaction(&self, Bytes) -> Result; - - /// @alias of `eth_sendRawTransaction`. - #[rpc(name = "eth_submitTransaction")] - fn submit_transaction(&self, Bytes) -> Result; - - /// Call contract, returning the output data. - #[rpc(name = "eth_call")] - fn call(&self, CallRequest, Trailing) -> BoxFuture; - - /// Estimate gas needed for execution of given contract. - #[rpc(name = "eth_estimateGas")] - fn estimate_gas(&self, CallRequest, Trailing) -> BoxFuture; - - /// Get transaction by its hash. - #[rpc(name = "eth_getTransactionByHash")] - fn transaction_by_hash(&self, H256) -> BoxFuture>; - - /// Returns transaction at given block hash and index. - #[rpc(name = "eth_getTransactionByBlockHashAndIndex")] - fn transaction_by_block_hash_and_index(&self, H256, Index) -> BoxFuture>; - - /// Returns transaction by given block number and index. - #[rpc(name = "eth_getTransactionByBlockNumberAndIndex")] - fn transaction_by_block_number_and_index(&self, BlockNumber, Index) -> BoxFuture>; - - /// Returns transaction receipt by transaction hash. - #[rpc(name = "eth_getTransactionReceipt")] - fn transaction_receipt(&self, H256) -> BoxFuture>; - - /// Returns an uncles at given block and index. - #[rpc(name = "eth_getUncleByBlockHashAndIndex")] - fn uncle_by_block_hash_and_index(&self, H256, Index) -> BoxFuture>; - - /// Returns an uncles at given block and index. - #[rpc(name = "eth_getUncleByBlockNumberAndIndex")] - fn uncle_by_block_number_and_index(&self, BlockNumber, Index) -> BoxFuture>; - - /// Returns available compilers. - /// @deprecated - #[rpc(name = "eth_getCompilers")] - fn compilers(&self) -> Result>; - - /// Compiles lll code. - /// @deprecated - #[rpc(name = "eth_compileLLL")] - fn compile_lll(&self, String) -> Result; - - /// Compiles solidity. - /// @deprecated - #[rpc(name = "eth_compileSolidity")] - fn compile_solidity(&self, String) -> Result; - - /// Compiles serpent. - /// @deprecated - #[rpc(name = "eth_compileSerpent")] - fn compile_serpent(&self, String) -> Result; - - /// Returns logs matching given filter object. - #[rpc(name = "eth_getLogs")] - fn logs(&self, Filter) -> BoxFuture>; - - /// Returns the hash of the current block, the seedHash, and the boundary condition to be met. - #[rpc(name = "eth_getWork")] - fn work(&self, Trailing) -> Result; - - /// Used for submitting a proof-of-work solution. - #[rpc(name = "eth_submitWork")] - fn submit_work(&self, H64, H256, H256) -> Result; - - /// Used for submitting mining hashrate. - #[rpc(name = "eth_submitHashrate")] - fn submit_hashrate(&self, U256, H256) -> Result; - } + /// Returns the chain ID used for transaction signing at the + /// current best block. None is returned if not + /// available. + #[rpc(name = "eth_chainId")] + fn chain_id(&self) -> Result>; + + /// Returns current gas_price. + #[rpc(name = "eth_gasPrice")] + fn gas_price(&self) -> BoxFuture; + + /// Returns accounts list. + #[rpc(name = "eth_accounts")] + fn accounts(&self) -> Result>; + + /// Returns highest block number. + #[rpc(name = "eth_blockNumber")] + fn block_number(&self) -> Result; + + /// Returns balance of the given account. + #[rpc(name = "eth_getBalance")] + fn balance(&self, H160, Option) -> BoxFuture; + + /// Returns the account- and storage-values of the specified account including the Merkle-proof + #[rpc(name = "eth_getProof")] + fn proof(&self, H160, Vec, Option) -> BoxFuture; + + /// Returns content of the storage at given address. + #[rpc(name = "eth_getStorageAt")] + fn storage_at(&self, H160, U256, Option) -> BoxFuture; + + /// Returns block with given hash. + #[rpc(name = "eth_getBlockByHash")] + fn block_by_hash(&self, H256, bool) -> BoxFuture>; + + /// Returns block with given number. + #[rpc(name = "eth_getBlockByNumber")] + fn block_by_number(&self, BlockNumber, bool) -> BoxFuture>; + + /// Returns the number of transactions sent from given address at given time (block number). + #[rpc(name = "eth_getTransactionCount")] + fn transaction_count(&self, H160, Option) -> BoxFuture; + + /// Returns the number of transactions in a block with given hash. + #[rpc(name = "eth_getBlockTransactionCountByHash")] + fn block_transaction_count_by_hash(&self, H256) -> BoxFuture>; + + /// Returns the number of transactions in a block with given block number. + #[rpc(name = "eth_getBlockTransactionCountByNumber")] + fn block_transaction_count_by_number(&self, BlockNumber) -> BoxFuture>; + + /// Returns the number of uncles in a block with given hash. + #[rpc(name = "eth_getUncleCountByBlockHash")] + fn block_uncles_count_by_hash(&self, H256) -> BoxFuture>; + + /// Returns the number of uncles in a block with given block number. + #[rpc(name = "eth_getUncleCountByBlockNumber")] + fn block_uncles_count_by_number(&self, BlockNumber) -> BoxFuture>; + + /// Returns the code at given address at given time (block number). + #[rpc(name = "eth_getCode")] + fn code_at(&self, H160, Option) -> BoxFuture; + + /// Sends signed transaction, returning its hash. + #[rpc(name = "eth_sendRawTransaction")] + fn send_raw_transaction(&self, Bytes) -> Result; + + /// @alias of `eth_sendRawTransaction`. + #[rpc(name = "eth_submitTransaction")] + fn submit_transaction(&self, Bytes) -> Result; + + /// Call contract, returning the output data. + #[rpc(name = "eth_call")] + fn call(&self, CallRequest, Option) -> BoxFuture; + + /// Estimate gas needed for execution of given contract. + #[rpc(name = "eth_estimateGas")] + fn estimate_gas(&self, CallRequest, Option) -> BoxFuture; + + /// Get transaction by its hash. + #[rpc(name = "eth_getTransactionByHash")] + fn transaction_by_hash(&self, H256) -> BoxFuture>; + + /// Returns transaction at given block hash and index. + #[rpc(name = "eth_getTransactionByBlockHashAndIndex")] + fn transaction_by_block_hash_and_index(&self, H256, Index) -> BoxFuture>; + + /// Returns transaction by given block number and index. + #[rpc(name = "eth_getTransactionByBlockNumberAndIndex")] + fn transaction_by_block_number_and_index(&self, BlockNumber, Index) -> BoxFuture>; + + /// Returns transaction receipt by transaction hash. + #[rpc(name = "eth_getTransactionReceipt")] + fn transaction_receipt(&self, H256) -> BoxFuture>; + + /// Returns an uncles at given block and index. + #[rpc(name = "eth_getUncleByBlockHashAndIndex")] + fn uncle_by_block_hash_and_index(&self, H256, Index) -> BoxFuture>; + + /// Returns an uncles at given block and index. + #[rpc(name = "eth_getUncleByBlockNumberAndIndex")] + fn uncle_by_block_number_and_index(&self, BlockNumber, Index) -> BoxFuture>; + + /// Returns available compilers. + /// @deprecated + #[rpc(name = "eth_getCompilers")] + fn compilers(&self) -> Result>; + + /// Compiles lll code. + /// @deprecated + #[rpc(name = "eth_compileLLL")] + fn compile_lll(&self, String) -> Result; + + /// Compiles solidity. + /// @deprecated + #[rpc(name = "eth_compileSolidity")] + fn compile_solidity(&self, String) -> Result; + + /// Compiles serpent. + /// @deprecated + #[rpc(name = "eth_compileSerpent")] + fn compile_serpent(&self, String) -> Result; + + /// Returns logs matching given filter object. + #[rpc(name = "eth_getLogs")] + fn logs(&self, Filter) -> BoxFuture>; + + /// Returns the hash of the current block, the seedHash, and the boundary condition to be met. + #[rpc(name = "eth_getWork")] + fn work(&self, Option) -> Result; + + /// Used for submitting a proof-of-work solution. + #[rpc(name = "eth_submitWork")] + fn submit_work(&self, H64, H256, H256) -> Result; + + /// Used for submitting mining hashrate. + #[rpc(name = "eth_submitHashrate")] + fn submit_hashrate(&self, U256, H256) -> Result; } -build_rpc_trait! { - /// Eth filters rpc api (polling). - // TODO: do filters api properly - pub trait EthFilter { - /// Returns id of new filter. - #[rpc(name = "eth_newFilter")] - fn new_filter(&self, Filter) -> Result; - - /// Returns id of new block filter. - #[rpc(name = "eth_newBlockFilter")] - fn new_block_filter(&self) -> Result; - - /// Returns id of new block filter. - #[rpc(name = "eth_newPendingTransactionFilter")] - fn new_pending_transaction_filter(&self) -> Result; - - /// Returns filter changes since last poll. - #[rpc(name = "eth_getFilterChanges")] - fn filter_changes(&self, Index) -> BoxFuture; - - /// Returns all logs matching given filter (in a range 'from' - 'to'). - #[rpc(name = "eth_getFilterLogs")] - fn filter_logs(&self, Index) -> BoxFuture>; - - /// Uninstalls filter. - #[rpc(name = "eth_uninstallFilter")] - fn uninstall_filter(&self, Index) -> Result; - } +/// Eth filters rpc api (polling). +// TODO: do filters api properly +#[rpc] +pub trait EthFilter { + /// Returns id of new filter. + #[rpc(name = "eth_newFilter")] + fn new_filter(&self, Filter) -> Result; + + /// Returns id of new block filter. + #[rpc(name = "eth_newBlockFilter")] + fn new_block_filter(&self) -> Result; + + /// Returns id of new block filter. + #[rpc(name = "eth_newPendingTransactionFilter")] + fn new_pending_transaction_filter(&self) -> Result; + + /// Returns filter changes since last poll. + #[rpc(name = "eth_getFilterChanges")] + fn filter_changes(&self, Index) -> BoxFuture; + + /// Returns all logs matching given filter (in a range 'from' - 'to'). + #[rpc(name = "eth_getFilterLogs")] + fn filter_logs(&self, Index) -> BoxFuture>; + + /// Uninstalls filter. + #[rpc(name = "eth_uninstallFilter")] + fn uninstall_filter(&self, Index) -> Result; } diff --git a/rpc/src/v1/traits/eth_pubsub.rs b/rpc/src/v1/traits/eth_pubsub.rs index d584b7dbc9..0628781392 100644 --- a/rpc/src/v1/traits/eth_pubsub.rs +++ b/rpc/src/v1/traits/eth_pubsub.rs @@ -17,25 +17,22 @@ //! Eth PUB-SUB rpc interface. use jsonrpc_core::Result; -use jsonrpc_macros::Trailing; -use jsonrpc_macros::pubsub::Subscriber; -use jsonrpc_pubsub::SubscriptionId; +use jsonrpc_derive::rpc; +use jsonrpc_pubsub::{typed, SubscriptionId}; use v1::types::pubsub; -build_rpc_trait! { - /// Eth PUB-SUB rpc interface. - pub trait EthPubSub { - type Metadata; - - #[pubsub(name = "eth_subscription")] { - /// Subscribe to Eth subscription. - #[rpc(name = "eth_subscribe")] - fn subscribe(&self, Self::Metadata, Subscriber, pubsub::Kind, Trailing); - - /// Unsubscribe from existing Eth subscription. - #[rpc(name = "eth_unsubscribe")] - fn unsubscribe(&self, SubscriptionId) -> Result; - } - } +/// Eth PUB-SUB rpc interface. +#[rpc] +pub trait EthPubSub { + /// RPC Metadata + type Metadata; + + /// Subscribe to Eth subscription. + #[pubsub(subscription = "eth_subscription", subscribe, name = "eth_subscribe")] + fn subscribe(&self, Self::Metadata, typed::Subscriber, pubsub::Kind, Option); + + /// Unsubscribe from existing Eth subscription. + #[pubsub(subscription = "eth_subscription", unsubscribe, name = "eth_unsubscribe")] + fn unsubscribe(&self, Option, SubscriptionId) -> Result; } diff --git a/rpc/src/v1/traits/eth_signing.rs b/rpc/src/v1/traits/eth_signing.rs index 3b7d88446e..72e13ddabe 100644 --- a/rpc/src/v1/traits/eth_signing.rs +++ b/rpc/src/v1/traits/eth_signing.rs @@ -17,28 +17,30 @@ //! Eth rpc interface. use jsonrpc_core::BoxFuture; - -use v1::types::{Bytes, H160, H256, H520, TransactionRequest, RichRawTransaction}; - -build_rpc_trait! { - /// Signing methods implementation relying on unlocked accounts. - pub trait EthSigning { - type Metadata; - - /// Signs the hash of data with given address signature. - #[rpc(meta, name = "eth_sign")] - fn sign(&self, Self::Metadata, H160, Bytes) -> BoxFuture; - - /// Sends transaction; will block waiting for signer to return the - /// transaction hash. - /// If Signer is disable it will require the account to be unlocked. - #[rpc(meta, name = "eth_sendTransaction")] - fn send_transaction(&self, Self::Metadata, TransactionRequest) -> BoxFuture; - - /// Signs transactions without dispatching it to the network. - /// Returns signed transaction RLP representation and the transaction itself. - /// It can be later submitted using `eth_sendRawTransaction/eth_submitTransaction`. - #[rpc(meta, name = "eth_signTransaction")] - fn sign_transaction(&self, Self::Metadata, TransactionRequest) -> BoxFuture; - } +use jsonrpc_derive::rpc; + +use ethereum_types::{H160, H256, H520}; +use v1::types::{Bytes, TransactionRequest, RichRawTransaction}; + +/// Signing methods implementation relying on unlocked accounts. +#[rpc] +pub trait EthSigning { + /// RPC Metadata + type Metadata; + + /// Signs the hash of data with given address signature. + #[rpc(meta, name = "eth_sign")] + fn sign(&self, Self::Metadata, H160, Bytes) -> BoxFuture; + + /// Sends transaction; will block waiting for signer to return the + /// transaction hash. + /// If Signer is disable it will require the account to be unlocked. + #[rpc(meta, name = "eth_sendTransaction")] + fn send_transaction(&self, Self::Metadata, TransactionRequest) -> BoxFuture; + + /// Signs transactions without dispatching it to the network. + /// Returns signed transaction RLP representation and the transaction itself. + /// It can be later submitted using `eth_sendRawTransaction/eth_submitTransaction`. + #[rpc(meta, name = "eth_signTransaction")] + fn sign_transaction(&self, Self::Metadata, TransactionRequest) -> BoxFuture; } diff --git a/rpc/src/v1/traits/mod.rs b/rpc/src/v1/traits/mod.rs index 130fcae105..e25ca76ac4 100644 --- a/rpc/src/v1/traits/mod.rs +++ b/rpc/src/v1/traits/mod.rs @@ -40,8 +40,8 @@ pub use self::eth_pubsub::EthPubSub; pub use self::eth_signing::EthSigning; pub use self::net::Net; pub use self::parity::Parity; -pub use self::parity_accounts::ParityAccounts; -pub use self::parity_set::ParitySet; +pub use self::parity_accounts::{ParityAccounts, ParityAccountsInfo}; +pub use self::parity_set::{ParitySet, ParitySetAccounts}; pub use self::parity_signing::ParitySigning; pub use self::personal::Personal; pub use self::private::Private; diff --git a/rpc/src/v1/traits/net.rs b/rpc/src/v1/traits/net.rs index b8bdb19607..a16729294d 100644 --- a/rpc/src/v1/traits/net.rs +++ b/rpc/src/v1/traits/net.rs @@ -16,21 +16,21 @@ //! Net rpc interface. use jsonrpc_core::Result; +use jsonrpc_derive::rpc; -build_rpc_trait! { - /// Net rpc interface. - pub trait Net { - /// Returns protocol version. - #[rpc(name = "net_version")] - fn version(&self) -> Result; +/// Net rpc interface. +#[rpc] +pub trait Net { + /// Returns protocol version. + #[rpc(name = "net_version")] + fn version(&self) -> Result; - /// Returns number of peers connected to node. - #[rpc(name = "net_peerCount")] - fn peer_count(&self) -> Result; + /// Returns number of peers connected to node. + #[rpc(name = "net_peerCount")] + fn peer_count(&self) -> Result; - /// Returns true if client is actively listening for network connections. - /// Otherwise false. - #[rpc(name = "net_listening")] - fn is_listening(&self) -> Result; - } + /// Returns true if client is actively listening for network connections. + /// Otherwise false. + #[rpc(name = "net_listening")] + fn is_listening(&self) -> Result; } diff --git a/rpc/src/v1/traits/parity.rs b/rpc/src/v1/traits/parity.rs index 8333498809..e3821355ee 100644 --- a/rpc/src/v1/traits/parity.rs +++ b/rpc/src/v1/traits/parity.rs @@ -18,234 +18,218 @@ use std::collections::BTreeMap; +use ethereum_types::{H64, H160, H256, H512, U64, U256}; use jsonrpc_core::{BoxFuture, Result}; -use jsonrpc_macros::Trailing; +use jsonrpc_derive::rpc; use v1::types::{ - H160, H256, H512, U256, U64, H64, Bytes, CallRequest, + Bytes, CallRequest, Peers, Transaction, RpcSettings, Histogram, RecoveredAccount, TransactionStats, LocalTransactionStatus, BlockNumber, ConsensusCapability, VersionInfo, OperationsInfo, ChainStatus, Log, Filter, - AccountInfo, HwAccountInfo, RichHeader, Receipt, + RichHeader, Receipt, }; -build_rpc_trait! { - /// Parity-specific rpc interface. - pub trait Parity { - type Metadata; - - /// Returns accounts information. - #[rpc(name = "parity_accountsInfo")] - fn accounts_info(&self) -> Result>; - - /// Returns hardware accounts information. - #[rpc(name = "parity_hardwareAccountsInfo")] - fn hardware_accounts_info(&self) -> Result>; - - /// Get a list of paths to locked hardware wallets - #[rpc(name = "parity_lockedHardwareAccountsInfo")] - fn locked_hardware_accounts_info(&self) -> Result>; - - /// Returns default account for dapp. - #[rpc(name = "parity_defaultAccount")] - fn default_account(&self) -> Result; - - /// Returns current transactions limit. - #[rpc(name = "parity_transactionsLimit")] - fn transactions_limit(&self) -> Result; - - /// Returns mining extra data. - #[rpc(name = "parity_extraData")] - fn extra_data(&self) -> Result; - - /// Returns mining gas floor target. - #[rpc(name = "parity_gasFloorTarget")] - fn gas_floor_target(&self) -> Result; - - /// Returns mining gas floor cap. - #[rpc(name = "parity_gasCeilTarget")] - fn gas_ceil_target(&self) -> Result; - - /// Returns minimal gas price for transaction to be included in queue. - #[rpc(name = "parity_minGasPrice")] - fn min_gas_price(&self) -> Result; - - /// Returns latest logs - #[rpc(name = "parity_devLogs")] - fn dev_logs(&self) -> Result>; - - /// Returns logs levels - #[rpc(name = "parity_devLogsLevels")] - fn dev_logs_levels(&self) -> Result; - - /// Returns chain name - DEPRECATED. Use `parity_chainName` instead. - #[rpc(name = "parity_netChain")] - fn net_chain(&self) -> Result; - - /// Returns peers details - #[rpc(name = "parity_netPeers")] - fn net_peers(&self) -> Result; - - /// Returns network port - #[rpc(name = "parity_netPort")] - fn net_port(&self) -> Result; - - /// Returns rpc settings - #[rpc(name = "parity_rpcSettings")] - fn rpc_settings(&self) -> Result; - - /// Returns node name - #[rpc(name = "parity_nodeName")] - fn node_name(&self) -> Result; - - /// Returns default extra data - #[rpc(name = "parity_defaultExtraData")] - fn default_extra_data(&self) -> Result; - - /// Returns distribution of gas price in latest blocks. - #[rpc(name = "parity_gasPriceHistogram")] - fn gas_price_histogram(&self) -> BoxFuture; - - /// Returns number of unsigned transactions waiting in the signer queue (if signer enabled) - /// Returns error when signer is disabled - #[rpc(name = "parity_unsignedTransactionsCount")] - fn unsigned_transactions_count(&self) -> Result; - - /// Returns a cryptographically random phrase sufficient for securely seeding a secret key. - #[rpc(name = "parity_generateSecretPhrase")] - fn generate_secret_phrase(&self) -> Result; - - /// Returns whatever address would be derived from the given phrase if it were to seed a brainwallet. - #[rpc(name = "parity_phraseToAddress")] - fn phrase_to_address(&self, String) -> Result; - - /// Returns the value of the registrar for this network. - #[rpc(name = "parity_registryAddress")] - fn registry_address(&self) -> Result>; - - /// Returns all addresses if Fat DB is enabled (`--fat-db`), or null if not. - #[rpc(name = "parity_listAccounts")] - fn list_accounts(&self, u64, Option, Trailing) -> Result>>; - - /// Returns all storage keys of the given address (first parameter) if Fat DB is enabled (`--fat-db`), - /// or null if not. - #[rpc(name = "parity_listStorageKeys")] - fn list_storage_keys(&self, H160, u64, Option, Trailing) -> Result>>; - - /// Encrypt some data with a public key under ECIES. - /// First parameter is the 512-byte destination public key, second is the message. - #[rpc(name = "parity_encryptMessage")] - fn encrypt_message(&self, H512, Bytes) -> Result; - - /// Returns all pending transactions from transaction queue. - #[rpc(name = "parity_pendingTransactions")] - fn pending_transactions(&self, Trailing) -> Result>; - - /// Returns all transactions from transaction queue. - /// - /// Some of them might not be ready to be included in a block yet. - #[rpc(name = "parity_allTransactions")] - fn all_transactions(&self) -> Result>; - - /// Same as parity_allTransactions, but return only transactions hashes. - #[rpc(name = "parity_allTransactionHashes")] - fn all_transaction_hashes(&self) -> Result>; - - /// Returns all future transactions from transaction queue (deprecated) - #[rpc(name = "parity_futureTransactions")] - fn future_transactions(&self) -> Result>; - - /// Returns propagation statistics on transactions pending in the queue. - #[rpc(name = "parity_pendingTransactionsStats")] - fn pending_transactions_stats(&self) -> Result>; - - /// Returns a list of current and past local transactions with status details. - #[rpc(name = "parity_localTransactions")] - fn local_transactions(&self) -> Result>; - - /// Returns current WS Server interface and port or an error if ws server is disabled. - #[rpc(name = "parity_wsUrl")] - fn ws_url(&self) -> Result; - - /// Returns next nonce for particular sender. Should include all transactions in the queue. - #[rpc(name = "parity_nextNonce")] - fn next_nonce(&self, H160) -> BoxFuture; - - /// Get the mode. Returns one of: "active", "passive", "dark", "offline". - #[rpc(name = "parity_mode")] - fn mode(&self) -> Result; - - /// Get the chain name. Returns one of the pre-configured chain names or a filename. - #[rpc(name = "parity_chain")] - fn chain(&self) -> Result; - - /// Get the enode of this node. - #[rpc(name = "parity_enode")] - fn enode(&self) -> Result; - - /// Returns information on current consensus capability. - #[rpc(name = "parity_consensusCapability")] - fn consensus_capability(&self) -> Result; - - /// Get our version information in a nice object. - #[rpc(name = "parity_versionInfo")] - fn version_info(&self) -> Result; - - /// Get information concerning the latest releases if available. - #[rpc(name = "parity_releasesInfo")] - fn releases_info(&self) -> Result>; - - /// Get the current chain status. - #[rpc(name = "parity_chainStatus")] - fn chain_status(&self) -> Result; - - /// Get node kind info. - #[rpc(name = "parity_nodeKind")] - fn node_kind(&self) -> Result<::v1::types::NodeKind>; - - /// Get block header. - /// Same as `eth_getBlockByNumber` but without uncles and transactions. - #[rpc(name = "parity_getBlockHeaderByNumber")] - fn block_header(&self, Trailing) -> BoxFuture; - - /// Get block receipts. - /// Allows you to fetch receipts from the entire block at once. - /// If no parameter is provided defaults to `latest`. - #[rpc(name = "parity_getBlockReceipts")] - fn block_receipts(&self, Trailing) -> BoxFuture>; - - /// Get IPFS CIDv0 given protobuf encoded bytes. - #[rpc(name = "parity_cidV0")] - fn ipfs_cid(&self, Bytes) -> Result; - - /// Call contract, returning the output data. - #[rpc(name = "parity_call")] - fn call(&self, Vec, Trailing) -> Result>; - - /// Used for submitting a proof-of-work solution (similar to `eth_submitWork`, - /// but returns block hash on success, and returns an explicit error message on failure). - #[rpc(name = "parity_submitWorkDetail")] - fn submit_work_detail(&self, H64, H256, H256) -> Result; - - /// Returns the status of the node. Used as the health endpoint. - /// - /// The RPC returns successful response if: - /// - The node have a peer (unless running a dev chain) - /// - The node is not syncing. - /// - /// Otherwise the RPC returns error. - #[rpc(name = "parity_nodeStatus")] - fn status(&self) -> Result<()>; - - /// Extracts Address and public key from signature using the r, s and v params. Equivalent to Solidity erecover - /// as well as checks the signature for chain replay protection - #[rpc(name = "parity_verifySignature")] - fn verify_signature(&self, bool, Bytes, H256, H256, U64) -> Result; - - /// Returns logs matching given filter object. - /// Is allowed to skip filling transaction hash for faster query. - #[rpc(name = "parity_getLogsNoTransactionHash")] - fn logs_no_tx_hash(&self, Filter) -> BoxFuture>; - - } +/// Parity-specific rpc interface. +#[rpc] +pub trait Parity { + /// RPC Metadata + type Metadata; + + /// Returns current transactions limit. + #[rpc(name = "parity_transactionsLimit")] + fn transactions_limit(&self) -> Result; + + /// Returns mining extra data. + #[rpc(name = "parity_extraData")] + fn extra_data(&self) -> Result; + + /// Returns mining gas floor target. + #[rpc(name = "parity_gasFloorTarget")] + fn gas_floor_target(&self) -> Result; + + /// Returns mining gas floor cap. + #[rpc(name = "parity_gasCeilTarget")] + fn gas_ceil_target(&self) -> Result; + + /// Returns minimal gas price for transaction to be included in queue. + #[rpc(name = "parity_minGasPrice")] + fn min_gas_price(&self) -> Result; + + /// Returns latest logs + #[rpc(name = "parity_devLogs")] + fn dev_logs(&self) -> Result>; + + /// Returns logs levels + #[rpc(name = "parity_devLogsLevels")] + fn dev_logs_levels(&self) -> Result; + + /// Returns chain name - DEPRECATED. Use `parity_chainName` instead. + #[rpc(name = "parity_netChain")] + fn net_chain(&self) -> Result; + + /// Returns peers details + #[rpc(name = "parity_netPeers")] + fn net_peers(&self) -> Result; + + /// Returns network port + #[rpc(name = "parity_netPort")] + fn net_port(&self) -> Result; + + /// Returns rpc settings + #[rpc(name = "parity_rpcSettings")] + fn rpc_settings(&self) -> Result; + + /// Returns node name + #[rpc(name = "parity_nodeName")] + fn node_name(&self) -> Result; + + /// Returns default extra data + #[rpc(name = "parity_defaultExtraData")] + fn default_extra_data(&self) -> Result; + + /// Returns distribution of gas price in latest blocks. + #[rpc(name = "parity_gasPriceHistogram")] + fn gas_price_histogram(&self) -> BoxFuture; + + /// Returns number of unsigned transactions waiting in the signer queue (if signer enabled) + /// Returns error when signer is disabled + #[rpc(name = "parity_unsignedTransactionsCount")] + fn unsigned_transactions_count(&self) -> Result; + + /// Returns a cryptographically random phrase sufficient for securely seeding a secret key. + #[rpc(name = "parity_generateSecretPhrase")] + fn generate_secret_phrase(&self) -> Result; + + /// Returns whatever address would be derived from the given phrase if it were to seed a brainwallet. + #[rpc(name = "parity_phraseToAddress")] + fn phrase_to_address(&self, String) -> Result; + + /// Returns the value of the registrar for this network. + #[rpc(name = "parity_registryAddress")] + fn registry_address(&self) -> Result>; + + /// Returns all addresses if Fat DB is enabled (`--fat-db`), or null if not. + #[rpc(name = "parity_listAccounts")] + fn list_accounts(&self, u64, Option, Option) -> Result>>; + + /// Returns all storage keys of the given address (first parameter) if Fat DB is enabled (`--fat-db`), + /// or null if not. + #[rpc(name = "parity_listStorageKeys")] + fn list_storage_keys(&self, H160, u64, Option, Option) -> Result>>; + + /// Encrypt some data with a public key under ECIES. + /// First parameter is the 512-byte destination public key, second is the message. + #[rpc(name = "parity_encryptMessage")] + fn encrypt_message(&self, H512, Bytes) -> Result; + + /// Returns all pending transactions from transaction queue. + #[rpc(name = "parity_pendingTransactions")] + fn pending_transactions(&self, Option) -> Result>; + + /// Returns all transactions from transaction queue. + /// + /// Some of them might not be ready to be included in a block yet. + #[rpc(name = "parity_allTransactions")] + fn all_transactions(&self) -> Result>; + + /// Same as parity_allTransactions, but return only transactions hashes. + #[rpc(name = "parity_allTransactionHashes")] + fn all_transaction_hashes(&self) -> Result>; + + /// Returns all future transactions from transaction queue (deprecated) + #[rpc(name = "parity_futureTransactions")] + fn future_transactions(&self) -> Result>; + + /// Returns propagation statistics on transactions pending in the queue. + #[rpc(name = "parity_pendingTransactionsStats")] + fn pending_transactions_stats(&self) -> Result>; + + /// Returns a list of current and past local transactions with status details. + #[rpc(name = "parity_localTransactions")] + fn local_transactions(&self) -> Result>; + + /// Returns current WS Server interface and port or an error if ws server is disabled. + #[rpc(name = "parity_wsUrl")] + fn ws_url(&self) -> Result; + + /// Returns next nonce for particular sender. Should include all transactions in the queue. + #[rpc(name = "parity_nextNonce")] + fn next_nonce(&self, H160) -> BoxFuture; + + /// Get the mode. Returns one of: "active", "passive", "dark", "offline". + #[rpc(name = "parity_mode")] + fn mode(&self) -> Result; + + /// Get the chain name. Returns one of the pre-configured chain names or a filename. + #[rpc(name = "parity_chain")] + fn chain(&self) -> Result; + + /// Get the enode of this node. + #[rpc(name = "parity_enode")] + fn enode(&self) -> Result; + + /// Returns information on current consensus capability. + #[rpc(name = "parity_consensusCapability")] + fn consensus_capability(&self) -> Result; + + /// Get our version information in a nice object. + #[rpc(name = "parity_versionInfo")] + fn version_info(&self) -> Result; + + /// Get information concerning the latest releases if available. + #[rpc(name = "parity_releasesInfo")] + fn releases_info(&self) -> Result>; + + /// Get the current chain status. + #[rpc(name = "parity_chainStatus")] + fn chain_status(&self) -> Result; + + /// Get node kind info. + #[rpc(name = "parity_nodeKind")] + fn node_kind(&self) -> Result<::v1::types::NodeKind>; + + /// Get block header. + /// Same as `eth_getBlockByNumber` but without uncles and transactions. + #[rpc(name = "parity_getBlockHeaderByNumber")] + fn block_header(&self, Option) -> BoxFuture; + + /// Get block receipts. + /// Allows you to fetch receipts from the entire block at once. + /// If no parameter is provided defaults to `latest`. + #[rpc(name = "parity_getBlockReceipts")] + fn block_receipts(&self, Option) -> BoxFuture>; + + /// Get IPFS CIDv0 given protobuf encoded bytes. + #[rpc(name = "parity_cidV0")] + fn ipfs_cid(&self, Bytes) -> Result; + + /// Call contract, returning the output data. + #[rpc(name = "parity_call")] + fn call(&self, Vec, Option) -> Result>; + + /// Used for submitting a proof-of-work solution (similar to `eth_submitWork`, + /// but returns block hash on success, and returns an explicit error message on failure). + #[rpc(name = "parity_submitWorkDetail")] + fn submit_work_detail(&self, H64, H256, H256) -> Result; + + /// Returns the status of the node. Used as the health endpoint. + /// + /// The RPC returns successful response if: + /// - The node have a peer (unless running a dev chain) + /// - The node is not syncing. + /// + /// Otherwise the RPC returns error. + #[rpc(name = "parity_nodeStatus")] + fn status(&self) -> Result<()>; + + /// Extracts Address and public key from signature using the r, s and v params. Equivalent to Solidity erecover + /// as well as checks the signature for chain replay protection + #[rpc(name = "parity_verifySignature")] + fn verify_signature(&self, bool, Bytes, H256, H256, U64) -> Result; + + /// Returns logs matching given filter object. + /// Is allowed to skip filling transaction hash for faster query. + #[rpc(name = "parity_getLogsNoTransactionHash")] + fn logs_no_tx_hash(&self, Filter) -> BoxFuture>; } diff --git a/rpc/src/v1/traits/parity_accounts.rs b/rpc/src/v1/traits/parity_accounts.rs index 8037161e05..eaffac7885 100644 --- a/rpc/src/v1/traits/parity_accounts.rs +++ b/rpc/src/v1/traits/parity_accounts.rs @@ -18,125 +18,147 @@ use std::collections::BTreeMap; use jsonrpc_core::Result; +use jsonrpc_derive::rpc; +use ethereum_types::{H160, H256, H520}; use ethkey::Password; use ethstore::KeyFile; -use v1::types::{H160, H256, H520, DeriveHash, DeriveHierarchical, ExtAccountInfo}; - -build_rpc_trait! { - /// Personal Parity rpc interface. - pub trait ParityAccounts { - /// Returns accounts information. - #[rpc(name = "parity_allAccountsInfo")] - fn all_accounts_info(&self) -> Result>; - - /// Creates new account from the given phrase using standard brainwallet mechanism. - /// Second parameter is password for the new account. - #[rpc(name = "parity_newAccountFromPhrase")] - fn new_account_from_phrase(&self, String, Password) -> Result; - - /// Creates new account from the given JSON wallet. - /// Second parameter is password for the wallet and the new account. - #[rpc(name = "parity_newAccountFromWallet")] - fn new_account_from_wallet(&self, String, Password) -> Result; - - /// Creates new account from the given raw secret. - /// Second parameter is password for the new account. - #[rpc(name = "parity_newAccountFromSecret")] - fn new_account_from_secret(&self, H256, Password) -> Result; - - /// Returns true if given `password` would unlock given `account`. - /// Arguments: `account`, `password`. - #[rpc(name = "parity_testPassword")] - fn test_password(&self, H160, Password) -> Result; - - /// Changes an account's password. - /// Arguments: `account`, `password`, `new_password`. - #[rpc(name = "parity_changePassword")] - fn change_password(&self, H160, Password, Password) -> Result; - - /// Permanently deletes an account. - /// Arguments: `account`, `password`. - #[rpc(name = "parity_killAccount")] - fn kill_account(&self, H160, Password) -> Result; - - /// Permanently deletes an address from the addressbook - /// Arguments: `address` - #[rpc(name = "parity_removeAddress")] - fn remove_address(&self, H160) -> Result; - - /// Set an account's name. - #[rpc(name = "parity_setAccountName")] - fn set_account_name(&self, H160, String) -> Result; - - /// Set an account's metadata string. - #[rpc(name = "parity_setAccountMeta")] - fn set_account_meta(&self, H160, String) -> Result; - - /// Imports a number of Geth accounts, with the list provided as the argument. - #[rpc(name = "parity_importGethAccounts")] - fn import_geth_accounts(&self, Vec) -> Result>; - - /// Returns the accounts available for importing from Geth. - #[rpc(name = "parity_listGethAccounts")] - fn geth_accounts(&self) -> Result>; - - /// Create new vault. - #[rpc(name = "parity_newVault")] - fn create_vault(&self, String, Password) -> Result; - - /// Open existing vault. - #[rpc(name = "parity_openVault")] - fn open_vault(&self, String, Password) -> Result; - - /// Close previously opened vault. - #[rpc(name = "parity_closeVault")] - fn close_vault(&self, String) -> Result; - - /// List all vaults. - #[rpc(name = "parity_listVaults")] - fn list_vaults(&self) -> Result>; - - /// List all currently opened vaults. - #[rpc(name = "parity_listOpenedVaults")] - fn list_opened_vaults(&self) -> Result>; - - /// Change vault password. - #[rpc(name = "parity_changeVaultPassword")] - fn change_vault_password(&self, String, Password) -> Result; - - /// Change vault of the given address. - #[rpc(name = "parity_changeVault")] - fn change_vault(&self, H160, String) -> Result; - - /// Get vault metadata string. - #[rpc(name = "parity_getVaultMeta")] - fn get_vault_meta(&self, String) -> Result; - - /// Set vault metadata string. - #[rpc(name = "parity_setVaultMeta")] - fn set_vault_meta(&self, String, String) -> Result; - - /// Derive new address from given account address using specific hash. - /// Resulting address can be either saved as a new account (with the same password). - #[rpc(name = "parity_deriveAddressHash")] - fn derive_key_hash(&self, H160, Password, DeriveHash, bool) -> Result; - - /// Derive new address from given account address using - /// hierarchical derivation (sequence of 32-bit integer indices). - /// Resulting address can be either saved as a new account (with the same password). - #[rpc(name = "parity_deriveAddressIndex")] - fn derive_key_index(&self, H160, Password, DeriveHierarchical, bool) -> Result; - - /// Exports an account with given address if provided password matches. - #[rpc(name = "parity_exportAccount")] - fn export_account(&self, H160, Password) -> Result; - - /// Sign raw hash with the key corresponding to address and password. - #[rpc(name = "parity_signMessage")] - fn sign_message(&self, H160, Password, H256) -> Result; - - /// Send a PinMatrixAck to a hardware wallet, unlocking it - #[rpc(name = "parity_hardwarePinMatrixAck")] - fn hardware_pin_matrix_ack(&self, String, String) -> Result; - } +use v1::types::{DeriveHash, DeriveHierarchical, ExtAccountInfo}; +use v1::types::{AccountInfo, HwAccountInfo}; + +/// Parity-specific read-only accounts rpc interface. +#[rpc] +pub trait ParityAccountsInfo { + /// Returns accounts information. + #[rpc(name = "parity_accountsInfo")] + fn accounts_info(&self) -> Result>; + + /// Returns hardware accounts information. + #[rpc(name = "parity_hardwareAccountsInfo")] + fn hardware_accounts_info(&self) -> Result>; + + /// Get a list of paths to locked hardware wallets + #[rpc(name = "parity_lockedHardwareAccountsInfo")] + fn locked_hardware_accounts_info(&self) -> Result>; + + /// Returns default account for dapp. + #[rpc(name = "parity_defaultAccount")] + fn default_account(&self) -> Result; +} + +/// Personal Parity rpc interface. +#[rpc] +pub trait ParityAccounts { + /// Returns accounts information. + #[rpc(name = "parity_allAccountsInfo")] + fn all_accounts_info(&self) -> Result>; + + /// Creates new account from the given phrase using standard brainwallet mechanism. + /// Second parameter is password for the new account. + #[rpc(name = "parity_newAccountFromPhrase")] + fn new_account_from_phrase(&self, String, Password) -> Result; + + /// Creates new account from the given JSON wallet. + /// Second parameter is password for the wallet and the new account. + #[rpc(name = "parity_newAccountFromWallet")] + fn new_account_from_wallet(&self, String, Password) -> Result; + + /// Creates new account from the given raw secret. + /// Second parameter is password for the new account. + #[rpc(name = "parity_newAccountFromSecret")] + fn new_account_from_secret(&self, H256, Password) -> Result; + + /// Returns true if given `password` would unlock given `account`. + /// Arguments: `account`, `password`. + #[rpc(name = "parity_testPassword")] + fn test_password(&self, H160, Password) -> Result; + + /// Changes an account's password. + /// Arguments: `account`, `password`, `new_password`. + #[rpc(name = "parity_changePassword")] + fn change_password(&self, H160, Password, Password) -> Result; + + /// Permanently deletes an account. + /// Arguments: `account`, `password`. + #[rpc(name = "parity_killAccount")] + fn kill_account(&self, H160, Password) -> Result; + + /// Permanently deletes an address from the addressbook + /// Arguments: `address` + #[rpc(name = "parity_removeAddress")] + fn remove_address(&self, H160) -> Result; + + /// Set an account's name. + #[rpc(name = "parity_setAccountName")] + fn set_account_name(&self, H160, String) -> Result; + + /// Set an account's metadata string. + #[rpc(name = "parity_setAccountMeta")] + fn set_account_meta(&self, H160, String) -> Result; + + /// Imports a number of Geth accounts, with the list provided as the argument. + #[rpc(name = "parity_importGethAccounts")] + fn import_geth_accounts(&self, Vec) -> Result>; + + /// Returns the accounts available for importing from Geth. + #[rpc(name = "parity_listGethAccounts")] + fn geth_accounts(&self) -> Result>; + + /// Create new vault. + #[rpc(name = "parity_newVault")] + fn create_vault(&self, String, Password) -> Result; + + /// Open existing vault. + #[rpc(name = "parity_openVault")] + fn open_vault(&self, String, Password) -> Result; + + /// Close previously opened vault. + #[rpc(name = "parity_closeVault")] + fn close_vault(&self, String) -> Result; + + /// List all vaults. + #[rpc(name = "parity_listVaults")] + fn list_vaults(&self) -> Result>; + + /// List all currently opened vaults. + #[rpc(name = "parity_listOpenedVaults")] + fn list_opened_vaults(&self) -> Result>; + + /// Change vault password. + #[rpc(name = "parity_changeVaultPassword")] + fn change_vault_password(&self, String, Password) -> Result; + + /// Change vault of the given address. + #[rpc(name = "parity_changeVault")] + fn change_vault(&self, H160, String) -> Result; + + /// Get vault metadata string. + #[rpc(name = "parity_getVaultMeta")] + fn get_vault_meta(&self, String) -> Result; + + /// Set vault metadata string. + #[rpc(name = "parity_setVaultMeta")] + fn set_vault_meta(&self, String, String) -> Result; + + /// Derive new address from given account address using specific hash. + /// Resulting address can be either saved as a new account (with the same password). + #[rpc(name = "parity_deriveAddressHash")] + fn derive_key_hash(&self, H160, Password, DeriveHash, bool) -> Result; + + /// Derive new address from given account address using + /// hierarchical derivation (sequence of 32-bit integer indices). + /// Resulting address can be either saved as a new account (with the same password). + #[rpc(name = "parity_deriveAddressIndex")] + fn derive_key_index(&self, H160, Password, DeriveHierarchical, bool) -> Result; + + /// Exports an account with given address if provided password matches. + #[rpc(name = "parity_exportAccount")] + fn export_account(&self, H160, Password) -> Result; + + /// Sign raw hash with the key corresponding to address and password. + #[rpc(name = "parity_signMessage")] + fn sign_message(&self, H160, Password, H256) -> Result; + + /// Send a PinMatrixAck to a hardware wallet, unlocking it + #[rpc(name = "parity_hardwarePinMatrixAck")] + fn hardware_pin_matrix_ack(&self, String, String) -> Result; } diff --git a/rpc/src/v1/traits/parity_set.rs b/rpc/src/v1/traits/parity_set.rs index 66f91a524d..c7c2338790 100644 --- a/rpc/src/v1/traits/parity_set.rs +++ b/rpc/src/v1/traits/parity_set.rs @@ -16,100 +16,109 @@ //! Parity-specific rpc interface for operations altering the settings. +use ethereum_types::{H160, H256, U256}; use jsonrpc_core::{BoxFuture, Result}; +use jsonrpc_derive::rpc; -use v1::types::{Bytes, H160, H256, U256, ReleaseInfo, Transaction}; - -build_rpc_trait! { - /// Parity-specific rpc interface for operations altering the settings. - pub trait ParitySet { - /// Sets new minimal gas price for mined blocks. - #[rpc(name = "parity_setMinGasPrice")] - fn set_min_gas_price(&self, U256) -> Result; - - /// Sets new gas floor target for mined blocks. - #[rpc(name = "parity_setGasFloorTarget")] - fn set_gas_floor_target(&self, U256) -> Result; - - /// Sets new gas ceiling target for mined blocks. - #[rpc(name = "parity_setGasCeilTarget")] - fn set_gas_ceil_target(&self, U256) -> Result; - - /// Sets new extra data for mined blocks. - #[rpc(name = "parity_setExtraData")] - fn set_extra_data(&self, Bytes) -> Result; - - /// Sets new author for mined block. - #[rpc(name = "parity_setAuthor")] - fn set_author(&self, H160) -> Result; - - /// Sets account for signing consensus messages. - #[rpc(name = "parity_setEngineSigner")] - fn set_engine_signer(&self, H160, String) -> Result; - - /// Sets the limits for transaction queue. - #[rpc(name = "parity_setTransactionsLimit")] - fn set_transactions_limit(&self, usize) -> Result; - - /// Sets the maximum amount of gas a single transaction may consume. - #[rpc(name = "parity_setMaxTransactionGas")] - fn set_tx_gas_limit(&self, U256) -> Result; - - /// Add a reserved peer. - #[rpc(name = "parity_addReservedPeer")] - fn add_reserved_peer(&self, String) -> Result; - - /// Remove a reserved peer. - #[rpc(name = "parity_removeReservedPeer")] - fn remove_reserved_peer(&self, String) -> Result; - - /// Drop all non-reserved peers. - #[rpc(name = "parity_dropNonReservedPeers")] - fn drop_non_reserved_peers(&self) -> Result; - - /// Accept non-reserved peers (default behavior) - #[rpc(name = "parity_acceptNonReservedPeers")] - fn accept_non_reserved_peers(&self) -> Result; - - /// Start the network. - /// - /// @deprecated - Use `set_mode("active")` instead. - #[rpc(name = "parity_startNetwork")] - fn start_network(&self) -> Result; - - /// Stop the network. - /// - /// @deprecated - Use `set_mode("offline")` instead. - #[rpc(name = "parity_stopNetwork")] - fn stop_network(&self) -> Result; - - /// Set the mode. Argument must be one of: "active", "passive", "dark", "offline". - #[rpc(name = "parity_setMode")] - fn set_mode(&self, String) -> Result; - - /// Set the network spec. Argument must be one of pre-configured chains or a filename. - #[rpc(name = "parity_setChain")] - fn set_spec_name(&self, String) -> Result; - - /// Hash a file content under given URL. - #[rpc(name = "parity_hashContent")] - fn hash_content(&self, String) -> BoxFuture; - - /// Is there a release ready for install? - #[rpc(name = "parity_upgradeReady")] - fn upgrade_ready(&self) -> Result>; - - /// Execute a release which is ready according to upgrade_ready(). - #[rpc(name = "parity_executeUpgrade")] - fn execute_upgrade(&self) -> Result; - - /// Removes transaction from transaction queue. - /// Makes sense only for transactions that were not propagated to other peers yet - /// like scheduled transactions or transactions in future. - /// It might also work for some local transactions with to low gas price - /// or excessive gas limit that are not accepted by other peers whp. - /// Returns `true` when transaction was removed, `false` if it was not found. - #[rpc(name = "parity_removeTransaction")] - fn remove_transaction(&self, H256) -> Result>; - } +use v1::types::{Bytes, ReleaseInfo, Transaction}; + +/// Parity-specific rpc interface for operations altering the account-related settings. +#[rpc] +pub trait ParitySetAccounts { + /// Sets account for signing consensus messages. + #[rpc(name = "parity_setEngineSigner")] + fn set_engine_signer(&self, H160, String) -> Result; +} + +/// Parity-specific rpc interface for operations altering the settings. +#[rpc] +pub trait ParitySet { + /// Sets new minimal gas price for mined blocks. + #[rpc(name = "parity_setMinGasPrice")] + fn set_min_gas_price(&self, U256) -> Result; + + /// Sets new gas floor target for mined blocks. + #[rpc(name = "parity_setGasFloorTarget")] + fn set_gas_floor_target(&self, U256) -> Result; + + /// Sets new gas ceiling target for mined blocks. + #[rpc(name = "parity_setGasCeilTarget")] + fn set_gas_ceil_target(&self, U256) -> Result; + + /// Sets new extra data for mined blocks. + #[rpc(name = "parity_setExtraData")] + fn set_extra_data(&self, Bytes) -> Result; + + /// Sets new author for mined block. + #[rpc(name = "parity_setAuthor")] + fn set_author(&self, H160) -> Result; + + /// Sets the secret of engine signer account. + #[rpc(name = "parity_setEngineSignerSecret")] + fn set_engine_signer_secret(&self, H256) -> Result; + + /// Sets the limits for transaction queue. + #[rpc(name = "parity_setTransactionsLimit")] + fn set_transactions_limit(&self, usize) -> Result; + + /// Sets the maximum amount of gas a single transaction may consume. + #[rpc(name = "parity_setMaxTransactionGas")] + fn set_tx_gas_limit(&self, U256) -> Result; + + /// Add a reserved peer. + #[rpc(name = "parity_addReservedPeer")] + fn add_reserved_peer(&self, String) -> Result; + + /// Remove a reserved peer. + #[rpc(name = "parity_removeReservedPeer")] + fn remove_reserved_peer(&self, String) -> Result; + + /// Drop all non-reserved peers. + #[rpc(name = "parity_dropNonReservedPeers")] + fn drop_non_reserved_peers(&self) -> Result; + + /// Accept non-reserved peers (default behavior) + #[rpc(name = "parity_acceptNonReservedPeers")] + fn accept_non_reserved_peers(&self) -> Result; + + /// Start the network. + /// + /// @deprecated - Use `set_mode("active")` instead. + #[rpc(name = "parity_startNetwork")] + fn start_network(&self) -> Result; + + /// Stop the network. + /// + /// @deprecated - Use `set_mode("offline")` instead. + #[rpc(name = "parity_stopNetwork")] + fn stop_network(&self) -> Result; + + /// Set the mode. Argument must be one of: "active", "passive", "dark", "offline". + #[rpc(name = "parity_setMode")] + fn set_mode(&self, String) -> Result; + + /// Set the network spec. Argument must be one of pre-configured chains or a filename. + #[rpc(name = "parity_setChain")] + fn set_spec_name(&self, String) -> Result; + + /// Hash a file content under given URL. + #[rpc(name = "parity_hashContent")] + fn hash_content(&self, String) -> BoxFuture; + + /// Is there a release ready for install? + #[rpc(name = "parity_upgradeReady")] + fn upgrade_ready(&self) -> Result>; + + /// Execute a release which is ready according to upgrade_ready(). + #[rpc(name = "parity_executeUpgrade")] + fn execute_upgrade(&self) -> Result; + + /// Removes transaction from transaction queue. + /// Makes sense only for transactions that were not propagated to other peers yet + /// like scheduled transactions or transactions in future. + /// It might also work for some local transactions with to low gas price + /// or excessive gas limit that are not accepted by other peers whp. + /// Returns `true` when transaction was removed, `false` if it was not found. + #[rpc(name = "parity_removeTransaction")] + fn remove_transaction(&self, H256) -> Result>; } diff --git a/rpc/src/v1/traits/parity_signing.rs b/rpc/src/v1/traits/parity_signing.rs index e716204be7..acd9e8cd68 100644 --- a/rpc/src/v1/traits/parity_signing.rs +++ b/rpc/src/v1/traits/parity_signing.rs @@ -16,37 +16,39 @@ //! ParitySigning rpc interface. use jsonrpc_core::{BoxFuture, Result}; - -use v1::types::{U256, H160, Bytes, ConfirmationResponse, TransactionRequest, Either}; - -build_rpc_trait! { - /// Signing methods implementation. - pub trait ParitySigning { - type Metadata; - - /// Given partial transaction request produces transaction with all fields filled in. - /// Such transaction can be then signed externally. - #[rpc(meta, name = "parity_composeTransaction")] - fn compose_transaction(&self, Self::Metadata, TransactionRequest) -> BoxFuture; - - /// Posts sign request asynchronously. - /// Will return a confirmation ID for later use with check_transaction. - #[rpc(meta, name = "parity_postSign")] - fn post_sign(&self, Self::Metadata, H160, Bytes) -> BoxFuture>; - - /// Posts transaction asynchronously. - /// Will return a transaction ID for later use with check_transaction. - #[rpc(meta, name = "parity_postTransaction")] - fn post_transaction(&self, Self::Metadata, TransactionRequest) -> BoxFuture>; - - /// Checks the progress of a previously posted request (transaction/sign). - /// Should be given a valid send_transaction ID. - #[rpc(name = "parity_checkRequest")] - fn check_request(&self, U256) -> Result>; - - /// Decrypt some ECIES-encrypted message. - /// First parameter is the address with which it is encrypted, second is the ciphertext. - #[rpc(meta, name = "parity_decryptMessage")] - fn decrypt_message(&self, Self::Metadata, H160, Bytes) -> BoxFuture; - } +use jsonrpc_derive::rpc; + +use ethereum_types::{H160, U256}; +use v1::types::{Bytes, ConfirmationResponse, TransactionRequest, Either}; + +/// Signing methods implementation. +#[rpc] +pub trait ParitySigning { + /// RPC Metadata + type Metadata; + + /// Given partial transaction request produces transaction with all fields filled in. + /// Such transaction can be then signed externally. + #[rpc(meta, name = "parity_composeTransaction")] + fn compose_transaction(&self, Self::Metadata, TransactionRequest) -> BoxFuture; + + /// Posts sign request asynchronously. + /// Will return a confirmation ID for later use with check_transaction. + #[rpc(meta, name = "parity_postSign")] + fn post_sign(&self, Self::Metadata, H160, Bytes) -> BoxFuture>; + + /// Posts transaction asynchronously. + /// Will return a transaction ID for later use with check_transaction. + #[rpc(meta, name = "parity_postTransaction")] + fn post_transaction(&self, Self::Metadata, TransactionRequest) -> BoxFuture>; + + /// Checks the progress of a previously posted request (transaction/sign). + /// Should be given a valid send_transaction ID. + #[rpc(name = "parity_checkRequest")] + fn check_request(&self, U256) -> Result>; + + /// Decrypt some ECIES-encrypted message. + /// First parameter is the address with which it is encrypted, second is the ciphertext. + #[rpc(meta, name = "parity_decryptMessage")] + fn decrypt_message(&self, Self::Metadata, H160, Bytes) -> BoxFuture; } diff --git a/rpc/src/v1/traits/personal.rs b/rpc/src/v1/traits/personal.rs index 8965564e7b..e3632731fa 100644 --- a/rpc/src/v1/traits/personal.rs +++ b/rpc/src/v1/traits/personal.rs @@ -16,58 +16,59 @@ //! Personal rpc interface. use eip_712::EIP712; +use ethereum_types::{H160, H256, H520, U128}; use jsonrpc_core::types::Value; use jsonrpc_core::{BoxFuture, Result}; -use v1::types::{Bytes, U128, H160, H256, H520, TransactionRequest, RichRawTransaction as RpcRichRawTransaction, EIP191Version}; - -build_rpc_trait! { - /// Personal rpc interface. Safe (read-only) functions. - pub trait Personal { - type Metadata; - - /// Lists all stored accounts - #[rpc(name = "personal_listAccounts")] - fn accounts(&self) -> Result>; - - /// Creates new account (it becomes new current unlocked account) - /// Param is the password for the account. - #[rpc(name = "personal_newAccount")] - fn new_account(&self, String) -> Result; - - /// Unlocks specified account for use (can only be one unlocked account at one moment) - #[rpc(name = "personal_unlockAccount")] - fn unlock_account(&self, H160, String, Option) -> Result; - - /// Signs the hash of data with given account signature using the given password to unlock the account during - /// the request. - #[rpc(name = "personal_sign")] - fn sign(&self, Bytes, H160, String) -> BoxFuture; - - /// Produces an EIP-712 compliant signature with given account using the given password to unlock the - /// account during the request. - #[rpc(name = "personal_signTypedData")] - fn sign_typed_data(&self, EIP712, H160, String) -> BoxFuture; - - /// Signs an arbitrary message based on the version specified - #[rpc(name = "personal_sign191")] - fn sign_191(&self, EIP191Version, Value, H160, String) -> BoxFuture; - - /// Returns the account associated with the private key that was used to calculate the signature in - /// `personal_sign`. - #[rpc(name = "personal_ecRecover")] - fn ec_recover(&self, Bytes, H520) -> BoxFuture; - - /// Signs transaction. The account is not unlocked in such case. - #[rpc(meta, name = "personal_signTransaction")] - fn sign_transaction(&self, Self::Metadata, TransactionRequest, String) -> BoxFuture; - - /// Sends transaction and signs it in single call. The account is not unlocked in such case. - #[rpc(meta, name = "personal_sendTransaction")] - fn send_transaction(&self, Self::Metadata, TransactionRequest, String) -> BoxFuture; - - /// @deprecated alias for `personal_sendTransaction`. - #[rpc(meta, name = "personal_signAndSendTransaction")] - fn sign_and_send_transaction(&self, Self::Metadata, TransactionRequest, String) -> BoxFuture; - - } +use jsonrpc_derive::rpc; +use v1::types::{Bytes, TransactionRequest, RichRawTransaction as RpcRichRawTransaction, EIP191Version}; + +/// Personal rpc interface. Safe (read-only) functions. +#[rpc] +pub trait Personal { + /// RPC Metadata + type Metadata; + + /// Lists all stored accounts + #[rpc(name = "personal_listAccounts")] + fn accounts(&self) -> Result>; + + /// Creates new account (it becomes new current unlocked account) + /// Param is the password for the account. + #[rpc(name = "personal_newAccount")] + fn new_account(&self, String) -> Result; + + /// Unlocks specified account for use (can only be one unlocked account at one moment) + #[rpc(name = "personal_unlockAccount")] + fn unlock_account(&self, H160, String, Option) -> Result; + + /// Signs the hash of data with given account signature using the given password to unlock the account during + /// the request. + #[rpc(name = "personal_sign")] + fn sign(&self, Bytes, H160, String) -> BoxFuture; + + /// Produces an EIP-712 compliant signature with given account using the given password to unlock the + /// account during the request. + #[rpc(name = "personal_signTypedData")] + fn sign_typed_data(&self, EIP712, H160, String) -> BoxFuture; + + /// Signs an arbitrary message based on the version specified + #[rpc(name = "personal_sign191")] + fn sign_191(&self, EIP191Version, Value, H160, String) -> BoxFuture; + + /// Returns the account associated with the private key that was used to calculate the signature in + /// `personal_sign`. + #[rpc(name = "personal_ecRecover")] + fn ec_recover(&self, Bytes, H520) -> BoxFuture; + + /// Signs transaction. The account is not unlocked in such case. + #[rpc(meta, name = "personal_signTransaction")] + fn sign_transaction(&self, Self::Metadata, TransactionRequest, String) -> BoxFuture; + + /// Sends transaction and signs it in single call. The account is not unlocked in such case. + #[rpc(meta, name = "personal_sendTransaction")] + fn send_transaction(&self, Self::Metadata, TransactionRequest, String) -> BoxFuture; + + /// @deprecated alias for `personal_sendTransaction`. + #[rpc(meta, name = "personal_signAndSendTransaction")] + fn sign_and_send_transaction(&self, Self::Metadata, TransactionRequest, String) -> BoxFuture; } diff --git a/rpc/src/v1/traits/private.rs b/rpc/src/v1/traits/private.rs index f7168c06c8..732e3914bd 100644 --- a/rpc/src/v1/traits/private.rs +++ b/rpc/src/v1/traits/private.rs @@ -16,30 +16,32 @@ //! SecretStore-specific rpc interface. +use ethereum_types::{H160, H256, U256}; use jsonrpc_core::Error; +use jsonrpc_derive::rpc; -use v1::types::{Bytes, PrivateTransactionReceipt, H160, H256, U256, BlockNumber, +use v1::types::{Bytes, PrivateTransactionReceipt, BlockNumber, PrivateTransactionReceiptAndTransaction, CallRequest}; -build_rpc_trait! { - /// Private transaction management RPC interface. - pub trait Private { - type Metadata; +/// Private transaction management RPC interface. +#[rpc] +pub trait Private { + /// RPC Metadata + type Metadata; - /// Sends private transaction; Transaction will be added to the validation queue and sent out when ready. - #[rpc(name = "private_sendTransaction")] - fn send_transaction(&self, Bytes) -> Result; + /// Sends private transaction; Transaction will be added to the validation queue and sent out when ready. + #[rpc(name = "private_sendTransaction")] + fn send_transaction(&self, Bytes) -> Result; - /// Creates a transaction for contract's deployment from origin (signed transaction) - #[rpc(name = "private_composeDeploymentTransaction")] - fn compose_deployment_transaction(&self, BlockNumber, Bytes, Vec, U256) -> Result; + /// Creates a transaction for contract's deployment from origin (signed transaction) + #[rpc(name = "private_composeDeploymentTransaction")] + fn compose_deployment_transaction(&self, BlockNumber, Bytes, Vec, U256) -> Result; - /// Make a call to the private contract - #[rpc(name = "private_call")] - fn private_call(&self, BlockNumber, CallRequest) -> Result; + /// Make a call to the private contract + #[rpc(name = "private_call")] + fn private_call(&self, BlockNumber, CallRequest) -> Result; - /// Retrieve the id of the key associated with the contract - #[rpc(name = "private_contractKey")] - fn private_contract_key(&self, H160) -> Result; - } + /// Retrieve the id of the key associated with the contract + #[rpc(name = "private_contractKey")] + fn private_contract_key(&self, H160) -> Result; } diff --git a/rpc/src/v1/traits/pubsub.rs b/rpc/src/v1/traits/pubsub.rs index 007e1dae40..c91b335613 100644 --- a/rpc/src/v1/traits/pubsub.rs +++ b/rpc/src/v1/traits/pubsub.rs @@ -17,23 +17,20 @@ //! Parity-specific PUB-SUB rpc interface. use jsonrpc_core::{Result, Value, Params}; -use jsonrpc_pubsub::SubscriptionId; -use jsonrpc_macros::Trailing; -use jsonrpc_macros::pubsub::Subscriber; - -build_rpc_trait! { - /// Parity-specific PUB-SUB rpc interface. - pub trait PubSub { - type Metadata; - - #[pubsub(name = "parity_subscription")] { - /// Subscribe to changes of any RPC method in Parity. - #[rpc(name = "parity_subscribe")] - fn parity_subscribe(&self, Self::Metadata, Subscriber, String, Trailing); - - /// Unsubscribe from existing Parity subscription. - #[rpc(name = "parity_unsubscribe")] - fn parity_unsubscribe(&self, SubscriptionId) -> Result; - } - } +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use jsonrpc_derive::rpc; + +/// Parity-specific PUB-SUB rpc interface. +#[rpc] +pub trait PubSub { + /// Pub/Sub Metadata + type Metadata; + + /// Subscribe to changes of any RPC method in Parity. + #[pubsub(subscription = "parity_subscription", subscribe, name = "parity_subscribe")] + fn parity_subscribe(&self, Self::Metadata, Subscriber, String, Option); + + /// Unsubscribe from existing Parity subscription. + #[pubsub(subscription = "parity_subscription", unsubscribe, name = "parity_unsubscribe")] + fn parity_unsubscribe(&self, Option, SubscriptionId) -> Result; } diff --git a/rpc/src/v1/traits/rpc.rs b/rpc/src/v1/traits/rpc.rs index 4ec58b2424..9600630fec 100644 --- a/rpc/src/v1/traits/rpc.rs +++ b/rpc/src/v1/traits/rpc.rs @@ -19,18 +19,18 @@ use std::collections::BTreeMap; use jsonrpc_core::Result; - -build_rpc_trait! { - /// RPC Interface. - pub trait Rpc { - /// Returns supported modules for Geth 1.3.6 - /// @ignore - #[rpc(name = "modules")] - fn modules(&self) -> Result>; - - /// Returns supported modules for Geth 1.4.0 - /// @ignore - #[rpc(name = "rpc_modules")] - fn rpc_modules(&self) -> Result>; - } +use jsonrpc_derive::rpc; + +/// RPC Interface. +#[rpc] +pub trait Rpc { + /// Returns supported modules for Geth 1.3.6 + /// @ignore + #[rpc(name = "modules")] + fn modules(&self) -> Result>; + + /// Returns supported modules for Geth 1.4.0 + /// @ignore + #[rpc(name = "rpc_modules")] + fn rpc_modules(&self) -> Result>; } diff --git a/rpc/src/v1/traits/secretstore.rs b/rpc/src/v1/traits/secretstore.rs index 0a5216c493..6883753b4f 100644 --- a/rpc/src/v1/traits/secretstore.rs +++ b/rpc/src/v1/traits/secretstore.rs @@ -17,44 +17,45 @@ //! SecretStore-specific rpc interface. use std::collections::BTreeSet; + use jsonrpc_core::Result; +use jsonrpc_derive::rpc; +use ethereum_types::{H160, H256, H512}; use ethkey::Password; - -use v1::types::{H160, H256, H512, Bytes, EncryptedDocumentKey}; - -build_rpc_trait! { - /// Parity-specific rpc interface. - pub trait SecretStore { - /// Generate document key to store in secret store. - /// Arguments: `account`, `password`, `server_key_public`. - #[rpc(name = "secretstore_generateDocumentKey")] - fn generate_document_key(&self, H160, Password, H512) -> Result; - - /// Encrypt data with key, received from secret store. - /// Arguments: `account`, `password`, `key`, `data`. - #[rpc(name = "secretstore_encrypt")] - fn encrypt(&self, H160, Password, Bytes, Bytes) -> Result; - - /// Decrypt data with key, received from secret store. - /// Arguments: `account`, `password`, `key`, `data`. - #[rpc(name = "secretstore_decrypt")] - fn decrypt(&self, H160, Password, Bytes, Bytes) -> Result; - - /// Decrypt data with shadow key, received from secret store. - /// Arguments: `account`, `password`, `decrypted_secret`, `common_point`, `decrypt_shadows`, `data`. - #[rpc(name = "secretstore_shadowDecrypt")] - fn shadow_decrypt(&self, H160, Password, H512, H512, Vec, Bytes) -> Result; - - /// Calculates the hash (keccak256) of servers set for using in ServersSetChange session. - /// Returned hash must be signed later by using `secretstore_signRawHash` method. - /// Arguments: `servers_set`. - #[rpc(name = "secretstore_serversSetHash")] - fn servers_set_hash(&self, BTreeSet) -> Result; - - /// Generate recoverable ECDSA signature of raw hash. - /// Passed hash is treated as an input to the `sign` function (no prefixes added, no hash function is applied). - /// Arguments: `account`, `password`, `raw_hash`. - #[rpc(name = "secretstore_signRawHash")] - fn sign_raw_hash(&self, H160, Password, H256) -> Result; - } +use v1::types::{Bytes, EncryptedDocumentKey}; + +/// Parity-specific rpc interface. +#[rpc] +pub trait SecretStore { + /// Generate document key to store in secret store. + /// Arguments: `account`, `password`, `server_key_public`. + #[rpc(name = "secretstore_generateDocumentKey")] + fn generate_document_key(&self, H160, Password, H512) -> Result; + + /// Encrypt data with key, received from secret store. + /// Arguments: `account`, `password`, `key`, `data`. + #[rpc(name = "secretstore_encrypt")] + fn encrypt(&self, H160, Password, Bytes, Bytes) -> Result; + + /// Decrypt data with key, received from secret store. + /// Arguments: `account`, `password`, `key`, `data`. + #[rpc(name = "secretstore_decrypt")] + fn decrypt(&self, H160, Password, Bytes, Bytes) -> Result; + + /// Decrypt data with shadow key, received from secret store. + /// Arguments: `account`, `password`, `decrypted_secret`, `common_point`, `decrypt_shadows`, `data`. + #[rpc(name = "secretstore_shadowDecrypt")] + fn shadow_decrypt(&self, H160, Password, H512, H512, Vec, Bytes) -> Result; + + /// Calculates the hash (keccak256) of servers set for using in ServersSetChange session. + /// Returned hash must be signed later by using `secretstore_signRawHash` method. + /// Arguments: `servers_set`. + #[rpc(name = "secretstore_serversSetHash")] + fn servers_set_hash(&self, BTreeSet) -> Result; + + /// Generate recoverable ECDSA signature of raw hash. + /// Passed hash is treated as an input to the `sign` function (no prefixes added, no hash function is applied). + /// Arguments: `account`, `password`, `raw_hash`. + #[rpc(name = "secretstore_signRawHash")] + fn sign_raw_hash(&self, H160, Password, H256) -> Result; } diff --git a/rpc/src/v1/traits/signer.rs b/rpc/src/v1/traits/signer.rs index afaba5ebec..b5653eba63 100644 --- a/rpc/src/v1/traits/signer.rs +++ b/rpc/src/v1/traits/signer.rs @@ -15,53 +15,49 @@ // along with Parity Ethereum. If not, see . //! Parity Signer-related rpc interface. -use jsonrpc_core::{BoxFuture, Result}; -use jsonrpc_pubsub::SubscriptionId; -use jsonrpc_macros::pubsub::Subscriber; -use v1::types::{U256, Bytes, TransactionModification, ConfirmationRequest, ConfirmationResponse, ConfirmationResponseWithToken}; +use ethereum_types::U256; +use jsonrpc_core::{BoxFuture, Result}; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use jsonrpc_derive::rpc; -build_rpc_trait! { - /// Signer extension for confirmations rpc interface. - pub trait Signer { - type Metadata; +use v1::types::{Bytes, TransactionModification, ConfirmationRequest, ConfirmationResponse, ConfirmationResponseWithToken}; - /// Returns a list of items to confirm. - #[rpc(name = "signer_requestsToConfirm")] - fn requests_to_confirm(&self) -> Result>; +/// Signer extension for confirmations rpc interface. +#[rpc] +pub trait Signer { + /// RPC Metadata + type Metadata; - /// Confirm specific request. - #[rpc(name = "signer_confirmRequest")] - fn confirm_request(&self, U256, TransactionModification, String) -> BoxFuture; + /// Returns a list of items to confirm. + #[rpc(name = "signer_requestsToConfirm")] + fn requests_to_confirm(&self) -> Result>; - /// Confirm specific request with token. - #[rpc(name = "signer_confirmRequestWithToken")] - fn confirm_request_with_token(&self, U256, TransactionModification, String) -> BoxFuture; + /// Confirm specific request. + #[rpc(name = "signer_confirmRequest")] + fn confirm_request(&self, U256, TransactionModification, String) -> BoxFuture; - /// Confirm specific request with already signed data. - #[rpc(name = "signer_confirmRequestRaw")] - fn confirm_request_raw(&self, U256, Bytes) -> Result; + /// Confirm specific request with token. + #[rpc(name = "signer_confirmRequestWithToken")] + fn confirm_request_with_token(&self, U256, TransactionModification, String) -> BoxFuture; - /// Reject the confirmation request. - #[rpc(name = "signer_rejectRequest")] - fn reject_request(&self, U256) -> Result; + /// Confirm specific request with already signed data. + #[rpc(name = "signer_confirmRequestRaw")] + fn confirm_request_raw(&self, U256, Bytes) -> Result; - /// Generates new authorization token. - #[rpc(name = "signer_generateAuthorizationToken")] - fn generate_token(&self) -> Result; + /// Reject the confirmation request. + #[rpc(name = "signer_rejectRequest")] + fn reject_request(&self, U256) -> Result; - /// Generates new web proxy access token for particular domain. - #[rpc(name = "signer_generateWebProxyAccessToken")] - fn generate_web_proxy_token(&self, String) -> Result; + /// Generates new authorization token. + #[rpc(name = "signer_generateAuthorizationToken")] + fn generate_token(&self) -> Result; - #[pubsub(name = "signer_pending")] { - /// Subscribe to new pending requests on signer interface. - #[rpc(name = "signer_subscribePending")] - fn subscribe_pending(&self, Self::Metadata, Subscriber>); + /// Subscribe to new pending requests on signer interface. + #[pubsub(subscription = "signer_pending", subscribe, name = "signer_subscribePending")] + fn subscribe_pending(&self, Self::Metadata, Subscriber>); - /// Unsubscribe from pending requests subscription. - #[rpc(name = "signer_unsubscribePending")] - fn unsubscribe_pending(&self, SubscriptionId) -> Result; - } - } + /// Unsubscribe from pending requests subscription. + #[pubsub(subscription = "signer_pending", unsubscribe, name = "signer_unsubscribePending")] + fn unsubscribe_pending(&self, Option, SubscriptionId) -> Result; } diff --git a/rpc/src/v1/traits/traces.rs b/rpc/src/v1/traits/traces.rs index f6efae7395..5308ed4c6c 100644 --- a/rpc/src/v1/traits/traces.rs +++ b/rpc/src/v1/traits/traces.rs @@ -16,49 +16,51 @@ //! Traces specific rpc interface. +use ethereum_types::H256; use jsonrpc_core::Result; -use jsonrpc_macros::Trailing; -use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, TraceResultsWithTransactionHash, H256, TraceOptions}; +use jsonrpc_derive::rpc; +use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, + TraceResultsWithTransactionHash, TraceOptions}; -build_rpc_trait! { - /// Traces specific rpc interface. - pub trait Traces { - type Metadata; +/// Traces specific rpc interface. +#[rpc] +pub trait Traces { + /// RPC Metadata + type Metadata; - /// Returns traces matching given filter. - #[rpc(name = "trace_filter")] - fn filter(&self, TraceFilter) -> Result>>; + /// Returns traces matching given filter. + #[rpc(name = "trace_filter")] + fn filter(&self, TraceFilter) -> Result>>; - /// Returns transaction trace at given index. - #[rpc(name = "trace_get")] - fn trace(&self, H256, Vec) -> Result>; + /// Returns transaction trace at given index. + #[rpc(name = "trace_get")] + fn trace(&self, H256, Vec) -> Result>; - /// Returns all traces of given transaction. - #[rpc(name = "trace_transaction")] - fn transaction_traces(&self, H256) -> Result>>; + /// Returns all traces of given transaction. + #[rpc(name = "trace_transaction")] + fn transaction_traces(&self, H256) -> Result>>; - /// Returns all traces produced at given block. - #[rpc(name = "trace_block")] - fn block_traces(&self, BlockNumber) -> Result>>; + /// Returns all traces produced at given block. + #[rpc(name = "trace_block")] + fn block_traces(&self, BlockNumber) -> Result>>; - /// Executes the given call and returns a number of possible traces for it. - #[rpc(name = "trace_call")] - fn call(&self, CallRequest, TraceOptions, Trailing) -> Result; + /// Executes the given call and returns a number of possible traces for it. + #[rpc(name = "trace_call")] + fn call(&self, CallRequest, TraceOptions, Option) -> Result; - /// Executes all given calls and returns a number of possible traces for each of it. - #[rpc(name = "trace_callMany")] - fn call_many(&self, Vec<(CallRequest, TraceOptions)>, Trailing) -> Result>; + /// Executes all given calls and returns a number of possible traces for each of it. + #[rpc(name = "trace_callMany")] + fn call_many(&self, Vec<(CallRequest, TraceOptions)>, Option) -> Result>; - /// Executes the given raw transaction and returns a number of possible traces for it. - #[rpc(name = "trace_rawTransaction")] - fn raw_transaction(&self, Bytes, TraceOptions, Trailing) -> Result; + /// Executes the given raw transaction and returns a number of possible traces for it. + #[rpc(name = "trace_rawTransaction")] + fn raw_transaction(&self, Bytes, TraceOptions, Option) -> Result; - /// Executes the transaction with the given hash and returns a number of possible traces for it. - #[rpc(name = "trace_replayTransaction")] - fn replay_transaction(&self, H256, TraceOptions) -> Result; + /// Executes the transaction with the given hash and returns a number of possible traces for it. + #[rpc(name = "trace_replayTransaction")] + fn replay_transaction(&self, H256, TraceOptions) -> Result; - /// Executes all the transactions at the given block and returns a number of possible traces for each transaction. - #[rpc(name = "trace_replayBlockTransactions")] - fn replay_block_transactions(&self, BlockNumber, TraceOptions) -> Result>; - } + /// Executes all the transactions at the given block and returns a number of possible traces for each transaction. + #[rpc(name = "trace_replayBlockTransactions")] + fn replay_block_transactions(&self, BlockNumber, TraceOptions) -> Result>; } diff --git a/rpc/src/v1/traits/web3.rs b/rpc/src/v1/traits/web3.rs index e50c0963a6..dd464ee1c2 100644 --- a/rpc/src/v1/traits/web3.rs +++ b/rpc/src/v1/traits/web3.rs @@ -15,19 +15,20 @@ // along with Parity Ethereum. If not, see . //! Web3 rpc interface. +use ethereum_types::H256; use jsonrpc_core::Result; +use jsonrpc_derive::rpc; -use v1::types::{H256, Bytes}; +use v1::types::Bytes; -build_rpc_trait! { - /// Web3 rpc interface. - pub trait Web3 { - /// Returns current client version. - #[rpc(name = "web3_clientVersion")] - fn client_version(&self) -> Result; +/// Web3 rpc interface. +#[rpc] +pub trait Web3 { + /// Returns current client version. + #[rpc(name = "web3_clientVersion")] + fn client_version(&self) -> Result; - /// Returns sha3 of the given data - #[rpc(name = "web3_sha3")] - fn sha3(&self, Bytes) -> Result; - } + /// Returns sha3 of the given data + #[rpc(name = "web3_sha3")] + fn sha3(&self, Bytes) -> Result; } diff --git a/rpc/src/v1/types/account_info.rs b/rpc/src/v1/types/account_info.rs index a35537b029..6d7585f87f 100644 --- a/rpc/src/v1/types/account_info.rs +++ b/rpc/src/v1/types/account_info.rs @@ -16,8 +16,8 @@ //! Return types for RPC calls -use ethereum_types::{Public, Address}; -use v1::types::{H160, H256, U256, Bytes}; +use ethereum_types::{Public, Address, H160, H256, U256}; +use v1::types::Bytes; /// Account information. #[derive(Debug, Default, Clone, PartialEq, Serialize)] diff --git a/rpc/src/v1/types/block.rs b/rpc/src/v1/types/block.rs index b3a6018f67..61f4402af0 100644 --- a/rpc/src/v1/types/block.rs +++ b/rpc/src/v1/types/block.rs @@ -17,11 +17,11 @@ use std::ops::Deref; use std::collections::BTreeMap; +use ethereum_types::{H160, H256, U256, Bloom as H2048}; use serde::ser::Error; use serde::{Serialize, Serializer}; use types::encoded::Header as EthHeader; - -use v1::types::{Bytes, Transaction, H160, H256, H2048, U256}; +use v1::types::{Bytes, Transaction}; /// Block Transactions #[derive(Debug)] @@ -139,21 +139,21 @@ impl From for Header { impl<'a> From<&'a EthHeader> for Header { fn from(h: &'a EthHeader) -> Self { Header { - hash: Some(h.hash().into()), + hash: Some(h.hash()), size: Some(h.rlp().as_raw().len().into()), - parent_hash: h.parent_hash().into(), - uncles_hash: h.uncles_hash().into(), - author: h.author().into(), - miner: h.author().into(), - state_root: h.state_root().into(), - transactions_root: h.transactions_root().into(), - receipts_root: h.receipts_root().into(), + parent_hash: h.parent_hash(), + uncles_hash: h.uncles_hash(), + author: h.author(), + miner: h.author(), + state_root: h.state_root(), + transactions_root: h.transactions_root(), + receipts_root: h.receipts_root(), number: Some(h.number().into()), - gas_used: h.gas_used().into(), - gas_limit: h.gas_limit().into(), - logs_bloom: h.log_bloom().into(), + gas_used: h.gas_used(), + gas_limit: h.gas_limit(), + logs_bloom: h.log_bloom(), timestamp: h.timestamp().into(), - difficulty: h.difficulty().into(), + difficulty: h.difficulty(), extra_data: h.extra_data().into(), seal_fields: h.view().decode_seal() .expect("Client/Miner returns only valid headers. We only serialize headers from Client/Miner; qed") @@ -205,8 +205,9 @@ impl Serialize for Rich { #[cfg(test)] mod tests { use std::collections::BTreeMap; + use ethereum_types::{H64, H160, H256, U256, Bloom as H2048}; use serde_json; - use v1::types::{Transaction, H64, H160, H256, H2048, Bytes, U256}; + use v1::types::{Transaction, Bytes}; use super::{Block, RichBlock, BlockTransactions, Header, RichHeader}; #[test] @@ -248,8 +249,8 @@ mod tests { let rich_block = RichBlock { inner: block, extra_info: map![ - "mixHash".into() => format!("0x{:?}", H256::default()), - "nonce".into() => format!("0x{:?}", H64::default()) + "mixHash".into() => format!("{:?}", H256::default()), + "nonce".into() => format!("{:?}", H64::default()) ], }; let serialized_rich_block = serde_json::to_string(&rich_block).unwrap(); @@ -286,8 +287,8 @@ mod tests { let rich_block = RichBlock { inner: block, extra_info: map![ - "mixHash".into() => format!("0x{:?}", H256::default()), - "nonce".into() => format!("0x{:?}", H64::default()) + "mixHash".into() => format!("{:?}", H256::default()), + "nonce".into() => format!("{:?}", H64::default()) ], }; let serialized_rich_block = serde_json::to_string(&rich_block).unwrap(); @@ -321,8 +322,8 @@ mod tests { let rich_header = RichHeader { inner: header, extra_info: map![ - "mixHash".into() => format!("0x{:?}", H256::default()), - "nonce".into() => format!("0x{:?}", H64::default()) + "mixHash".into() => format!("{:?}", H256::default()), + "nonce".into() => format!("{:?}", H64::default()) ], }; let serialized_rich_header = serde_json::to_string(&rich_header).unwrap(); diff --git a/rpc/src/v1/types/block_number.rs b/rpc/src/v1/types/block_number.rs index 64b100d5aa..7e19f2d3d9 100644 --- a/rpc/src/v1/types/block_number.rs +++ b/rpc/src/v1/types/block_number.rs @@ -107,7 +107,7 @@ impl<'a> Visitor<'a> for BlockNumberVisitor { _ if value.starts_with("0x") => u64::from_str_radix(&value[2..], 16).map(BlockNumber::Num).map_err(|e| { Error::custom(format!("Invalid block number: {}", e)) }), - _ => Err(Error::custom(format!("Invalid block number: missing 0x prefix"))), + _ => Err(Error::custom("Invalid block number: missing 0x prefix".to_string())), } } diff --git a/rpc/src/v1/types/call_request.rs b/rpc/src/v1/types/call_request.rs index c265731509..d75e4b1a2d 100644 --- a/rpc/src/v1/types/call_request.rs +++ b/rpc/src/v1/types/call_request.rs @@ -14,8 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +use ethereum_types::{H160, U256}; use v1::helpers::CallRequest as Request; -use v1::types::{Bytes, H160, U256}; +use v1::types::Bytes; /// Call request #[derive(Debug, Default, PartialEq, Deserialize)] @@ -57,7 +58,7 @@ mod tests { use std::str::FromStr; use rustc_hex::FromHex; use serde_json; - use v1::types::{U256, H160}; + use ethereum_types::{U256, H160}; use super::CallRequest; #[test] diff --git a/rpc/src/v1/types/confirmations.rs b/rpc/src/v1/types/confirmations.rs index 2a62e2cfae..dedd0ba253 100644 --- a/rpc/src/v1/types/confirmations.rs +++ b/rpc/src/v1/types/confirmations.rs @@ -21,7 +21,8 @@ use serde::{Serialize, Serializer}; use ansi_term::Colour; use bytes::ToPretty; -use v1::types::{U256, TransactionRequest, RichRawTransaction, H160, H256, H520, Bytes, TransactionCondition, Origin}; +use ethereum_types::{H160, H256, H520, U256}; +use v1::types::{TransactionRequest, RichRawTransaction, Bytes, TransactionCondition, Origin}; use v1::helpers; use ethkey::Password; @@ -40,7 +41,7 @@ pub struct ConfirmationRequest { impl From for ConfirmationRequest { fn from(c: helpers::ConfirmationRequest) -> Self { ConfirmationRequest { - id: c.id.into(), + id: c.id, payload: c.payload.into(), origin: c.origin, } @@ -213,15 +214,15 @@ impl From for ConfirmationPayload { helpers::ConfirmationPayload::SendTransaction(t) => ConfirmationPayload::SendTransaction(t.into()), helpers::ConfirmationPayload::SignTransaction(t) => ConfirmationPayload::SignTransaction(t.into()), helpers::ConfirmationPayload::EthSignMessage(address, data) => ConfirmationPayload::EthSignMessage(EthSignRequest { - address: address.into(), + address, data: data.into(), }), helpers::ConfirmationPayload::SignMessage(address, data) => ConfirmationPayload::EIP191SignMessage(EIP191SignRequest { - address: address.into(), - data: data.into(), + address, + data, }), helpers::ConfirmationPayload::Decrypt(address, msg) => ConfirmationPayload::Decrypt(DecryptRequest { - address: address.into(), + address, msg: msg.into(), }), } @@ -281,8 +282,9 @@ impl Serialize for Either where #[cfg(test)] mod tests { use std::str::FromStr; + use ethereum_types::{H256, U256}; use serde_json; - use v1::types::{U256, H256, TransactionCondition}; + use v1::types::TransactionCondition; use v1::helpers; use super::*; diff --git a/rpc/src/v1/types/consensus_status.rs b/rpc/src/v1/types/consensus_status.rs index 15047ed051..da2aa26a1d 100644 --- a/rpc/src/v1/types/consensus_status.rs +++ b/rpc/src/v1/types/consensus_status.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +use ethereum_types::{H160, H256}; use semver; -use v1::types::{H160, H256}; use updater::{self, CapState}; /// Capability info @@ -109,7 +109,7 @@ impl Into for updater::VersionInfo { VersionInfo { track: self.track.into(), version: self.version.into(), - hash: self.hash.into(), + hash: self.hash, } } } diff --git a/rpc/src/v1/types/derivation.rs b/rpc/src/v1/types/derivation.rs index a2947a89f7..1f2764d9ff 100644 --- a/rpc/src/v1/types/derivation.rs +++ b/rpc/src/v1/types/derivation.rs @@ -18,10 +18,9 @@ use std::fmt; use serde::{Deserialize, Deserializer}; use serde::de::{Error, Visitor}; +use ethereum_types::H256; use ethstore; -use super::hash::H256; - /// Type of derivation pub enum DerivationType { /// Soft - allow proof of parent @@ -70,6 +69,7 @@ impl From for Derive { } /// Error converting request data +#[cfg(any(test, feature = "accounts"))] #[derive(Debug)] pub enum ConvertError { IndexOverlfow(u64), @@ -77,6 +77,7 @@ pub enum ConvertError { impl Derive { /// Convert to account provider struct dealing with possible overflows + #[cfg(any(test, feature = "accounts"))] pub fn to_derivation(self) -> Result { Ok(match self { Derive::Hierarchical(drv) => { diff --git a/rpc/src/v1/types/eip191.rs b/rpc/src/v1/types/eip191.rs index 16b8536bf8..fe3aab4c51 100644 --- a/rpc/src/v1/types/eip191.rs +++ b/rpc/src/v1/types/eip191.rs @@ -15,9 +15,11 @@ // along with Parity Ethereum. If not, see . //! EIP-191 specific types + +use ethereum_types::H160; use serde::{Deserialize, Deserializer}; use serde::de; -use v1::types::{H160, Bytes}; +use v1::types::Bytes; /// EIP-191 version specifier #[derive(Debug)] diff --git a/rpc/src/v1/types/eth_types.rs b/rpc/src/v1/types/eth_types.rs new file mode 100644 index 0000000000..606e759248 --- /dev/null +++ b/rpc/src/v1/types/eth_types.rs @@ -0,0 +1,84 @@ +use ethereum_types::{H256, U256}; +use serde_json; + +type Res = Result; + +#[test] +fn should_serialize_u256() { + let serialized1 = serde_json::to_string(&U256::from(0)).unwrap(); + let serialized2 = serde_json::to_string(&U256::from(1)).unwrap(); + let serialized3 = serde_json::to_string(&U256::from(16)).unwrap(); + let serialized4 = serde_json::to_string(&U256::from(256)).unwrap(); + + assert_eq!(serialized1, r#""0x0""#); + assert_eq!(serialized2, r#""0x1""#); + assert_eq!(serialized3, r#""0x10""#); + assert_eq!(serialized4, r#""0x100""#); +} + +#[test] +fn should_serialize_h256() { + let serialized1 = serde_json::to_string(&H256::from(0)).unwrap(); + let serialized2 = serde_json::to_string(&H256::from(1)).unwrap(); + let serialized3 = serde_json::to_string(&H256::from(16)).unwrap(); + let serialized4 = serde_json::to_string(&H256::from(256)).unwrap(); + + assert_eq!(serialized1, r#""0x0000000000000000000000000000000000000000000000000000000000000000""#); + assert_eq!(serialized2, r#""0x0000000000000000000000000000000000000000000000000000000000000001""#); + assert_eq!(serialized3, r#""0x0000000000000000000000000000000000000000000000000000000000000010""#); + assert_eq!(serialized4, r#""0x0000000000000000000000000000000000000000000000000000000000000100""#); +} + +#[test] +fn should_fail_to_deserialize_decimals() { + let deserialized0: Res = serde_json::from_str(r#""∀∂""#); + let deserialized1: Res = serde_json::from_str(r#""""#); + let deserialized2: Res = serde_json::from_str(r#""0""#); + let deserialized3: Res = serde_json::from_str(r#""10""#); + let deserialized4: Res = serde_json::from_str(r#""1000000""#); + let deserialized5: Res = serde_json::from_str(r#""1000000000000000000""#); + let deserialized6: Res = serde_json::from_str(r#""0x""#); + + assert!(deserialized0.is_err()); + assert!(deserialized1.is_err()); + assert!(deserialized2.is_err()); + assert!(deserialized3.is_err()); + assert!(deserialized4.is_err()); + assert!(deserialized5.is_err()); + assert!(deserialized6.is_err(), "Quantities should represent zero as 0x0"); +} + +#[test] +fn should_fail_to_deserialize_bad_hex_strings() { + let deserialized1: Result = serde_json::from_str(r#""0""#); + let deserialized2: Result = serde_json::from_str(r#""0x""#); + let deserialized3: Result = serde_json::from_str(r#""0x∀∂0000000000000000000000000000000000000000000000000000000000""#); + + assert!(deserialized1.is_err(), "hex string should start with 0x"); + assert!(deserialized2.is_err(), "0x-prefixed hex string of length 64"); + assert!(deserialized3.is_err(), "hex string should only contain hex chars"); +} + +#[test] +fn should_deserialize_u256() { + let deserialized1: U256 = serde_json::from_str(r#""0x0""#).unwrap(); + let deserialized2: U256 = serde_json::from_str(r#""0x1""#).unwrap(); + let deserialized3: U256 = serde_json::from_str(r#""0x01""#).unwrap(); + let deserialized4: U256 = serde_json::from_str(r#""0x100""#).unwrap(); + + assert_eq!(deserialized1, 0.into()); + assert_eq!(deserialized2, 1.into()); + assert_eq!(deserialized3, 1.into()); + assert_eq!(deserialized4, 256.into()); +} + +#[test] +fn should_deserialize_h256() { + let deserialized1: H256 = serde_json::from_str(r#""0x0000000000000000000000000000000000000000000000000000000000000000""#).unwrap(); + let deserialized2: H256 = serde_json::from_str(r#""0x0000000000000000000000000000000000000000000000000000000000000001""#).unwrap(); + let deserialized3: H256 = serde_json::from_str(r#""0x0000000000000000000000000000000000000000000000000000000000000100""#).unwrap(); + + assert_eq!(deserialized1, 0.into()); + assert_eq!(deserialized2, 1.into()); + assert_eq!(deserialized3, 256.into()); +} diff --git a/rpc/src/v1/types/filter.rs b/rpc/src/v1/types/filter.rs index dfcf78acf4..ec9f541797 100644 --- a/rpc/src/v1/types/filter.rs +++ b/rpc/src/v1/types/filter.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +use ethereum_types::{H160, H256}; use jsonrpc_core::{Error as RpcError}; use serde::de::{Error, DeserializeOwned}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -21,7 +22,7 @@ use serde_json::{Value, from_value}; use types::filter::Filter as EthFilter; use types::ids::BlockId; -use v1::types::{BlockNumber, H160, H256, Log}; +use v1::types::{BlockNumber, Log}; use v1::helpers::errors::invalid_params; /// Variadic value @@ -87,10 +88,7 @@ impl Filter { }; let (from_block, to_block) = match self.block_hash { - Some(hash) => { - let hash = hash.into(); - (BlockId::Hash(hash), BlockId::Hash(hash)) - }, + Some(hash) => (BlockId::Hash(hash), BlockId::Hash(hash)), None => (self.from_block.map_or_else(|| BlockId::Latest, &num_to_id), self.to_block.map_or_else(|| BlockId::Latest, &num_to_id)), @@ -100,14 +98,14 @@ impl Filter { from_block, to_block, address: self.address.and_then(|address| match address { VariadicValue::Null => None, - VariadicValue::Single(a) => Some(vec![a.into()]), - VariadicValue::Multiple(a) => Some(a.into_iter().map(Into::into).collect()) + VariadicValue::Single(a) => Some(vec![a]), + VariadicValue::Multiple(a) => Some(a) }), topics: { let mut iter = self.topics.map_or_else(Vec::new, |topics| topics.into_iter().take(4).map(|topic| match topic { VariadicValue::Null => None, - VariadicValue::Single(t) => Some(vec![t.into()]), - VariadicValue::Multiple(t) => Some(t.into_iter().map(Into::into).collect()) + VariadicValue::Single(t) => Some(vec![t]), + VariadicValue::Multiple(t) => Some(t) }).collect()).into_iter(); vec![ diff --git a/rpc/src/v1/types/hash.rs b/rpc/src/v1/types/hash.rs deleted file mode 100644 index 6cdaccf43b..0000000000 --- a/rpc/src/v1/types/hash.rs +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -use std::fmt; -use std::str::FromStr; -use std::cmp::Ordering; -use std::hash::{Hash, Hasher}; -use serde; -use rustc_hex::{ToHex, FromHex}; -use ethereum_types::{H64 as Eth64, H160 as Eth160, H256 as Eth256, H520 as Eth520, H512 as Eth512, Bloom as Eth2048}; - -macro_rules! impl_hash { - ($name: ident, $other: ident, $size: expr) => { - /// Hash serialization - pub struct $name(pub [u8; $size]); - - impl Eq for $name { } - - impl Default for $name { - fn default() -> Self { - $name([0; $size]) - } - } - - impl fmt::Debug for $name { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.0.to_hex()) - } - } - - impl fmt::Display for $name { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let hex = self.0.to_hex(); - write!(f, "{}..{}", &hex[0..2], &hex[$size-2..$size]) - } - } - - impl From for $name where $other: From { - fn from(o: T) -> Self { - $name($other::from(o).0) - } - } - - impl FromStr for $name { - type Err = <$other as FromStr>::Err; - - fn from_str(s: &str) -> Result { - $other::from_str(s).map(|x| $name(x.0)) - } - } - - impl Into<$other> for $name { - fn into(self) -> $other { - $other(self.0) - } - } - - impl PartialEq for $name { - fn eq(&self, other: &Self) -> bool { - let self_ref: &[u8] = &self.0; - let other_ref: &[u8] = &other.0; - self_ref == other_ref - } - } - - impl PartialOrd for $name { - fn partial_cmp(&self, other: &Self) -> Option { - let self_ref: &[u8] = &self.0; - let other_ref: &[u8] = &other.0; - self_ref.partial_cmp(other_ref) - } - } - - impl Ord for $name { - fn cmp(&self, other: &Self) -> Ordering { - let self_ref: &[u8] = &self.0; - let other_ref: &[u8] = &other.0; - self_ref.cmp(other_ref) - } - } - - impl Hash for $name { - fn hash(&self, state: &mut H) where H: Hasher { - let self_ref: &[u8] = &self.0; - Hash::hash(self_ref, state) - } - } - - impl Clone for $name { - fn clone(&self) -> Self { - let mut r = [0; $size]; - r.copy_from_slice(&self.0); - $name(r) - } - } - - impl serde::Serialize for $name { - fn serialize(&self, serializer: S) -> Result - where S: serde::Serializer { - let mut hex = "0x".to_owned(); - hex.push_str(&self.0.to_hex()); - serializer.serialize_str(&hex) - } - } - - impl<'a> serde::Deserialize<'a> for $name { - fn deserialize(deserializer: D) -> Result<$name, D::Error> where D: serde::Deserializer<'a> { - struct HashVisitor; - - impl<'b> serde::de::Visitor<'b> for HashVisitor { - type Value = $name; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a 0x-prefixed, padded, hex-encoded hash with length {}", $size * 2) - } - - fn visit_str(self, value: &str) -> Result where E: serde::de::Error { - - if value.len() < 2 || !value.starts_with("0x") { - return Err(E::custom("expected a hex-encoded hash with 0x prefix")); - } - if value.len() != 2 + $size * 2 { - return Err(E::invalid_length(value.len() - 2, &self)); - } - - match value[2..].from_hex() { - Ok(ref v) => { - let mut result = [0u8; $size]; - result.copy_from_slice(v); - Ok($name(result)) - }, - Err(e) => Err(E::custom(format!("invalid hex value: {:?}", e))), - } - } - - fn visit_string(self, value: String) -> Result where E: serde::de::Error { - self.visit_str(value.as_ref()) - } - } - - deserializer.deserialize_any(HashVisitor) - } - } - } -} - -impl_hash!(H64, Eth64, 8); -impl_hash!(H160, Eth160, 20); -impl_hash!(H256, Eth256, 32); -impl_hash!(H512, Eth512, 64); -impl_hash!(H520, Eth520, 65); -impl_hash!(H2048, Eth2048, 256); diff --git a/rpc/src/v1/types/histogram.rs b/rpc/src/v1/types/histogram.rs index 5b7ab1bb68..d7f14c514e 100644 --- a/rpc/src/v1/types/histogram.rs +++ b/rpc/src/v1/types/histogram.rs @@ -16,7 +16,7 @@ //! Gas prices histogram. -use v1::types::U256; +use ethereum_types::U256; /// Values of RPC settings. #[derive(Serialize, Deserialize)] diff --git a/rpc/src/v1/types/log.rs b/rpc/src/v1/types/log.rs index dd8f3d31cc..57b2cdd5dc 100644 --- a/rpc/src/v1/types/log.rs +++ b/rpc/src/v1/types/log.rs @@ -14,8 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +use ethereum_types::{H160, H256, U256}; use types::log_entry::{LocalizedLogEntry, LogEntry}; -use v1::types::{Bytes, H160, H256, U256}; +use v1::types::Bytes; /// Log #[derive(Debug, Serialize, PartialEq, Eq, Hash, Clone)] @@ -50,12 +51,12 @@ pub struct Log { impl From for Log { fn from(e: LocalizedLogEntry) -> Log { Log { - address: e.entry.address.into(), + address: e.entry.address, topics: e.entry.topics.into_iter().map(Into::into).collect(), data: e.entry.data.into(), - block_hash: Some(e.block_hash.into()), + block_hash: Some(e.block_hash), block_number: Some(e.block_number.into()), - transaction_hash: Some(e.transaction_hash.into()), + transaction_hash: Some(e.transaction_hash), transaction_index: Some(e.transaction_index.into()), log_index: Some(e.log_index.into()), transaction_log_index: Some(e.transaction_log_index.into()), @@ -68,7 +69,7 @@ impl From for Log { impl From for Log { fn from(e: LogEntry) -> Log { Log { - address: e.address.into(), + address: e.address, topics: e.topics.into_iter().map(Into::into).collect(), data: e.data.into(), block_hash: None, @@ -87,7 +88,8 @@ impl From for Log { mod tests { use serde_json; use std::str::FromStr; - use v1::types::{Log, H160, H256, U256}; + use v1::types::Log; + use ethereum_types::{H160, H256, U256}; #[test] fn log_serialization() { diff --git a/rpc/src/v1/types/mod.rs b/rpc/src/v1/types/mod.rs index 9859bc909d..a41f49fab1 100644 --- a/rpc/src/v1/types/mod.rs +++ b/rpc/src/v1/types/mod.rs @@ -16,6 +16,9 @@ //! RPC types +#[cfg(test)] +mod eth_types; + mod account_info; mod block; mod block_number; @@ -25,7 +28,6 @@ mod confirmations; mod consensus_status; mod derivation; mod filter; -mod hash; mod histogram; mod index; mod log; @@ -40,7 +42,6 @@ mod trace_filter; mod transaction; mod transaction_request; mod transaction_condition; -mod uint; mod work; mod private_receipt; mod eip191; @@ -60,7 +61,6 @@ pub use self::confirmations::{ pub use self::consensus_status::*; pub use self::derivation::{DeriveHash, DeriveHierarchical, Derive}; pub use self::filter::{Filter, FilterChanges}; -pub use self::hash::{H64, H160, H256, H512, H520, H2048}; pub use self::histogram::Histogram; pub use self::index::Index; pub use self::log::Log; @@ -78,7 +78,6 @@ pub use self::trace_filter::TraceFilter; pub use self::transaction::{Transaction, RichRawTransaction, LocalTransactionStatus}; pub use self::transaction_request::TransactionRequest; pub use self::transaction_condition::TransactionCondition; -pub use self::uint::{U128, U256, U64}; pub use self::work::Work; pub use self::private_receipt::{PrivateTransactionReceipt, PrivateTransactionReceiptAndTransaction}; diff --git a/rpc/src/v1/types/private_receipt.rs b/rpc/src/v1/types/private_receipt.rs index a9e1eef01e..68e9e716f9 100644 --- a/rpc/src/v1/types/private_receipt.rs +++ b/rpc/src/v1/types/private_receipt.rs @@ -14,8 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use v1::types::{H160, H256, TransactionRequest}; use ethcore_private_tx::{Receipt as EthPrivateReceipt}; +use ethereum_types::{H160, H256}; +use v1::types::TransactionRequest; /// Receipt #[derive(Debug, Serialize)] @@ -24,7 +25,7 @@ pub struct PrivateTransactionReceipt { /// Transaction Hash pub transaction_hash: H256, /// Private contract address - pub contract_address: Option, + pub contract_address: H160, /// Status code #[serde(rename = "status")] pub status_code: u8, @@ -33,9 +34,9 @@ pub struct PrivateTransactionReceipt { impl From for PrivateTransactionReceipt { fn from(r: EthPrivateReceipt) -> Self { PrivateTransactionReceipt { - transaction_hash: r.hash.into(), - contract_address: r.contract_address.map(Into::into), - status_code: r.status_code.into(), + transaction_hash: r.hash, + contract_address: r.contract_address, + status_code: r.status_code, } } } diff --git a/rpc/src/v1/types/provenance.rs b/rpc/src/v1/types/provenance.rs index 2d9301b49e..dcdd2408fe 100644 --- a/rpc/src/v1/types/provenance.rs +++ b/rpc/src/v1/types/provenance.rs @@ -17,7 +17,7 @@ //! Request Provenance use std::fmt; -use v1::types::H256; +use ethereum_types::H256; /// RPC request origin #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] diff --git a/rpc/src/v1/types/pubsub.rs b/rpc/src/v1/types/pubsub.rs index 179ee0e5c3..1586b115c3 100644 --- a/rpc/src/v1/types/pubsub.rs +++ b/rpc/src/v1/types/pubsub.rs @@ -16,18 +16,19 @@ //! Pub-Sub types. +use ethereum_types::H256; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::de::Error; use serde_json::{Value, from_value}; -use v1::types::{RichHeader, Filter, Log, H256}; +use v1::types::{RichHeader, Filter, Log}; /// Subscription result. #[derive(Debug, Clone, PartialEq, Eq)] pub enum Result { /// New block header. - Header(RichHeader), + Header(Box), /// Log - Log(Log), + Log(Box), /// Transaction hash TransactionHash(H256), } @@ -143,7 +144,7 @@ mod tests { #[test] fn should_serialize_header() { - let header = Result::Header(RichHeader { + let header = Result::Header(Box::new(RichHeader { extra_info: Default::default(), inner: Header { hash: Some(Default::default()), @@ -164,7 +165,7 @@ mod tests { seal_fields: vec![Default::default(), Default::default()], size: Some(69.into()), }, - }); + })); let expected = r#"{"author":"0x0000000000000000000000000000000000000000","difficulty":"0x0","extraData":"0x","gasLimit":"0x0","gasUsed":"0x0","hash":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","number":"0x0","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","sealFields":["0x","0x"],"sha3Uncles":"0x0000000000000000000000000000000000000000000000000000000000000000","size":"0x45","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","timestamp":"0x0","transactionsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000"}"#; assert_eq!(serde_json::to_string(&header).unwrap(), expected); } diff --git a/rpc/src/v1/types/receipt.rs b/rpc/src/v1/types/receipt.rs index f57c988ffe..f492ca98c5 100644 --- a/rpc/src/v1/types/receipt.rs +++ b/rpc/src/v1/types/receipt.rs @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use v1::types::{Log, H160, H256, H2048, U256, U64}; +use ethereum_types::{H160, H256, U64, U256, Bloom as H2048}; +use v1::types::Log; use types::receipt::{Receipt as EthReceipt, RichReceipt, LocalizedReceipt, TransactionOutcome}; /// Receipt @@ -55,7 +56,7 @@ impl Receipt { fn outcome_to_state_root(outcome: TransactionOutcome) -> Option { match outcome { TransactionOutcome::Unknown | TransactionOutcome::StatusCode(_) => None, - TransactionOutcome::StateRoot(root) => Some(root.into()), + TransactionOutcome::StateRoot(root) => Some(root), } } @@ -71,18 +72,18 @@ impl From for Receipt { fn from(r: LocalizedReceipt) -> Self { Receipt { to: r.to.map(Into::into), - from: Some(r.from.into()), - transaction_hash: Some(r.transaction_hash.into()), + from: Some(r.from), + transaction_hash: Some(r.transaction_hash), transaction_index: Some(r.transaction_index.into()), - block_hash: Some(r.block_hash.into()), + block_hash: Some(r.block_hash), block_number: Some(r.block_number.into()), - cumulative_gas_used: r.cumulative_gas_used.into(), - gas_used: Some(r.gas_used.into()), + cumulative_gas_used: r.cumulative_gas_used, + gas_used: Some(r.gas_used), contract_address: r.contract_address.map(Into::into), logs: r.logs.into_iter().map(Into::into).collect(), status_code: Self::outcome_to_status_code(&r.outcome), state_root: Self::outcome_to_state_root(r.outcome), - logs_bloom: r.log_bloom.into(), + logs_bloom: r.log_bloom, } } } @@ -92,17 +93,17 @@ impl From for Receipt { Receipt { from: None, to: None, - transaction_hash: Some(r.transaction_hash.into()), + transaction_hash: Some(r.transaction_hash), transaction_index: Some(r.transaction_index.into()), block_hash: None, block_number: None, - cumulative_gas_used: r.cumulative_gas_used.into(), - gas_used: Some(r.gas_used.into()), + cumulative_gas_used: r.cumulative_gas_used, + gas_used: Some(r.gas_used), contract_address: r.contract_address.map(Into::into), logs: r.logs.into_iter().map(Into::into).collect(), status_code: Self::outcome_to_status_code(&r.outcome), state_root: Self::outcome_to_state_root(r.outcome), - logs_bloom: r.log_bloom.into(), + logs_bloom: r.log_bloom, } } } @@ -116,13 +117,13 @@ impl From for Receipt { transaction_index: None, block_hash: None, block_number: None, - cumulative_gas_used: r.gas_used.into(), + cumulative_gas_used: r.gas_used, gas_used: None, contract_address: None, logs: r.logs.into_iter().map(Into::into).collect(), status_code: Self::outcome_to_status_code(&r.outcome), state_root: Self::outcome_to_state_root(r.outcome), - logs_bloom: r.log_bloom.into(), + logs_bloom: r.log_bloom, } } } diff --git a/rpc/src/v1/types/secretstore.rs b/rpc/src/v1/types/secretstore.rs index 0de3aaac67..ef76ec5b46 100644 --- a/rpc/src/v1/types/secretstore.rs +++ b/rpc/src/v1/types/secretstore.rs @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use v1::types::{Bytes, H512}; +use ethereum_types::H512; +use v1::types::Bytes; /// Encrypted document key. #[derive(Default, Debug, Serialize, PartialEq)] @@ -22,7 +23,7 @@ use v1::types::{Bytes, H512}; pub struct EncryptedDocumentKey { /// Common encryption point. Pass this to Secret Store 'Document key storing session' pub common_point: H512, - /// Ecnrypted point. Pass this to Secret Store 'Document key storing session'. + /// Encrypted point. Pass this to Secret Store 'Document key storing session'. pub encrypted_point: H512, /// Document key itself, encrypted with passed account public. Pass this to 'secretstore_encrypt'. pub encrypted_key: Bytes, diff --git a/rpc/src/v1/types/sync.rs b/rpc/src/v1/types/sync.rs index b56d1f9ccb..901611fea2 100644 --- a/rpc/src/v1/types/sync.rs +++ b/rpc/src/v1/types/sync.rs @@ -14,10 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +use network::client_version::ClientVersion; use std::collections::BTreeMap; + +use ethereum_types::{U256, H512}; use sync::{self, PeerInfo as SyncPeerInfo, TransactionStats as SyncTransactionStats}; use serde::{Serialize, Serializer}; -use v1::types::{U256, H512}; /// Sync info #[derive(Default, Debug, Serialize, PartialEq)] @@ -54,7 +56,7 @@ pub struct PeerInfo { /// Public node id pub id: Option, /// Node client ID - pub name: String, + pub name: ClientVersion, /// Capabilities pub caps: Vec, /// Network information @@ -118,7 +120,7 @@ impl From for PipProtocolInfo { fn from(info: sync::PipProtocolInfo) -> Self { PipProtocolInfo { version: info.version, - difficulty: info.difficulty.into(), + difficulty: info.difficulty, head: format!("{:x}", info.head), } } @@ -177,7 +179,7 @@ impl From for TransactionStats { first_seen: s.first_seen, propagated_to: s.propagated_to .into_iter() - .map(|(id, count)| (id.into(), count)) + .map(|(id, count)| (id, count)) .collect(), } } diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index 209523d3f8..58a5ee5962 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -19,14 +19,14 @@ use std::collections::BTreeMap; use ethcore::client::Executed; use ethcore::trace as et; use ethcore::trace::{FlatTrace, LocalizedTrace as EthLocalizedTrace, trace, TraceError}; -use ethereum_types::H256 as EthH256; +use ethereum_types::{H160, H256, U256}; use serde::ser::SerializeStruct; use serde::{Serialize, Serializer}; use types::account_diff; use types::state_diff; use vm; -use v1::types::{Bytes, H160, H256, U256}; +use v1::types::Bytes; #[derive(Debug, Serialize)] /// A diff of some chunk of memory. @@ -58,8 +58,8 @@ pub struct StorageDiff { impl From for StorageDiff { fn from(c: et::StorageDiff) -> Self { StorageDiff { - key: c.location.into(), - val: c.value.into(), + key: c.location, + val: c.value, } } } @@ -190,7 +190,7 @@ impl From for AccountDiff { balance: c.balance.into(), nonce: c.nonce.into(), code: c.code.into(), - storage: c.storage.into_iter().map(|(k, v)| (k.into(), v.into())).collect(), + storage: c.storage.into_iter().map(|(k, v)| (k, v.into())).collect(), } } } @@ -208,7 +208,7 @@ impl Serialize for StateDiff { impl From for StateDiff { fn from(c: state_diff::StateDiff) -> Self { - StateDiff(c.raw.into_iter().map(|(k, v)| (k.into(), v.into())).collect()) + StateDiff(c.raw.into_iter().map(|(k, v)| (k, v.into())).collect()) } } @@ -228,9 +228,9 @@ pub struct Create { impl From for Create { fn from(c: trace::Create) -> Self { Create { - from: c.from.into(), - value: c.value.into(), - gas: c.gas.into(), + from: c.from, + value: c.value, + gas: c.gas, init: Bytes::new(c.init), } } @@ -285,10 +285,10 @@ pub struct Call { impl From for Call { fn from(c: trace::Call) -> Self { Call { - from: c.from.into(), - to: c.to.into(), - value: c.value.into(), - gas: c.gas.into(), + from: c.from, + to: c.to, + value: c.value, + gas: c.gas, input: c.input.into(), call_type: c.call_type.into(), } @@ -335,8 +335,8 @@ pub struct Reward { impl From for Reward { fn from(r: trace::Reward) -> Self { Reward { - author: r.author.into(), - value: r.value.into(), + author: r.author, + value: r.value, reward_type: r.reward_type.into(), } } @@ -357,9 +357,9 @@ pub struct Suicide { impl From for Suicide { fn from(s: trace::Suicide) -> Self { Suicide { - address: s.address.into(), - refund_address: s.refund_address.into(), - balance: s.balance.into(), + address: s.address, + refund_address: s.refund_address, + balance: s.balance, } } } @@ -401,7 +401,7 @@ pub struct CallResult { impl From for CallResult { fn from(c: trace::CallResult) -> Self { CallResult { - gas_used: c.gas_used.into(), + gas_used: c.gas_used, output: c.output.into(), } } @@ -422,9 +422,9 @@ pub struct CreateResult { impl From for CreateResult { fn from(c: trace::CreateResult) -> Self { CreateResult { - gas_used: c.gas_used.into(), + gas_used: c.gas_used, code: c.code.into(), - address: c.address.into(), + address: c.address, } } } @@ -526,11 +526,11 @@ impl From for LocalizedTrace { action: t.action.into(), result: t.result.into(), trace_address: t.trace_address.into_iter().map(Into::into).collect(), - subtraces: t.subtraces.into(), + subtraces: t.subtraces, transaction_position: t.transaction_number.map(Into::into), transaction_hash: t.transaction_hash.map(Into::into), - block_number: t.block_number.into(), - block_hash: t.block_hash.into(), + block_number: t.block_number, + block_hash: t.block_hash, } } } @@ -591,7 +591,7 @@ impl From for Trace { fn from(t: FlatTrace) -> Self { Trace { trace_address: t.trace_address.into_iter().map(Into::into).collect(), - subtraces: t.subtraces.into(), + subtraces: t.subtraces, action: t.action.into(), result: t.result.into(), } @@ -639,14 +639,14 @@ pub struct TraceResultsWithTransactionHash { pub transaction_hash: H256, } -impl From<(EthH256, Executed)> for TraceResultsWithTransactionHash { - fn from(t: (EthH256, Executed)) -> Self { +impl From<(H256, Executed)> for TraceResultsWithTransactionHash { + fn from(t: (H256, Executed)) -> Self { TraceResultsWithTransactionHash { output: t.1.output.into(), trace: t.1.trace.into_iter().map(Into::into).collect(), vm_trace: t.1.vm_trace.map(Into::into), state_diff: t.1.state_diff.map(Into::into), - transaction_hash: t.0.into(), + transaction_hash: t.0, } } } diff --git a/rpc/src/v1/types/trace_filter.rs b/rpc/src/v1/types/trace_filter.rs index d5ef60f47b..a455c3d1cc 100644 --- a/rpc/src/v1/types/trace_filter.rs +++ b/rpc/src/v1/types/trace_filter.rs @@ -18,7 +18,8 @@ use ethcore::client::BlockId; use ethcore::client; -use v1::types::{BlockNumber, H160}; +use ethereum_types::H160; +use v1::types::BlockNumber; /// Trace filter #[derive(Debug, PartialEq, Deserialize)] diff --git a/rpc/src/v1/types/transaction.rs b/rpc/src/v1/types/transaction.rs index dc7d6b5a15..931e038669 100644 --- a/rpc/src/v1/types/transaction.rs +++ b/rpc/src/v1/types/transaction.rs @@ -19,9 +19,10 @@ use std::sync::Arc; use serde::{Serialize, Serializer}; use serde::ser::SerializeStruct; use ethcore::{contract_address, CreateContractAddress}; +use ethereum_types::{H160, H256, H512, U64, U256}; use miner; use types::transaction::{LocalizedTransaction, Action, PendingTransaction, SignedTransaction}; -use v1::types::{Bytes, H160, H256, U256, H512, U64, TransactionCondition}; +use v1::types::{Bytes, TransactionCondition}; /// Transaction #[derive(Debug, Default, Clone, PartialEq, Serialize)] @@ -176,22 +177,22 @@ impl Transaction { let signature = t.signature(); let scheme = CreateContractAddress::FromSenderAndNonce; Transaction { - hash: t.hash().into(), - nonce: t.nonce.into(), - block_hash: Some(t.block_hash.clone().into()), + hash: t.hash(), + nonce: t.nonce, + block_hash: Some(t.block_hash), block_number: Some(t.block_number.into()), transaction_index: Some(t.transaction_index.into()), - from: t.sender().into(), + from: t.sender(), to: match t.action { Action::Create => None, - Action::Call(ref address) => Some(address.clone().into()) + Action::Call(ref address) => Some(*address) }, - value: t.value.into(), - gas_price: t.gas_price.into(), - gas: t.gas.into(), + value: t.value, + gas_price: t.gas_price, + gas: t.gas, input: Bytes::new(t.data.clone()), creates: match t.action { - Action::Create => Some(contract_address(scheme, &t.sender(), &t.nonce, &t.data).0.into()), + Action::Create => Some(contract_address(scheme, &t.sender(), &t.nonce, &t.data).0), Action::Call(_) => None, }, raw: ::rlp::encode(&t.signed).into(), @@ -210,22 +211,22 @@ impl Transaction { let signature = t.signature(); let scheme = CreateContractAddress::FromSenderAndNonce; Transaction { - hash: t.hash().into(), - nonce: t.nonce.into(), + hash: t.hash(), + nonce: t.nonce, block_hash: None, block_number: None, transaction_index: None, - from: t.sender().into(), + from: t.sender(), to: match t.action { Action::Create => None, - Action::Call(ref address) => Some(address.clone().into()) + Action::Call(ref address) => Some(*address) }, - value: t.value.into(), - gas_price: t.gas_price.into(), - gas: t.gas.into(), + value: t.value, + gas_price: t.gas_price, + gas: t.gas, input: Bytes::new(t.data.clone()), creates: match t.action { - Action::Create => Some(contract_address(scheme, &t.sender(), &t.nonce, &t.data).0.into()), + Action::Create => Some(contract_address(scheme, &t.sender(), &t.nonce, &t.data).0), Action::Call(_) => None, }, raw: ::rlp::encode(&t).into(), @@ -242,7 +243,7 @@ impl Transaction { /// Convert `PendingTransaction` into RPC Transaction. pub fn from_pending(t: PendingTransaction) -> Transaction { let mut r = Transaction::from_signed(t.transaction); - r.condition = t.condition.map(|b| b.into()); + r.condition = r.condition.map(Into::into); r } } @@ -264,8 +265,8 @@ impl LocalTransactionStatus { Canceled(tx) => LocalTransactionStatus::Canceled(convert(tx)), Replaced { old, new } => LocalTransactionStatus::Replaced( convert(old), - new.signed().gas_price.into(), - new.signed().hash().into(), + new.signed().gas_price, + new.signed().hash(), ), } } diff --git a/rpc/src/v1/types/transaction_request.rs b/rpc/src/v1/types/transaction_request.rs index bfefde462d..944ee11148 100644 --- a/rpc/src/v1/types/transaction_request.rs +++ b/rpc/src/v1/types/transaction_request.rs @@ -16,7 +16,8 @@ //! `TransactionRequest` type -use v1::types::{Bytes, H160, U256, TransactionCondition}; +use ethereum_types::{H160, U256}; +use v1::types::{Bytes, TransactionCondition}; use v1::helpers; use ansi_term::Colour; @@ -57,13 +58,12 @@ pub fn format_ether(i: U256) -> String { } else { string.insert(idx as usize, '.'); } - String::from(string.trim_right_matches('0') - .trim_right_matches('.')) + String::from(string.trim_end_matches('0').trim_end_matches('.')) } impl fmt::Display for TransactionRequest { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let eth = self.value.unwrap_or(U256::from(0)); + let eth = self.value.unwrap_or_default(); match self.to { Some(ref to) => write!( f, @@ -106,14 +106,14 @@ impl From for TransactionRequest { impl From for TransactionRequest { fn from(r: helpers::FilledTransactionRequest) -> Self { TransactionRequest { - from: Some(r.from.into()), - to: r.to.map(Into::into), - gas_price: Some(r.gas_price.into()), - gas: Some(r.gas.into()), - value: Some(r.value.into()), + from: Some(r.from), + to: r.to, + gas_price: Some(r.gas_price), + gas: Some(r.gas), + value: Some(r.value), data: Some(r.data.into()), - nonce: r.nonce.map(Into::into), - condition: r.condition.map(Into::into), + nonce: r.nonce, + condition: r.condition, } } } @@ -138,7 +138,8 @@ mod tests { use std::str::FromStr; use rustc_hex::FromHex; use serde_json; - use v1::types::{U256, H160, TransactionCondition}; + use v1::types::TransactionCondition; + use ethereum_types::{H160, U256}; use super::*; #[test] diff --git a/rpc/src/v1/types/uint.rs b/rpc/src/v1/types/uint.rs deleted file mode 100644 index 3c5801c07c..0000000000 --- a/rpc/src/v1/types/uint.rs +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -use std::str::FromStr; -use std::fmt; -use serde; -use ethereum_types::{U256 as EthU256, U128 as EthU128}; - -macro_rules! impl_uint { - ($name: ident, $other: ident, $size: expr) => { - /// Uint serialization. - #[derive(Debug, Default, Clone, Copy, PartialEq, Hash)] - pub struct $name($other); - - impl Eq for $name { } - - impl From for $name where $other: From { - fn from(o: T) -> Self { - $name($other::from(o)) - } - } - - impl FromStr for $name { - type Err = <$other as FromStr>::Err; - - fn from_str(s: &str) -> Result { - $other::from_str(s).map($name) - } - } - - impl Into<$other> for $name { - fn into(self) -> $other { - self.0 - } - } - - impl fmt::Display for $name { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.0) - } - } - - impl fmt::LowerHex for $name { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::LowerHex::fmt(&self.0, f) - } - } - - impl<'a> serde::Deserialize<'a> for $name { - fn deserialize(deserializer: D) -> Result<$name, D::Error> - where D: serde::Deserializer<'a> { - struct UintVisitor; - - impl<'b> serde::de::Visitor<'b> for UintVisitor { - type Value = $name; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a 0x-prefixed, hex-encoded number of length {}", $size*16) - } - - fn visit_str(self, value: &str) -> Result where E: serde::de::Error { - if value.len() < 2 || !value.starts_with("0x") { - return Err(E::custom("expected a hex-encoded numbers with 0x prefix")) - } - - // 0x + len - if value.len() > 2 + $size * 16 { - return Err(E::invalid_length(value.len() - 2, &self)); - } - - $other::from_str(&value[2..]).map($name).map_err(|e| E::custom(&format!("invalid hex value: {:?}", e))) - } - - fn visit_string(self, value: String) -> Result where E: serde::de::Error { - self.visit_str(&value) - } - } - - deserializer.deserialize_any(UintVisitor) - } - } - - } -} - -impl_uint!(U128, EthU128, 2); -impl_uint!(U256, EthU256, 4); -impl_uint!(U64, u64, 1); - -impl serde::Serialize for U128 { - fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { - serializer.serialize_str(&format!("{:#x}", self)) - } -} - -impl serde::Serialize for U256 { - fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { - serializer.serialize_str(&format!("{:#x}", self)) - } -} - -impl serde::Serialize for U64 { - fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { - serializer.serialize_str(&format!("{:#x}", self)) - } -} - -#[cfg(test)] -mod tests { - use super::U256; - use serde_json; - - type Res = Result; - - #[test] - fn should_serialize_u256() { - let serialized1 = serde_json::to_string(&U256(0.into())).unwrap(); - let serialized2 = serde_json::to_string(&U256(1.into())).unwrap(); - let serialized3 = serde_json::to_string(&U256(16.into())).unwrap(); - let serialized4 = serde_json::to_string(&U256(256.into())).unwrap(); - - assert_eq!(serialized1, r#""0x0""#); - assert_eq!(serialized2, r#""0x1""#); - assert_eq!(serialized3, r#""0x10""#); - assert_eq!(serialized4, r#""0x100""#); - } - - #[test] - fn should_fail_to_deserialize_decimals() { - let deserialized0: Res = serde_json::from_str(r#""∀∂""#); - let deserialized1: Res = serde_json::from_str(r#""""#); - let deserialized2: Res = serde_json::from_str(r#""0""#); - let deserialized3: Res = serde_json::from_str(r#""10""#); - let deserialized4: Res = serde_json::from_str(r#""1000000""#); - let deserialized5: Res = serde_json::from_str(r#""1000000000000000000""#); - - assert!(deserialized0.is_err()); - assert!(deserialized1.is_err()); - assert!(deserialized2.is_err()); - assert!(deserialized3.is_err()); - assert!(deserialized4.is_err()); - assert!(deserialized5.is_err()); - } - - #[test] - fn should_deserialize_u256() { - let deserialized1: U256 = serde_json::from_str(r#""0x""#).unwrap(); - let deserialized2: U256 = serde_json::from_str(r#""0x0""#).unwrap(); - let deserialized3: U256 = serde_json::from_str(r#""0x1""#).unwrap(); - let deserialized4: U256 = serde_json::from_str(r#""0x01""#).unwrap(); - let deserialized5: U256 = serde_json::from_str(r#""0x100""#).unwrap(); - - assert_eq!(deserialized1, U256(0.into())); - assert_eq!(deserialized2, U256(0.into())); - assert_eq!(deserialized3, U256(1.into())); - assert_eq!(deserialized4, U256(1.into())); - assert_eq!(deserialized5, U256(256.into())); - } -} diff --git a/rpc/src/v1/types/work.rs b/rpc/src/v1/types/work.rs index b7c312162b..ed6c7c8e91 100644 --- a/rpc/src/v1/types/work.rs +++ b/rpc/src/v1/types/work.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use super::{H256, U256}; +use ethereum_types::{H256, U256}; use serde::{Serialize, Serializer}; diff --git a/scripts/docker/debian/Dockerfile b/scripts/docker/debian/Dockerfile index 5e7465bbdd..e37e95e0a4 100644 --- a/scripts/docker/debian/Dockerfile +++ b/scripts/docker/debian/Dockerfile @@ -8,7 +8,7 @@ RUN apt update -y && \ WORKDIR /parity COPY . /parity -RUN cargo build --release --verbose +RUN cargo build --release RUN strip target/release/parity FROM debian:stretch diff --git a/scripts/docker/hub/Dockerfile b/scripts/docker/hub/Dockerfile index a18cacf9cc..ac1dd32ee1 100644 --- a/scripts/docker/hub/Dockerfile +++ b/scripts/docker/hub/Dockerfile @@ -1,30 +1,48 @@ FROM ubuntu:xenial -LABEL MAINTAINER="Parity Technologies " -# install tools and dependencies -RUN apt update && apt install -y --no-install-recommends openssl libudev-dev file curl jq +# metadata +ARG VCS_REF +ARG BUILD_DATE + +LABEL io.parity.image.authors="devops-team@parity.io" \ + io.parity.image.vendor="Parity Technologies" \ + io.parity.image.title="parity/parity" \ + io.parity.image.description="Parity Ethereum. The Fastest and most Advanced Ethereum Client." \ + io.parity.image.source="https://github.com/paritytech/parity-ethereum/blob/${VCS_REF}/\ +scripts/docker/hub/Dockerfile" \ + io.parity.image.documentation="https://wiki.parity.io/Parity-Ethereum" \ + io.parity.image.revision="${VCS_REF}" \ + io.parity.image.created="${BUILD_DATE}" # show backtraces ENV RUST_BACKTRACE 1 -# cleanup Docker image -RUN apt autoremove -y \ - && apt clean -y \ - && rm -rf /tmp/* /var/tmp/* /var/lib/apt/lists/* - -RUN groupadd -g 1000 parity \ - && useradd -m -u 1000 -g parity -s /bin/sh parity +# install tools and dependencies +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + file curl jq; \ +# apt cleanup + apt-get autoremove -y; \ + apt-get clean; \ + rm -rf /tmp/* /var/tmp/* /var/lib/apt/lists/*; \ +# add user + groupadd -g 1000 parity; \ + useradd -m -u 1000 -g parity -s /bin/sh parity WORKDIR /home/parity -# add parity-ethereum to docker image +# add parity-ethereum binary to docker image COPY artifacts/x86_64-unknown-linux-gnu/parity /bin/parity - -COPY scripts/docker/hub/check_sync.sh /check_sync.sh +COPY tools/check_sync.sh /check_sync.sh # switch to user parity here USER parity +# check if executable works in this container +RUN parity --version + EXPOSE 5001 8080 8082 8083 8545 8546 8180 30303/tcp 30303/udp ENTRYPOINT ["/bin/parity"] + diff --git a/scripts/docker/hub/publish-docker.sh b/scripts/docker/hub/publish-docker.sh new file mode 100755 index 0000000000..84feedb281 --- /dev/null +++ b/scripts/docker/hub/publish-docker.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +set -e # fail on any error + +VERSION=$(cat ./tools/VERSION) +TRACK=$(cat ./tools/TRACK) +echo "Parity Ethereum version = ${VERSION}" +echo "Parity Ethereum track = ${TRACK}" + +test "$Docker_Hub_User_Parity" -a "$Docker_Hub_Pass_Parity" \ + || ( echo "no docker credentials provided"; exit 1 ) +docker login -u "$Docker_Hub_User_Parity" -p "$Docker_Hub_Pass_Parity" +echo "__________Docker info__________" +docker info + +# we stopped pushing nightlies to dockerhub, will push to own registry prb. +case "${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}" in + "$SCHEDULE_TAG") + echo "Docker TAG - 'parity/parity:${SCHEDULE_TAG}'"; + docker build --no-cache \ + --build-arg VCS_REF="${CI_COMMIT_SHA}" \ + --build-arg BUILD_DATE="$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \ + --tag "parity/parity:${SCHEDULE_TAG}" \ + --file tools/Dockerfile .; + docker push "parity/parity:${SCHEDULE_TAG}";; + "beta") + echo "Docker TAGs - 'parity/parity:beta', 'parity/parity:latest', \ + 'parity/parity:${VERSION}-${CI_COMMIT_REF_NAME}'"; + docker build --no-cache \ + --build-arg VCS_REF="${CI_COMMIT_SHA}" \ + --build-arg BUILD_DATE="$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \ + --tag "parity/parity:beta" \ + --tag "parity/parity:latest" \ + --tag "parity/parity:${VERSION}-${CI_COMMIT_REF_NAME}" \ + --file tools/Dockerfile .; + docker push "parity/parity:beta"; + docker push "parity/parity:latest"; + docker push "parity/parity:${VERSION}-${CI_COMMIT_REF_NAME}";; + "stable") + echo "Docker TAGs - 'parity/parity:${VERSION}-${CI_COMMIT_REF_NAME}', 'parity/parity:stable'"; + docker build --no-cache \ + --build-arg VCS_REF="${CI_COMMIT_SHA}" \ + --build-arg BUILD_DATE="$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \ + --tag "parity/parity:${VERSION}-${CI_COMMIT_REF_NAME}" \ + --tag "parity/parity:stable" \ + --file tools/Dockerfile .; + docker push "parity/parity:${VERSION}-${CI_COMMIT_REF_NAME}"; + docker push "parity/parity:stable";; + v[0-9]*.[0-9]*) + echo "Docker TAG - 'parity/parity:${VERSION}-${TRACK}'" + docker build --no-cache \ + --build-arg VCS_REF="${CI_COMMIT_SHA}" \ + --build-arg BUILD_DATE="$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \ + --tag "parity/parity:${VERSION}-${TRACK}" \ + --file tools/Dockerfile .; + docker push "parity/parity:${VERSION}-${TRACK}";; + *) + echo "Docker TAG - 'parity/parity:${VERSION}-${CI_COMMIT_REF_NAME}'" + docker build --no-cache \ + --build-arg VCS_REF="${CI_COMMIT_SHA}" \ + --build-arg BUILD_DATE="$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \ + --tag "parity/parity:${VERSION}-${CI_COMMIT_REF_NAME}" \ + --file tools/Dockerfile .; + docker push "parity/parity:${VERSION}-${CI_COMMIT_REF_NAME}";; +esac + +docker logout diff --git a/scripts/gitlab/build-linux.sh b/scripts/gitlab/build-linux.sh new file mode 100755 index 0000000000..ebd65cd9b3 --- /dev/null +++ b/scripts/gitlab/build-linux.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +set -e # fail on any error +set -u # treat unset variables as error + +echo "__________Show ENVIROMENT__________" +echo "CI_SERVER_NAME: " $CI_SERVER_NAME +echo "CARGO_HOME: " $CARGO_HOME +echo "CARGO_TARGET: " $CARGO_TARGET +echo "CC: " $CC +echo "CXX: " $CXX +#strip ON +export RUSTFLAGS=" -C link-arg=-s" +# Linker for crosscomile +echo "_____ Linker _____" +cat .cargo/config + +echo "_____ Building target: "$CARGO_TARGET" _____" +if [ "${CARGO_TARGET}" = "armv7-linux-androideabi" ] +then + time cargo build --target $CARGO_TARGET --verbose --color=always --release -p parity-clib --features final +else + time cargo build --target $CARGO_TARGET --verbose --color=always --release --features final + time cargo build --target $CARGO_TARGET --verbose --color=always --release -p evmbin + time cargo build --target $CARGO_TARGET --verbose --color=always --release -p ethstore-cli + time cargo build --target $CARGO_TARGET --verbose --color=always --release -p ethkey-cli + time cargo build --target $CARGO_TARGET --verbose --color=always --release -p whisper-cli +fi + +echo "_____ Post-processing binaries _____" +rm -rf artifacts/* +mkdir -p artifacts/$CARGO_TARGET +cd artifacts/$CARGO_TARGET + +if [ "${CARGO_TARGET}" = "armv7-linux-androideabi" ] +then + cp -v ../../target/$CARGO_TARGET/release/libparity.so ./libparity.so +else + cp -v ../../target/$CARGO_TARGET/release/parity ./parity + cp -v ../../target/$CARGO_TARGET/release/parity-evm ./parity-evm + cp -v ../../target/$CARGO_TARGET/release/ethstore ./ethstore + cp -v ../../target/$CARGO_TARGET/release/ethkey ./ethkey + cp -v ../../target/$CARGO_TARGET/release/whisper ./whisper +fi + +echo "_____ Calculating checksums _____" +for binary in $(ls) +do + rhash --sha256 $binary -o $binary.sha256 #do we still need this hash (SHA2)? + if [[ $CARGO_TARGET == *"x86_64"* ]]; + then + ./parity tools hash $binary > $binary.sha3 + else + echo "> ${binary} cannot be hashed with cross-compiled binary (keccak256)" + fi +done diff --git a/scripts/gitlab/build-windows.sh b/scripts/gitlab/build-windows.sh index d4176c7580..76332124d1 100755 --- a/scripts/gitlab/build-windows.sh +++ b/scripts/gitlab/build-windows.sh @@ -4,18 +4,21 @@ set -u # treat unset variables as error set INCLUDE="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include;C:\vs2015\VC\include;C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt" set LIB="C:\vs2015\VC\lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64" +sccache -s echo "__________Show ENVIROMENT__________" echo "CI_SERVER_NAME: " $CI_SERVER_NAME echo "CARGO_HOME: " $CARGO_HOME echo "CARGO_TARGET: " $CARGO_TARGET +echo "RUSTC_WRAPPER: " $RUSTC_WRAPPER +echo "SCCACHE_DIR: " $SCCACHE_DIR echo "_____ Building target: "$CARGO_TARGET" _____" -time cargo build --target $CARGO_TARGET --release --features final -time cargo build --target $CARGO_TARGET --release -p evmbin -time cargo build --target $CARGO_TARGET --release -p ethstore-cli -time cargo build --target $CARGO_TARGET --release -p ethkey-cli -time cargo build --target $CARGO_TARGET --release -p whisper-cli +time cargo build --target $CARGO_TARGET --verbose --release --features final +time cargo build --target $CARGO_TARGET --verbose --release -p evmbin +time cargo build --target $CARGO_TARGET --verbose --release -p ethstore-cli +time cargo build --target $CARGO_TARGET --verbose --release -p ethkey-cli +time cargo build --target $CARGO_TARGET --verbose --release -p whisper-cli echo "__________Sign binaries__________" scripts/gitlab/sign-win.cmd $keyfile $certpass target/$CARGO_TARGET/release/parity.exe @@ -44,3 +47,5 @@ do done cp parity.exe.sha256 parity.sha256 cp parity.exe.sha3 parity.sha3 + +sccache -s diff --git a/scripts/gitlab/publish-av-whitelists.sh b/scripts/gitlab/publish-av-whitelists.sh new file mode 100755 index 0000000000..3c5dde8075 --- /dev/null +++ b/scripts/gitlab/publish-av-whitelists.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -e + +target_filename="parity-${CI_COMMIT_TAG:-${CI_COMMIT_REF_NAME}}.exe" +apt -y update +apt -y install ftp + +echo "__________Publish Windows binaries to Avast Whitelisting program__________" + +ftp -pinv whitelisting.avast.com <&1 \ + | sed -r "s|(${GITHUB_USER}):[a-f0-9]+@|\1:REDACTED@|g" + git push -q -f --tags 2>&1 \ + | sed -r "s|(${GITHUB_USER}):[a-f0-9]+@|\1:REDACTED@|g" } RPC_TRAITS_DIR="rpc/src/v1/traits" diff --git a/scripts/gitlab/publish-snap.sh b/scripts/gitlab/publish-snap.sh index 5e0231af00..d9f10ce3ee 100755 --- a/scripts/gitlab/publish-snap.sh +++ b/scripts/gitlab/publish-snap.sh @@ -3,15 +3,11 @@ set -e # fail on any error set -u # treat unset variables as error -# some necromancy: -# gsub(/"/, "", $2) deletes "qoutes" -# gsub(/ /, "", $2) deletes whitespaces -TRACK=`awk -F '=' '/^track/ {gsub(/"/, "", $2); gsub(/ /, "", $2); print $2}' ./util/version/Cargo.toml` -echo Track is: $TRACK # prepare variables -VERSION=v"$(sed -r -n '1,/^version/s/^version = "([^"]+)".*$/\1/p' Cargo.toml)" +TRACK=$(cat ./tools/TRACK) +echo "Track is: ${TRACK}" +VERSION=$(cat ./tools/VERSION) SNAP_PACKAGE="parity_"$VERSION"_"$BUILD_ARCH".snap" -CARGO_TARGET="$(ls artifacts)" # Choose snap release channel based on parity ethereum version track case ${TRACK} in nightly) export GRADE="devel" CHANNEL="edge";; @@ -20,12 +16,8 @@ case ${TRACK} in *) echo "No release" && exit 0;; esac -# Release untagged versions from branches to the candidate snap channel -case ${CI_COMMIT_REF_NAME} in - beta|stable) export GRADE="stable" CHANNEL="candidate";; -esac echo "__________Create snap package__________" -echo "Release channel :" $GRADE " Branch/tag: " $CI_COMMIT_REF_NAME +echo "Release channel :" $GRADE " Branch/tag: " $CI_COMMIT_REF_NAME "Track: " ${TRACK} echo $VERSION:$GRADE:$BUILD_ARCH:$CARGO_TARGET sed -e 's/$VERSION/'"$VERSION"'/g' \ diff --git a/scripts/gitlab/test-all.sh b/scripts/gitlab/rust-changes.sh similarity index 87% rename from scripts/gitlab/test-all.sh rename to scripts/gitlab/rust-changes.sh index 925124b7ac..236a20d59e 100755 --- a/scripts/gitlab/test-all.sh +++ b/scripts/gitlab/rust-changes.sh @@ -1,7 +1,9 @@ #!/bin/bash +echo "________Running rust_changes.sh________" set -e # fail on any error set -u # treat unset variables as error +echo "__________Checking if Rust files were changed__________" git log --graph --oneline --decorate=short -n 10 case ${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}} in @@ -26,5 +28,3 @@ then fi rustup show - -exec ./test.sh diff --git a/scripts/gitlab/test-cpp.sh b/scripts/gitlab/test-cpp.sh new file mode 100755 index 0000000000..1cbd58a30c --- /dev/null +++ b/scripts/gitlab/test-cpp.sh @@ -0,0 +1,17 @@ +#!/bin/bash +echo "________Running test-cpp.sh________" +set -e # fail on any error +set -u # treat unset variables as error +#use nproc `linux only +THREADS=$(nproc) + +echo "________Running the C++ example________" +DIR=parity-clib/examples/cpp/build +mkdir -p $DIR +cd $DIR +cmake .. +make VERBOSE=1 -j $THREADS +# Note: we don't try to run the example because it tries to sync Kovan, and we don't want +# that to happen on CI +cd - +rm -rf $DIR diff --git a/scripts/gitlab/test-linux.sh b/scripts/gitlab/test-linux.sh new file mode 100755 index 0000000000..d7e6da0bb6 --- /dev/null +++ b/scripts/gitlab/test-linux.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# ARGUMENT $1 Rust flavor to run test with (stable/beta/nightly) + +echo "________Running test-linux.sh________" +set -e # fail on any error +set -u # treat unset variables as error + +FEATURES="json-tests,ci-skip-tests" +OPTIONS="" +#use nproc `linux only +THREADS=$(nproc) + +rustup default $1 +rustup show + +echo "________Running Parity Full Test Suite________" +# Why are we using RUSTFLAGS? See https://github.com/paritytech/parity-ethereum/pull/10719 +CARGO_INCREMENTAL=0 RUSTFLAGS="-C opt-level=3 -C overflow-checks=on -C debuginfo=2" time cargo test $OPTIONS --features "$FEATURES" --locked --all --target $CARGO_TARGET --verbose --color=never -- --test-threads $THREADS diff --git a/scripts/gitlab/validate-chainspecs.sh b/scripts/gitlab/validate-chainspecs.sh new file mode 100755 index 0000000000..58391e1312 --- /dev/null +++ b/scripts/gitlab/validate-chainspecs.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -e # fail on any error +set -u # treat unset variables as error +echo "________Running validate_chainspecs.sh________" + +ERR=0 + +echo "________Validate chainspecs________" +time cargo build --release -p chainspec --verbose --color=always + +for spec in ethcore/res/*.json; do + if ! ./target/release/chainspec "$spec"; then ERR=1; fi +done + +for spec in ethcore/res/ethereum/*.json; do + if ! ./target/release/chainspec "$spec"; then ERR=1; fi +done + +exit $ERR diff --git a/scripts/validate_chainspecs.sh b/scripts/validate_chainspecs.sh deleted file mode 100755 index c350445dd9..0000000000 --- a/scripts/validate_chainspecs.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env sh - -ERR=0 -cargo build --release -p chainspec - -for spec in ethcore/res/*.json; do - if ! ./target/release/chainspec "$spec"; then ERR=1; fi -done - -for spec in ethcore/res/ethereum/*.json; do - if ! ./target/release/chainspec "$spec"; then ERR=1; fi -done - -exit $ERR diff --git a/secret-store/Cargo.toml b/secret-store/Cargo.toml index 016028a0bf..6f5e16d7a5 100644 --- a/secret-store/Cargo.toml +++ b/secret-store/Cargo.toml @@ -1,5 +1,5 @@ [package] -description = "Ethcore Secret Store" +description = "Parity Ethereum (EthCore) Secret Store" name = "ethcore-secretstore" version = "1.0.0" license = "GPL-3.0" @@ -8,36 +8,40 @@ authors = ["Parity Technologies "] [dependencies] byteorder = "1.0" common-types = { path = "../ethcore/types" } +ethabi = "6.0" +ethabi-contract = "6.0" +ethabi-derive = "6.0" +ethcore = { path = "../ethcore" } +ethcore-accounts = { path = "../accounts", optional = true} ethcore-call-contract = { path = "../ethcore/call-contract" } +ethcore-sync = { path = "../ethcore/sync" } +ethereum-types = "0.4" +ethkey = { path = "../accounts/ethkey" } +futures = "0.1" +hyper = { version = "0.12", default-features = false } +keccak-hash = "0.1" +kvdb = "0.1" +lazy_static = "1.0" log = "0.4" +parity-bytes = "0.1" +parity-crypto = "0.3" +parity-runtime = { path = "../util/runtime" } parking_lot = "0.7" -hyper = { version = "0.12", default-features = false } +rustc-hex = "1.0" serde = "1.0" -serde_json = "1.0" serde_derive = "1.0" -futures = "0.1" -rustc-hex = "1.0" +serde_json = "1.0" tiny-keccak = "1.4" tokio = "~0.1.11" -parity-runtime = { path = "../util/runtime" } tokio-io = "0.1" tokio-service = "0.1" url = "1.0" -ethcore = { path = "../ethcore" } -parity-bytes = "0.1" -parity-crypto = "0.2" -ethcore-sync = { path = "../ethcore/sync" } -ethereum-types = "0.4" -kvdb = "0.1" -keccak-hash = "0.1" -ethkey = { path = "../accounts/ethkey" } -lazy_static = "1.0" -ethabi = "6.0" -ethabi-derive = "6.0" -ethabi-contract = "6.0" [dev-dependencies] env_logger = "0.5" ethcore = { path = "../ethcore", features = ["test-helpers"] } tempdir = "0.3" kvdb-rocksdb = "0.1.3" + +[features] +accounts = ["ethcore-accounts"] diff --git a/secret-store/src/key_server.rs b/secret-store/src/key_server.rs index 24d8c8f9e0..3f03e7e259 100644 --- a/secret-store/src/key_server.rs +++ b/secret-store/src/key_server.rs @@ -23,11 +23,11 @@ use parity_runtime::Executor; use super::acl_storage::AclStorage; use super::key_storage::KeyStorage; use super::key_server_set::KeyServerSet; -use key_server_cluster::{math, ClusterCore}; +use key_server_cluster::{math, new_network_cluster}; use traits::{AdminSessionsServer, ServerKeyGenerator, DocumentKeyServer, MessageSigner, KeyServer, NodeKeyPair}; use types::{Error, Public, RequestSignature, Requester, ServerKeyId, EncryptedDocumentKey, EncryptedDocumentKeyShadow, ClusterConfiguration, MessageHash, EncryptedMessageSignature, NodeId}; -use key_server_cluster::{ClusterClient, ClusterConfiguration as NetClusterConfiguration}; +use key_server_cluster::{ClusterClient, ClusterConfiguration as NetClusterConfiguration, NetConnectionsManagerConfig}; /// Secret store key server implementation pub struct KeyServerImpl { @@ -175,20 +175,23 @@ impl KeyServerCore { pub fn new(config: &ClusterConfiguration, key_server_set: Arc, self_key_pair: Arc, acl_storage: Arc, key_storage: Arc, executor: Executor) -> Result { - let config = NetClusterConfiguration { + let cconfig = NetClusterConfiguration { self_key_pair: self_key_pair.clone(), - listen_address: (config.listener_address.address.clone(), config.listener_address.port), key_server_set: key_server_set, - allow_connecting_to_higher_nodes: config.allow_connecting_to_higher_nodes, acl_storage: acl_storage, key_storage: key_storage, - admin_public: config.admin_public.clone(), + admin_public: config.admin_public, + preserve_sessions: false, + }; + let net_config = NetConnectionsManagerConfig { + listen_address: (config.listener_address.address.clone(), config.listener_address.port), + allow_connecting_to_higher_nodes: config.allow_connecting_to_higher_nodes, auto_migrate_enabled: config.auto_migrate_enabled, }; - let cluster = ClusterCore::new(executor, config) - .and_then(|c| c.run().map(|_| c.client())) - .map_err(|err| Error::from(err))?; + let core = new_network_cluster(executor, cconfig, net_config)?; + let cluster = core.client(); + core.run()?; Ok(KeyServerCore { cluster, @@ -297,14 +300,14 @@ pub mod tests { let start = time::Instant::now(); let mut tried_reconnections = false; loop { - if key_servers.iter().all(|ks| ks.cluster().cluster_state().connected.len() == num_nodes - 1) { + if key_servers.iter().all(|ks| ks.cluster().is_fully_connected()) { break; } let old_tried_reconnections = tried_reconnections; let mut fully_connected = true; for key_server in &key_servers { - if key_server.cluster().cluster_state().connected.len() != num_nodes - 1 { + if !key_server.cluster().is_fully_connected() { fully_connected = false; if !old_tried_reconnections { tried_reconnections = true; @@ -434,7 +437,7 @@ pub mod tests { #[test] fn decryption_session_is_delegated_when_node_does_not_have_key_share() { let _ = ::env_logger::try_init(); - let (key_servers, _, runtime) = make_key_servers(6110, 3); + let (key_servers, key_storages, runtime) = make_key_servers(6110, 3); // generate document key let threshold = 0; @@ -445,7 +448,7 @@ pub mod tests { let generated_key = crypto::ecies::decrypt(&secret, &DEFAULT_MAC, &generated_key).unwrap(); // remove key from node0 - key_servers[0].cluster().key_storage().remove(&document).unwrap(); + key_storages[0].remove(&document).unwrap(); // now let's try to retrieve key back by requesting it from node0, so that session must be delegated let retrieved_key = key_servers[0].restore_document_key(&document, &signature.into()).unwrap(); @@ -457,7 +460,7 @@ pub mod tests { #[test] fn schnorr_signing_session_is_delegated_when_node_does_not_have_key_share() { let _ = ::env_logger::try_init(); - let (key_servers, _, runtime) = make_key_servers(6114, 3); + let (key_servers, key_storages, runtime) = make_key_servers(6114, 3); let threshold = 1; // generate server key @@ -467,7 +470,7 @@ pub mod tests { let server_public = key_servers[0].generate_key(&server_key_id, &signature.clone().into(), threshold).unwrap(); // remove key from node0 - key_servers[0].cluster().key_storage().remove(&server_key_id).unwrap(); + key_storages[0].remove(&server_key_id).unwrap(); // sign message let message_hash = H256::from(42); @@ -484,7 +487,7 @@ pub mod tests { #[test] fn ecdsa_signing_session_is_delegated_when_node_does_not_have_key_share() { let _ = ::env_logger::try_init(); - let (key_servers, _, runtime) = make_key_servers(6117, 4); + let (key_servers, key_storages, runtime) = make_key_servers(6117, 4); let threshold = 1; // generate server key @@ -494,7 +497,7 @@ pub mod tests { let server_public = key_servers[0].generate_key(&server_key_id, &signature.clone().into(), threshold).unwrap(); // remove key from node0 - key_servers[0].cluster().key_storage().remove(&server_key_id).unwrap(); + key_storages[0].remove(&server_key_id).unwrap(); // sign message let message_hash = H256::random(); diff --git a/secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs b/secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs index 4d3de95005..18c6358795 100644 --- a/secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs +++ b/secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs @@ -1045,148 +1045,204 @@ fn check_nodes_set(all_nodes_set: &BTreeSet, new_nodes_set: &BTreeSet, - pub key_storage: Arc, - pub session: SessionImpl, + pub trait AdminSessionAdapter { + const SIGN_NEW_NODES: bool; + + fn create( + meta: ShareChangeSessionMeta, + admin_public: Public, + all_nodes_set: BTreeSet, + ml: &ClusterMessageLoop, + idx: usize + ) -> S; } - struct MessageLoop { + pub struct MessageLoop { + pub ml: ClusterMessageLoop, pub admin_key_pair: KeyPair, pub original_key_pair: KeyPair, + pub original_key_version: H256, pub all_nodes_set: BTreeSet, pub new_nodes_set: BTreeSet, pub all_set_signature: Signature, pub new_set_signature: Signature, - pub nodes: BTreeMap, + pub sessions: BTreeMap, pub queue: VecDeque<(NodeId, NodeId, Message)>, } - fn create_session(mut meta: ShareChangeSessionMeta, self_node_id: NodeId, admin_public: Public, all_nodes_set: BTreeSet, cluster: Arc, key_storage: Arc) -> SessionImpl { - meta.self_node_id = self_node_id; - SessionImpl::new(SessionParams { - meta: meta, - all_nodes_set: all_nodes_set, - cluster: cluster, - key_storage: key_storage, - nonce: 1, - admin_public: admin_public, - migration_id: None, - }).unwrap() + impl ::std::fmt::Debug for MessageLoop { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{:?}", self.ml) + } } - fn create_node(meta: ShareChangeSessionMeta, admin_public: Public, all_nodes_set: BTreeSet, node: &GenerationNode) -> Node { - for n in &all_nodes_set { - node.cluster.add_node(n.clone()); + struct Adapter; + + impl AdminSessionAdapter for Adapter { + const SIGN_NEW_NODES: bool = true; + + fn create( + mut meta: ShareChangeSessionMeta, + admin_public: Public, + all_nodes_set: BTreeSet, + ml: &ClusterMessageLoop, + idx: usize + ) -> SessionImpl { + meta.self_node_id = *ml.node_key_pair(idx).public(); + SessionImpl::new(SessionParams { + meta: meta, + all_nodes_set: all_nodes_set, + cluster: ml.cluster(idx).view().unwrap(), + key_storage: ml.key_storage(idx).clone(), + nonce: 1, + admin_public: admin_public, + migration_id: None, + }).unwrap() } + } - Node { - cluster: node.cluster.clone(), - key_storage: node.key_storage.clone(), - session: create_session(meta, node.session.node().clone(), admin_public, all_nodes_set, node.cluster.clone(), node.key_storage.clone()), + impl MessageLoop { + pub fn with_gml>( + gml: GenerationMessageLoop, + master: NodeId, + add: Option>, + removed_nodes_ids: Option>, + isolated_nodes_ids: Option>, + ) -> Self { + // read generated key data + let original_key_pair = gml.compute_key_pair(); + let original_key_version = gml.key_version(); + Self::with_ml::( + gml.0, + original_key_pair, + original_key_version, + master, + add, + removed_nodes_ids, + isolated_nodes_ids) } - } - impl MessageLoop { - pub fn new(gml: &GenerationMessageLoop, master_node_id: NodeId, original_key_pair: Option, new_nodes_ids: BTreeSet, removed_nodes_ids: BTreeSet, isolated_nodes_ids: BTreeSet) -> Self { + pub fn and_then>( + self, + master: NodeId, + add: Option>, + removed_nodes_ids: Option>, + isolated_nodes_ids: Option>, + ) -> Self { + Self::with_ml::( + self.ml, + self.original_key_pair, + self.original_key_version, + master, + add, + removed_nodes_ids, + isolated_nodes_ids, + ) + } + + pub fn with_ml>( + mut ml: ClusterMessageLoop, + original_key_pair: KeyPair, + original_key_version: H256, + master: NodeId, + add: Option>, + removed_nodes_ids: Option>, + isolated_nodes_ids: Option>, + ) -> Self { + let add = add.unwrap_or_default(); + let removed_nodes_ids = removed_nodes_ids.unwrap_or_default(); + let isolated_nodes_ids = isolated_nodes_ids.unwrap_or_default(); + // generate admin key pair let admin_key_pair = Random.generate().unwrap(); let admin_public = admin_key_pair.public().clone(); - // compute original secret key - let original_key_pair = original_key_pair.unwrap_or_else(|| gml.compute_key_pair(1)); - // all active nodes set - let mut all_nodes_set: BTreeSet<_> = gml.nodes.keys() + let mut all_nodes_set: BTreeSet<_> = ml.nodes().into_iter() .filter(|n| !isolated_nodes_ids.contains(n)) - .cloned() .collect(); // new nodes set includes all old nodes, except nodes being removed + all nodes being added let new_nodes_set: BTreeSet = all_nodes_set.iter().cloned() - .chain(new_nodes_ids.iter().cloned()) + .chain(add.iter().map(|kp| *kp.public())) .filter(|n| !removed_nodes_ids.contains(n)) .collect(); - all_nodes_set.extend(new_nodes_ids.iter().cloned()); + let mut old_set_to_sign = all_nodes_set.clone(); + all_nodes_set.extend(add.iter().map(|kp| *kp.public())); + if C::SIGN_NEW_NODES { + old_set_to_sign.extend(add.iter().map(|kp| *kp.public())); + } for isolated_node_id in &isolated_nodes_ids { all_nodes_set.remove(isolated_node_id); } let meta = ShareChangeSessionMeta { - self_node_id: master_node_id.clone(), - master_node_id: master_node_id.clone(), + self_node_id: master, + master_node_id: master, id: SessionId::default(), configured_nodes_count: all_nodes_set.len(), connected_nodes_count: all_nodes_set.len(), }; - let old_nodes = gml.nodes.iter().map(|n| create_node(meta.clone(), admin_public.clone(), all_nodes_set.clone(), n.1)); - let new_nodes = new_nodes_ids.into_iter().map(|new_node_id| { - let new_node_cluster = Arc::new(DummyCluster::new(new_node_id.clone())); - for node in &all_nodes_set { - new_node_cluster.add_node(node.clone()); - } - - let new_node_key_storage = Arc::new(DummyKeyStorage::default()); - let new_node_session = create_session(meta.clone(), new_node_id, admin_public.clone(), all_nodes_set.clone(), new_node_cluster.clone(), new_node_key_storage.clone()); - Node { - cluster: new_node_cluster, - key_storage: new_node_key_storage, - session: new_node_session, - } - }); - let nodes: BTreeMap<_, _> = old_nodes.chain(new_nodes).map(|n| (n.session.core.meta.self_node_id.clone(), n)).collect(); - - for node in nodes.values() { - for isolated_node_id in &isolated_nodes_ids { - node.cluster.remove_node(isolated_node_id); - } + // include new nodes in the cluster + for node_key_pair in &add { + ml.include(Arc::new(PlainNodeKeyPair::new(node_key_pair.clone()))); } + // isolate nodes from the cluster + for isolated_node_id in &isolated_nodes_ids { + let idx = ml.nodes().iter().position(|n| n == isolated_node_id).unwrap(); + ml.exclude(idx); + } + + // prepare set of nodes + let sessions: BTreeMap<_, _> = (0..ml.nodes().len()) + .map(|idx| (ml.node(idx), C::create(meta.clone(), admin_public, all_nodes_set.clone(), &ml, idx))) + .collect(); - let all_set_signature = sign(admin_key_pair.secret(), &ordered_nodes_hash(&all_nodes_set)).unwrap(); + let all_set_signature = sign(admin_key_pair.secret(), &ordered_nodes_hash(&old_set_to_sign)).unwrap(); let new_set_signature = sign(admin_key_pair.secret(), &ordered_nodes_hash(&new_nodes_set)).unwrap(); MessageLoop { + ml, admin_key_pair: admin_key_pair, - original_key_pair: original_key_pair, + original_key_pair, + original_key_version, all_nodes_set: all_nodes_set.clone(), new_nodes_set: new_nodes_set, all_set_signature: all_set_signature, new_set_signature: new_set_signature, - nodes: nodes, + sessions, queue: Default::default(), } } pub fn run(&mut self) { + // run session until completion while let Some((from, to, message)) = self.take_message() { self.process_message((from, to, message)).unwrap(); } + + // check that all sessions have finished + assert!(self.sessions.values().all(|s| s.is_finished())); } pub fn take_message(&mut self) -> Option<(NodeId, NodeId, Message)> { - self.nodes.values() - .filter_map(|n| n.cluster.take_message().map(|m| (n.session.core.meta.self_node_id.clone(), m.0, m.1))) - .nth(0) - .or_else(|| self.queue.pop_front()) + self.ml.take_message().or_else(|| self.queue.pop_front()) } pub fn process_message(&mut self, msg: (NodeId, NodeId, Message)) -> Result<(), Error> { - match { match msg.2 { - Message::ServersSetChange(ref message) => self.nodes[&msg.1].session.process_message(&msg.0, message), - _ => unreachable!("only servers set change messages are expected"), - } } { + match self.sessions[&msg.1].on_message(&msg.0, &msg.2) { Ok(_) => Ok(()), Err(Error::TooEarlyForRequest) => { self.queue.push_back(msg); @@ -1195,213 +1251,201 @@ pub mod tests { Err(err) => Err(err), } } + + /// This only works for schemes where threshold = 1 + pub fn check_secret_is_preserved<'a, I: IntoIterator>(&self, nodes: I) { + let nodes: Vec<_> = nodes.into_iter().collect(); + let key_storages: Vec<_> = nodes.iter().map(|n| self.ml.key_storage_of(n)).collect(); + let n = nodes.len(); + let document_secret_plain = math::generate_random_point().unwrap(); + for n1 in 0..n { + for n2 in n1+1..n { + let share1 = key_storages[n1].get(&SessionId::default()).unwrap(); + let share2 = key_storages[n2].get(&SessionId::default()).unwrap(); + + let id_number1 = share1.as_ref().unwrap().last_version().unwrap().id_numbers[nodes[n1]].clone(); + let id_number2 = share1.as_ref().unwrap().last_version().unwrap().id_numbers[nodes[n2]].clone(); + // now encrypt and decrypt data + let (document_secret_decrypted, document_secret_decrypted_test) = + math::tests::do_encryption_and_decryption(1, + self.original_key_pair.public(), + &[id_number1, id_number2], + &[share1.unwrap().last_version().unwrap().secret_share.clone(), + share2.unwrap().last_version().unwrap().secret_share.clone()], + Some(self.original_key_pair.secret()), + document_secret_plain.clone()); + + assert_eq!(document_secret_plain, document_secret_decrypted_test); + assert_eq!(document_secret_plain, document_secret_decrypted); + } + } + } } - pub fn generate_key(threshold: usize, nodes_ids: BTreeSet) -> GenerationMessageLoop { - let mut gml = GenerationMessageLoop::with_nodes_ids(nodes_ids); - gml.master().initialize(Default::default(), Default::default(), false, threshold, gml.nodes.keys().cloned().collect::>().into()).unwrap(); - while let Some((from, to, message)) = gml.take_message() { - gml.process_message((from, to, message)).unwrap(); + impl MessageLoop { + pub fn run_at(mut self, master: NodeId) -> Self { + self.sessions[&master].initialize( + self.new_nodes_set.clone(), + self.all_set_signature.clone(), + self.new_set_signature.clone()).unwrap(); + self.run(); + self } + } + + pub fn generate_key(num_nodes: usize, threshold: usize) -> GenerationMessageLoop { + let gml = GenerationMessageLoop::new(num_nodes).init(threshold).unwrap(); + gml.0.loop_until(|| gml.0.is_empty()); gml } #[test] fn node_added_using_servers_set_change() { // initial 2-of-3 session - let gml = generate_key(1, generate_nodes_ids(3)); - let master_node_id = gml.nodes.keys().cloned().nth(0).unwrap(); + let gml = generate_key(3, 1); - // insert 1 node so that it becames 2-of-4 session - let nodes_to_add: BTreeSet<_> = (0..1).map(|_| Random.generate().unwrap().public().clone()).collect(); - let mut ml = MessageLoop::new(&gml, master_node_id, None, nodes_to_add, BTreeSet::new(), BTreeSet::new()); - ml.nodes[&master_node_id].session.initialize(ml.nodes.keys().cloned().collect(), ml.all_set_signature.clone(), ml.new_set_signature.clone()).unwrap(); - ml.run(); + // add 1 node so that it becames 2-of-4 session + let add = vec![Random.generate().unwrap()]; + let master = gml.0.node(0); + let ml = MessageLoop::with_gml::(gml, master, Some(add), None, None).run_at(master); // try to recover secret for every possible combination of nodes && check that secret is the same - check_secret_is_preserved(ml.original_key_pair.clone(), ml.nodes.iter().map(|(k, v)| (k.clone(), v.key_storage.clone())).collect()); - - // check that all sessions have finished - assert!(ml.nodes.values().all(|n| n.session.is_finished())); + ml.check_secret_is_preserved(ml.sessions.keys()); } #[test] fn node_added_using_server_set_change_from_this_node() { // initial 2-of-3 session - let gml = generate_key(1, generate_nodes_ids(3)); + let gml = generate_key(3, 1); // insert 1 node so that it becames 2-of-4 session // master node is the node we are adding => // 1) add session is delegated to one of old nodes // 2) key share is pushed to new node // 3) delegated session is returned back to added node - let nodes_to_add: BTreeSet<_> = (0..1).map(|_| Random.generate().unwrap().public().clone()).collect(); - let master_node_id = nodes_to_add.iter().cloned().nth(0).unwrap(); - let mut ml = MessageLoop::new(&gml, master_node_id, None, nodes_to_add, BTreeSet::new(), BTreeSet::new()); - ml.nodes[&master_node_id].session.initialize(ml.nodes.keys().cloned().collect(), ml.all_set_signature.clone(), ml.new_set_signature.clone()).unwrap(); - ml.run(); - - // check that all sessions have finished - assert!(ml.nodes.values().all(|n| n.session.is_finished())); + let add = vec![Random.generate().unwrap()]; + let master = add[0].public().clone(); + let ml = MessageLoop::with_gml::(gml, master, Some(add), None, None).run_at(master); + + // try to recover secret for every possible combination of nodes && check that secret is the same + ml.check_secret_is_preserved(ml.sessions.keys()); } #[test] fn node_moved_using_servers_set_change() { // initial 2-of-3 session - let gml = generate_key(1, generate_nodes_ids(3)); - let master_node_id = gml.nodes.keys().cloned().nth(0).unwrap(); + let gml = generate_key(3, 1); // remove 1 node && insert 1 node so that one share is moved - let nodes_to_remove: BTreeSet<_> = gml.nodes.keys().cloned().skip(1).take(1).collect(); - let nodes_to_add: BTreeSet<_> = (0..1).map(|_| Random.generate().unwrap().public().clone()).collect(); - let mut ml = MessageLoop::new(&gml, master_node_id, None, nodes_to_add.clone(), nodes_to_remove.clone(), BTreeSet::new()); - let new_nodes_set = ml.nodes.keys().cloned().filter(|n| !nodes_to_remove.contains(n)).collect(); - ml.nodes[&master_node_id].session.initialize(new_nodes_set, ml.all_set_signature.clone(), ml.new_set_signature.clone()).unwrap(); - ml.run(); + let master = gml.0.node(0); + let remove: BTreeSet<_> = ::std::iter::once(gml.0.node(1)).collect(); + let add = vec![Random.generate().unwrap()]; + let ml = MessageLoop::with_gml::(gml, master, Some(add), Some(remove.clone()), None).run_at(master); // check that secret is still the same as before moving the share - check_secret_is_preserved(ml.original_key_pair.clone(), ml.nodes.iter() - .filter(|&(k, _)| !nodes_to_remove.contains(k)) - .map(|(k, v)| (k.clone(), v.key_storage.clone())) - .collect()); + ml.check_secret_is_preserved(ml.sessions.keys() + .filter(|k| !remove.contains(k))); // check that all removed nodes do not own key share - assert!(ml.nodes.iter().filter(|&(k, _)| nodes_to_remove.contains(k)).all(|(_, v)| v.key_storage.get(&SessionId::default()).unwrap().is_none())); - - // check that all sessions have finished - assert!(ml.nodes.values().all(|n| n.session.is_finished())); + assert!(ml.sessions.keys().filter(|k| remove.contains(k)) + .all(|k| ml.ml.key_storage_of(k).get(&SessionId::default()).unwrap().is_none())); } #[test] fn node_removed_using_servers_set_change() { // initial 2-of-3 session - let gml = generate_key(1, generate_nodes_ids(3)); - let master_node_id = gml.nodes.keys().cloned().nth(0).unwrap(); + let gml = generate_key(3, 1); // remove 1 node so that session becames 2-of-2 - let nodes_to_remove: BTreeSet<_> = gml.nodes.keys().cloned().skip(1).take(1).collect(); - let new_nodes_set: BTreeSet<_> = gml.nodes.keys().cloned().filter(|n| !nodes_to_remove.contains(&n)).collect(); - let mut ml = MessageLoop::new(&gml, master_node_id, None, BTreeSet::new(), nodes_to_remove.clone(), BTreeSet::new()); - ml.nodes[&master_node_id].session.initialize(new_nodes_set, ml.all_set_signature.clone(), ml.new_set_signature.clone()).unwrap(); - ml.run(); + let remove: BTreeSet<_> = ::std::iter::once(gml.0.node(0)).collect(); + let master = gml.0.node(0); + let ml = MessageLoop::with_gml::(gml, master, None, Some(remove.clone()), None).run_at(master); // try to recover secret for every possible combination of nodes && check that secret is the same - check_secret_is_preserved(ml.original_key_pair.clone(), ml.nodes.iter() - .filter(|&(k, _)| !nodes_to_remove.contains(k)) - .map(|(k, v)| (k.clone(), v.key_storage.clone())) - .collect()); + ml.check_secret_is_preserved(ml.sessions.keys() + .filter(|k| !remove.contains(k))); // check that all removed nodes do not own key share - assert!(ml.nodes.iter().filter(|&(k, _)| nodes_to_remove.contains(k)).all(|(_, v)| v.key_storage.get(&SessionId::default()).unwrap().is_none())); - - // check that all sessions have finished - assert!(ml.nodes.values().all(|n| n.session.is_finished())); + assert!(ml.sessions.keys().filter(|k| remove.contains(k)) + .all(|k| ml.ml.key_storage_of(k).get(&SessionId::default()).unwrap().is_none())); } #[test] fn isolated_node_removed_using_servers_set_change() { // initial 2-of-3 session - let gml = generate_key(1, generate_nodes_ids(3)); - let master_node_id = gml.nodes.keys().cloned().nth(0).unwrap(); + let gml = generate_key(3, 1); // remove 1 node so that session becames 2-of-2 - let nodes_to_isolate: BTreeSet<_> = gml.nodes.keys().cloned().skip(1).take(1).collect(); - let new_nodes_set: BTreeSet<_> = gml.nodes.keys().cloned().filter(|n| !nodes_to_isolate.contains(&n)).collect(); - let mut ml = MessageLoop::new(&gml, master_node_id, None, BTreeSet::new(), BTreeSet::new(), nodes_to_isolate.clone()); - ml.nodes[&master_node_id].session.initialize(new_nodes_set, ml.all_set_signature.clone(), ml.new_set_signature.clone()).unwrap(); - ml.run(); + let isolate: BTreeSet<_> = ::std::iter::once(gml.0.node(1)).collect(); + let master = gml.0.node(0); + let ml = MessageLoop::with_gml::(gml, master, None, None, Some(isolate.clone())) + .run_at(master); // try to recover secret for every possible combination of nodes && check that secret is the same - check_secret_is_preserved(ml.original_key_pair.clone(), ml.nodes.iter() - .filter(|&(k, _)| !nodes_to_isolate.contains(k)) - .map(|(k, v)| (k.clone(), v.key_storage.clone())) - .collect()); + ml.check_secret_is_preserved(ml.sessions.keys() + .filter(|k| !isolate.contains(k))); // check that all isolated nodes still OWN key share - assert!(ml.nodes.iter().filter(|&(k, _)| nodes_to_isolate.contains(k)).all(|(_, v)| v.key_storage.get(&SessionId::default()).unwrap().is_some())); - - // check that all sessions have finished - assert!(ml.nodes.iter().filter(|&(k, _)| !nodes_to_isolate.contains(k)).all(|(_, v)| v.session.is_finished())); + assert!(ml.sessions.keys().filter(|k| isolate.contains(k)) + .all(|k| ml.ml.key_storage_of(k).get(&SessionId::default()).unwrap().is_some())); } #[test] fn having_less_than_required_nodes_after_change_does_not_fail_change_session() { // initial 2-of-3 session - let gml = generate_key(1, generate_nodes_ids(3)); - let master_node_id = gml.nodes.keys().cloned().nth(0).unwrap(); + let gml = generate_key(3, 1); - // remove 2 nodes so that key becomes irrecoverable (make sure the session is completed, even though key is irrecoverable) - let nodes_to_remove: BTreeSet<_> = gml.nodes.keys().cloned().skip(1).take(2).collect(); - let new_nodes_set: BTreeSet<_> = gml.nodes.keys().cloned().filter(|n| !nodes_to_remove.contains(&n)).collect(); - let mut ml = MessageLoop::new(&gml, master_node_id, None, BTreeSet::new(), nodes_to_remove.clone(), BTreeSet::new()); - ml.nodes[&master_node_id].session.initialize(new_nodes_set, ml.all_set_signature.clone(), ml.new_set_signature.clone()).unwrap(); - ml.run(); + // remove 2 nodes so that key becomes irrecoverable (make sure the session is completed + // even though key is irrecoverable) + let remove: BTreeSet<_> = gml.0.nodes().into_iter().skip(1).take(2).collect(); + let master = gml.0.node(0); + let ml = MessageLoop::with_gml::(gml, master, None, Some(remove.clone()), None).run_at(master); // check that all removed nodes do not own key share - assert!(ml.nodes.iter().filter(|&(k, _)| nodes_to_remove.contains(k)).all(|(_, v)| v.key_storage.get(&SessionId::default()).unwrap().is_none())); - - // check that all sessions have finished - assert!(ml.nodes.values().all(|n| n.session.is_finished())); + assert!(ml.sessions.keys().filter(|k| remove.contains(k)) + .all(|k| ml.ml.key_storage_of(k).get(&SessionId::default()).unwrap().is_none())); // and now let's add new node (make sure the session is completed, even though key is still irrecoverable) // isolated here are not actually isolated, but removed on the previous step - let nodes_to_add: BTreeSet<_> = (0..1).map(|_| Random.generate().unwrap().public().clone()).collect(); - let new_nodes_set: BTreeSet<_> = gml.nodes.keys().cloned().filter(|n| !nodes_to_remove.contains(&n)) - .chain(nodes_to_add.iter().cloned()) - .collect(); - let master_node_id = nodes_to_add.iter().cloned().nth(0).unwrap(); - let mut ml = MessageLoop::new(&gml, master_node_id, Some(ml.original_key_pair.clone()), nodes_to_add.clone(), BTreeSet::new(), nodes_to_remove.clone()); - ml.nodes[&master_node_id].session.initialize(new_nodes_set, ml.all_set_signature.clone(), ml.new_set_signature.clone()).unwrap(); - ml.run(); + let add = vec![Random.generate().unwrap()]; + let master = add[0].public().clone(); + let ml = ml.and_then::(master, Some(add.clone()), None, Some(remove)).run_at(master); // check that all added nodes do not own key share (there's not enough nodes to run share add session) - assert!(ml.nodes.iter().filter(|&(k, _)| nodes_to_add.contains(k)).all(|(_, v)| v.key_storage.get(&SessionId::default()).unwrap().is_none())); - - // check that all sessions have finished - assert!(ml.nodes.iter().filter(|&(k, _)| !nodes_to_remove.contains(k)).all(|(_, n)| n.session.is_finished())); + assert!(ml.sessions.keys().filter(|k| add.iter().any(|n| n.public() == *k)) + .all(|k| ml.ml.key_storage_of(k).get(&SessionId::default()).unwrap().is_none())); } #[test] fn removing_node_from_cluster_of_2_works() { // initial 2-of-2 session - let gml = generate_key(1, generate_nodes_ids(2)); - let master_node_id = gml.nodes.keys().cloned().nth(0).unwrap(); - - // make 2nd node isolated so that key becomes irrecoverable (make sure the session is completed, even though key is irrecoverable) - let nodes_to_isolate: BTreeSet<_> = gml.nodes.keys().cloned().skip(1).take(1).collect(); - let new_nodes_set: BTreeSet<_> = gml.nodes.keys().cloned().filter(|n| !nodes_to_isolate.contains(&n)).collect(); - let mut ml = MessageLoop::new(&gml, master_node_id, None, BTreeSet::new(), BTreeSet::new(), nodes_to_isolate.clone()); - ml.nodes[&master_node_id].session.initialize(new_nodes_set, ml.all_set_signature.clone(), ml.new_set_signature.clone()).unwrap(); - ml.run(); - - // check that session on master node has completed (session on 2nd node is not even started in network mode) - assert!(ml.nodes.values().take(1).all(|n| n.session.is_finished())); + let gml = generate_key(2, 1); + + // make 2nd node isolated so that key becomes irrecoverable (make sure the session is completed, + // even though key is irrecoverable) + let isolate: BTreeSet<_> = gml.0.nodes().into_iter().skip(1).take(1).collect(); + let master = gml.0.node(0); + MessageLoop::with_gml::(gml, master, None, None, Some(isolate)).run_at(master); } #[test] fn adding_node_that_has_lost_its_database_works() { // initial 2-of-2 session - let gml = generate_key(1, generate_nodes_ids(2)); - let master_node_id = gml.nodes.keys().cloned().nth(0).unwrap(); + let gml = generate_key(2, 1); // insert 1 node so that it becames 2-of-3 session - let nodes_to_add: BTreeSet<_> = (0..1).map(|_| Random.generate().unwrap().public().clone()).collect(); - let mut ml = MessageLoop::new(&gml, master_node_id, None, nodes_to_add.clone(), BTreeSet::new(), BTreeSet::new()); - ml.nodes[&master_node_id].session.initialize(ml.nodes.keys().cloned().collect(), ml.all_set_signature.clone(), ml.new_set_signature.clone()).unwrap(); - ml.run(); + let add = vec![Random.generate().unwrap()]; + let master = gml.0.node(0); + let ml = MessageLoop::with_gml::(gml, master, Some(add.clone()), None, None) + .run_at(master); // now let's say new node has lost its db and we're trying to join it again - ml.nodes[nodes_to_add.iter().nth(0).unwrap()].key_storage.clear().unwrap(); + ml.ml.key_storage_of(add[0].public()).clear().unwrap(); // this time old nodes have version, where new node is mentioned, but it doesn't report it when negotiating - let mut ml = MessageLoop::new(&gml, master_node_id, None, nodes_to_add, BTreeSet::new(), BTreeSet::new()); - ml.nodes[&master_node_id].session.initialize(ml.nodes.keys().cloned().collect(), ml.all_set_signature.clone(), ml.new_set_signature.clone()).unwrap(); - ml.run(); + let ml = ml.and_then::(master, Some(add), None, None).run_at(master); // try to recover secret for every possible combination of nodes && check that secret is the same - check_secret_is_preserved(ml.original_key_pair.clone(), ml.nodes.iter().map(|(k, v)| (k.clone(), v.key_storage.clone())).collect()); - - // check that all sessions have finished - assert!(ml.nodes.values().all(|n| n.session.is_finished())); + ml.check_secret_is_preserved(ml.sessions.keys()); } } diff --git a/secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs b/secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs index 0c771006a5..e2af7bc7fa 100644 --- a/secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs +++ b/secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs @@ -318,6 +318,7 @@ impl SessionImpl where T: SessionTransport { new_set_signature), consensus_transport: consensus_transport, })?; + consensus_session.initialize(new_nodes_map.keys().cloned().collect())?; // update data @@ -881,405 +882,197 @@ impl SessionTransport for IsolatedSessionTransport { #[cfg(test)] pub mod tests { - use std::sync::Arc; - use std::collections::{VecDeque, BTreeMap, BTreeSet, HashSet}; - use ethkey::{Random, Generator, Public, KeyPair, Signature, sign}; - use ethereum_types::H256; - use key_server_cluster::{NodeId, SessionId, Error, KeyStorage, DummyKeyStorage}; - use key_server_cluster::cluster::Cluster; - use key_server_cluster::cluster::tests::DummyCluster; - use key_server_cluster::cluster_sessions::ClusterSession; - use key_server_cluster::generation_session::tests::{Node as GenerationNode, generate_nodes_ids}; - use key_server_cluster::math; - use key_server_cluster::message::Message; - use key_server_cluster::servers_set_change_session::tests::generate_key; - use key_server_cluster::jobs::servers_set_change_access_job::ordered_nodes_hash; + use std::collections::BTreeSet; + use ethkey::{Random, Generator, Public}; + use key_server_cluster::{NodeId, Error, KeyStorage, NodeKeyPair}; + use key_server_cluster::cluster::tests::MessageLoop as ClusterMessageLoop; + use key_server_cluster::servers_set_change_session::tests::{MessageLoop, AdminSessionAdapter, generate_key}; use key_server_cluster::admin_sessions::ShareChangeSessionMeta; use super::{SessionImpl, SessionParams, IsolatedSessionTransport}; - struct Node { - pub cluster: Arc, - pub key_storage: Arc, - pub session: SessionImpl, - } - - struct MessageLoop { - pub admin_key_pair: KeyPair, - pub original_key_pair: KeyPair, - pub old_nodes_set: BTreeSet, - pub new_nodes_set: BTreeSet, - pub old_set_signature: Signature, - pub new_set_signature: Signature, - pub nodes: BTreeMap, - pub queue: VecDeque<(NodeId, NodeId, Message)>, - pub version: H256, - } - - fn create_session(mut meta: ShareChangeSessionMeta, admin_public: Public, self_node_id: NodeId, cluster: Arc, key_storage: Arc) -> SessionImpl { - let session_id = meta.id.clone(); - meta.self_node_id = self_node_id; - let key_version = key_storage.get(&session_id).unwrap().map(|ks| ks.versions.iter().last().unwrap().hash.clone()); - - SessionImpl::new(SessionParams { - meta: meta.clone(), - transport: IsolatedSessionTransport::new(session_id, key_version, 1, cluster), - key_storage: key_storage, - admin_public: Some(admin_public), - nonce: 1, - }).unwrap() - } - - fn create_node(meta: ShareChangeSessionMeta, admin_public: Public, node: GenerationNode, added_nodes: &BTreeSet) -> Node { - node.cluster.add_nodes(added_nodes.iter().cloned()); - Node { - cluster: node.cluster.clone(), - key_storage: node.key_storage.clone(), - session: create_session(meta, admin_public, node.session.node().clone(), node.cluster, node.key_storage), - } - } - - /// This only works for schemes where threshold = 1 - pub fn check_secret_is_preserved(joint_key_pair: KeyPair, nodes: BTreeMap>) { - let n = nodes.len(); - let document_secret_plain = math::generate_random_point().unwrap(); - for n1 in 0..n { - for n2 in n1+1..n { - let share1 = nodes.values().nth(n1).unwrap().get(&SessionId::default()).unwrap(); - let share2 = nodes.values().nth(n2).unwrap().get(&SessionId::default()).unwrap(); - let id_number1 = share1.as_ref().unwrap().last_version().unwrap().id_numbers[nodes.keys().nth(n1).unwrap()].clone(); - let id_number2 = share1.as_ref().unwrap().last_version().unwrap().id_numbers[nodes.keys().nth(n2).unwrap()].clone(); - - // now encrypt and decrypt data - let (document_secret_decrypted, document_secret_decrypted_test) = - math::tests::do_encryption_and_decryption(1, - joint_key_pair.public(), - &[id_number1, id_number2], - &[share1.unwrap().last_version().unwrap().secret_share.clone(), - share2.unwrap().last_version().unwrap().secret_share.clone()], - Some(joint_key_pair.secret()), - document_secret_plain.clone()); - - assert_eq!(document_secret_plain, document_secret_decrypted_test); - assert_eq!(document_secret_plain, document_secret_decrypted); - } + struct Adapter; + + impl AdminSessionAdapter> for Adapter { + const SIGN_NEW_NODES: bool = false; + + fn create( + mut meta: ShareChangeSessionMeta, + admin_public: Public, + _: BTreeSet, + ml: &ClusterMessageLoop, + idx: usize + ) -> SessionImpl { + let key_storage = ml.key_storage(idx).clone(); + let key_version = key_storage.get(&meta.id).unwrap().map(|ks| ks.last_version().unwrap().hash); + + meta.self_node_id = *ml.node_key_pair(idx).public(); + SessionImpl::new(SessionParams { + meta: meta.clone(), + transport: IsolatedSessionTransport::new(meta.id, key_version, 1, ml.cluster(idx).view().unwrap()), + key_storage, + admin_public: Some(admin_public), + nonce: 1, + }).unwrap() } } - impl MessageLoop { - pub fn new(t: usize, master_node_id: NodeId, old_nodes_set: BTreeSet, new_nodes_set: BTreeSet) -> Self { - // generate admin key pair - let admin_key_pair = Random.generate().unwrap(); - let admin_public = admin_key_pair.public().clone(); - - // run initial generation session - let gml = generate_key(t, old_nodes_set.clone()); - - // compute original secret key - let version = gml.nodes.values().nth(0).unwrap().key_storage.get(&Default::default()).unwrap().unwrap().versions[0].hash.clone(); - let original_key_pair = gml.compute_key_pair(t); - - // prepare sessions on all nodes - let meta = ShareChangeSessionMeta { - id: SessionId::default(), - self_node_id: NodeId::default(), - master_node_id: master_node_id, - configured_nodes_count: new_nodes_set.iter().chain(old_nodes_set.iter()).collect::>().len(), - connected_nodes_count: new_nodes_set.iter().chain(old_nodes_set.iter()).collect::>().len(), - }; - let new_nodes = new_nodes_set.iter() - .filter(|n| !old_nodes_set.contains(&n)) - .map(|new_node_id| { - let new_node_cluster = Arc::new(DummyCluster::new(new_node_id.clone())); - let new_node_key_storage = Arc::new(DummyKeyStorage::default()); - let new_node_session = create_session(meta.clone(), admin_public.clone(), new_node_id.clone(), new_node_cluster.clone(), new_node_key_storage.clone()); - new_node_cluster.add_nodes(new_nodes_set.iter().cloned()); - Node { - cluster: new_node_cluster, - key_storage: new_node_key_storage, - session: new_node_session, - } - }); - let old_nodes = gml.nodes.into_iter().map(|gn| create_node(meta.clone(), admin_public.clone(), gn.1, &new_nodes_set)); - let nodes = old_nodes.chain(new_nodes).map(|n| (n.session.core.meta.self_node_id.clone(), n)).collect(); - - let old_set_signature = sign(admin_key_pair.secret(), &ordered_nodes_hash(&old_nodes_set)).unwrap(); - let new_set_signature = sign(admin_key_pair.secret(), &ordered_nodes_hash(&new_nodes_set)).unwrap(); - MessageLoop { - admin_key_pair: admin_key_pair, - original_key_pair: original_key_pair, - version: version, - old_nodes_set: old_nodes_set.clone(), - new_nodes_set: new_nodes_set.clone(), - old_set_signature: old_set_signature, - new_set_signature: new_set_signature, - nodes: nodes, - queue: Default::default(), - } - } - - pub fn new_additional(master_node_id: NodeId, ml: MessageLoop, new_nodes_set: BTreeSet) -> Self { - let version = ml.nodes.values().nth(0).unwrap().key_storage.get(&Default::default()).unwrap().unwrap().versions.last().unwrap().hash.clone(); - - // prepare sessions on all nodes - let meta = ShareChangeSessionMeta { - id: SessionId::default(), - self_node_id: NodeId::default(), - master_node_id: master_node_id, - configured_nodes_count: new_nodes_set.iter().chain(ml.nodes.keys()).collect::>().len(), - connected_nodes_count: new_nodes_set.iter().chain(ml.nodes.keys()).collect::>().len(), - }; - let old_nodes_set = ml.nodes.keys().cloned().collect(); - let nodes = ml.nodes.iter() - .map(|(n, nd)| { - let node_cluster = nd.cluster.clone(); - let node_key_storage = nd.key_storage.clone(); - let node_session = create_session(meta.clone(), ml.admin_key_pair.public().clone(), n.clone(), node_cluster.clone(), node_key_storage.clone()); - node_cluster.add_nodes(new_nodes_set.iter().cloned()); - (n.clone(), Node { - cluster: node_cluster, - key_storage: node_key_storage, - session: node_session, - }) - }).chain(new_nodes_set.difference(&old_nodes_set).map(|n| { - let new_node_cluster = Arc::new(DummyCluster::new(n.clone())); - let new_node_key_storage = Arc::new(DummyKeyStorage::default()); - let new_node_session = create_session(meta.clone(), ml.admin_key_pair.public().clone(), n.clone(), new_node_cluster.clone(), new_node_key_storage.clone()); - new_node_cluster.add_nodes(new_nodes_set.iter().cloned()); - (n.clone(), Node { - cluster: new_node_cluster, - key_storage: new_node_key_storage, - session: new_node_session, - }) - })).collect(); - - let old_set_signature = sign(ml.admin_key_pair.secret(), &ordered_nodes_hash(&old_nodes_set)).unwrap(); - let new_set_signature = sign(ml.admin_key_pair.secret(), &ordered_nodes_hash(&new_nodes_set)).unwrap(); - MessageLoop { - admin_key_pair: ml.admin_key_pair, - original_key_pair: ml.original_key_pair, - version: version, - old_nodes_set: old_nodes_set.clone(), - new_nodes_set: new_nodes_set.clone(), - old_set_signature: old_set_signature, - new_set_signature: new_set_signature, - nodes: nodes, - queue: Default::default(), - } + impl MessageLoop> { + pub fn init_at(self, master: NodeId) -> Result { + self.sessions[&master].initialize( + Some(self.original_key_version), + Some(self.new_nodes_set.clone()), + Some(self.all_set_signature.clone()), + Some(self.new_set_signature.clone()))?; + Ok(self) } - pub fn update_signature(&mut self) { - self.old_set_signature = sign(self.admin_key_pair.secret(), &ordered_nodes_hash(&self.old_nodes_set)).unwrap(); - self.new_set_signature = sign(self.admin_key_pair.secret(), &ordered_nodes_hash(&self.new_nodes_set)).unwrap(); - } - - pub fn run(&mut self) { - while let Some((from, to, message)) = self.take_message() { - self.process_message((from, to, message)).unwrap(); - } - } - - pub fn take_message(&mut self) -> Option<(NodeId, NodeId, Message)> { - self.nodes.values() - .filter_map(|n| n.cluster.take_message().map(|m| (n.session.core.meta.self_node_id.clone(), m.0, m.1))) - .nth(0) - .or_else(|| self.queue.pop_front()) - } - - pub fn process_message(&mut self, msg: (NodeId, NodeId, Message)) -> Result<(), Error> { - match { match msg.2 { - Message::ShareAdd(ref message) => - self.nodes[&msg.1].session.process_message(&msg.0, message), - _ => unreachable!("only servers set change messages are expected"), - } } { - Ok(_) => Ok(()), - Err(Error::TooEarlyForRequest) => { - self.queue.push_back(msg); - Ok(()) - }, - Err(err) => Err(err), - } + pub fn run_at(self, master: NodeId) -> Result { + let mut ml = self.init_at(master)?; + ml.run(); + Ok(ml) } } #[test] fn node_add_fails_if_nodes_removed() { - let old_nodes_set = generate_nodes_ids(3); - let master_node_id = old_nodes_set.iter().cloned().nth(0).unwrap(); - let node_to_remove_id = old_nodes_set.iter().cloned().nth(1).unwrap(); - let mut new_nodes_set: BTreeSet<_> = old_nodes_set.clone().into_iter().chain(generate_nodes_ids(1)).collect(); - new_nodes_set.remove(&node_to_remove_id); - let ml = MessageLoop::new(1, master_node_id.clone(), old_nodes_set, new_nodes_set.clone()); - assert_eq!(ml.nodes[&master_node_id].session.initialize(Some(ml.version), Some(new_nodes_set), - Some(ml.old_set_signature.clone()), - Some(ml.new_set_signature.clone()) - ).unwrap_err(), Error::ConsensusUnreachable); + // initial 2-of-3 session + let gml = generate_key(3, 1); + + // try to remove 1 node + let add = vec![Random.generate().unwrap()]; + let remove: BTreeSet<_> = ::std::iter::once(gml.0.node(1)).collect(); + let master = gml.0.node(0); + assert_eq!(MessageLoop::with_gml::(gml, master, Some(add), Some(remove), None) + .run_at(master).unwrap_err(), Error::ConsensusUnreachable); } #[test] fn node_add_fails_if_no_nodes_added() { - let old_nodes_set = generate_nodes_ids(3); - let master_node_id = old_nodes_set.iter().cloned().nth(0).unwrap(); - let new_nodes_set = old_nodes_set.clone(); - let ml = MessageLoop::new(1, master_node_id.clone(), old_nodes_set, new_nodes_set.clone()); - assert_eq!(ml.nodes[&master_node_id].session.initialize(Some(ml.version), Some(new_nodes_set), - Some(ml.old_set_signature.clone()), - Some(ml.new_set_signature.clone()) - ).unwrap_err(), Error::ConsensusUnreachable); + // initial 2-of-3 session + let gml = generate_key(3, 1); + + // try to add 0 nodes + let add = vec![]; + let master = gml.0.node(0); + assert_eq!(MessageLoop::with_gml::(gml, master, Some(add), None, None) + .run_at(master).unwrap_err(), Error::ConsensusUnreachable); } #[test] fn node_add_fails_if_started_on_adding_node() { - let old_nodes_set = generate_nodes_ids(3); - let nodes_to_add_set = generate_nodes_ids(1); - let master_node_id = nodes_to_add_set.iter().cloned().nth(0).unwrap(); - let new_nodes_set: BTreeSet<_> = old_nodes_set.clone().into_iter().chain(nodes_to_add_set.into_iter()).collect(); - let ml = MessageLoop::new(1, master_node_id.clone(), old_nodes_set, new_nodes_set.clone()); - assert_eq!(ml.nodes[&master_node_id].session.initialize(Some(ml.version), Some(new_nodes_set), - Some(ml.old_set_signature.clone()), - Some(ml.new_set_signature.clone()) - ).unwrap_err(), Error::ServerKeyIsNotFound); + // initial 2-of-3 session + let gml = generate_key(3, 1); + + // try to add 1 node using this node as a master node + let add = vec![Random.generate().unwrap()]; + let master = *add[0].public(); + assert_eq!(MessageLoop::with_gml::(gml, master, Some(add), None, None) + .run_at(master).unwrap_err(), Error::ServerKeyIsNotFound); } #[test] fn node_add_fails_if_initialized_twice() { - let old_nodes_set = generate_nodes_ids(3); - let master_node_id = old_nodes_set.iter().cloned().nth(0).unwrap(); - let new_nodes_set: BTreeSet<_> = old_nodes_set.clone().into_iter().chain(generate_nodes_ids(1)).collect(); - let ml = MessageLoop::new(1, master_node_id.clone(), old_nodes_set, new_nodes_set.clone()); - assert_eq!(ml.nodes[&master_node_id].session.initialize(Some(ml.version), Some(new_nodes_set.clone()), - Some(ml.old_set_signature.clone()), - Some(ml.new_set_signature.clone()) - ), Ok(())); - assert_eq!(ml.nodes[&master_node_id].session.initialize(Some(ml.version), Some(new_nodes_set), - Some(ml.old_set_signature.clone()), - Some(ml.new_set_signature.clone()) - ), Err(Error::InvalidStateForRequest)); + // initial 2-of-3 session + let gml = generate_key(3, 1); + + // try to add 1 node using this node as a master node + let add = vec![Random.generate().unwrap()]; + let master = gml.0.node(0); + assert_eq!(MessageLoop::with_gml::(gml, master, Some(add), None, None) + .init_at(master).unwrap() + .init_at(master).unwrap_err(), Error::InvalidStateForRequest); } #[test] fn node_add_fails_if_started_without_signatures() { - let old_nodes_set = generate_nodes_ids(3); - let master_node_id = old_nodes_set.iter().cloned().nth(0).unwrap(); - let new_nodes_set: BTreeSet<_> = old_nodes_set.clone().into_iter().chain(generate_nodes_ids(1)).collect(); - let ml = MessageLoop::new(1, master_node_id.clone(), old_nodes_set, new_nodes_set.clone()); - assert_eq!(ml.nodes[&master_node_id].session.initialize(None, None, None, None), Err(Error::InvalidMessage)); + // initial 2-of-3 session + let gml = generate_key(3, 1); + + // try to add 1 node using this node as a master node + let add = vec![Random.generate().unwrap()]; + let master = gml.0.node(0); + assert_eq!(MessageLoop::with_gml::(gml, master, Some(add), None, None) + .sessions[&master] + .initialize(None, None, None, None).unwrap_err(), Error::InvalidMessage); } #[test] fn nodes_added_using_share_add() { let test_cases = vec![(3, 1), (3, 3)]; - for (n, nodes_to_add) in test_cases { - // generate key && prepare ShareAdd sessions - let old_nodes_set = generate_nodes_ids(n); - let new_nodes_set: BTreeSet<_> = old_nodes_set.clone().into_iter().chain(generate_nodes_ids(nodes_to_add)).collect(); - let master_node_id = old_nodes_set.iter().cloned().nth(0).unwrap(); - let mut ml = MessageLoop::new(1, master_node_id.clone(), old_nodes_set, new_nodes_set.clone()); - - // initialize session on master node && run to completion - ml.nodes[&master_node_id].session.initialize(Some(ml.version), Some(new_nodes_set), - Some(ml.old_set_signature.clone()), - Some(ml.new_set_signature.clone())).unwrap(); - ml.run(); + for (n, add) in test_cases { + // generate key + let gml = generate_key(n, 1); - // check that session has completed on all nodes - assert!(ml.nodes.values().all(|n| n.session.is_finished())); + // run share add session + let add = (0..add).map(|_| Random.generate().unwrap()).collect(); + let master = gml.0.node(0); + let ml = MessageLoop::with_gml::(gml, master, Some(add), None, None) + .run_at(master).unwrap(); // check that secret is still the same as before adding the share - check_secret_is_preserved(ml.original_key_pair.clone(), ml.nodes.iter().map(|(k, v)| (k.clone(), v.key_storage.clone())).collect()); + ml.check_secret_is_preserved(ml.sessions.keys()); } } #[test] fn nodes_added_using_share_add_with_isolated_nodes() { - let (n, nodes_to_add) = (3, 3); - - // generate key && prepare ShareAdd sessions - let old_nodes_set = generate_nodes_ids(n); - let new_nodes_set: BTreeSet<_> = old_nodes_set.clone().into_iter().chain(generate_nodes_ids(nodes_to_add)).collect(); - let master_node_id = old_nodes_set.iter().cloned().nth(0).unwrap(); - let isolated_node_id = old_nodes_set.iter().cloned().nth(1).unwrap(); - let mut ml = MessageLoop::new(1, master_node_id.clone(), old_nodes_set, new_nodes_set.clone()); - - // now let's isolate 1 of 3 nodes owning key share - ml.nodes.remove(&isolated_node_id); - ml.old_nodes_set.remove(&isolated_node_id); - ml.new_nodes_set.remove(&isolated_node_id); - for (_, node) in ml.nodes.iter_mut() { - node.cluster.remove_node(&isolated_node_id); - } - ml.update_signature(); + let (n, add) = (3, 3); - // initialize session on master node && run to completion - ml.nodes[&master_node_id].session.initialize(Some(ml.version), Some(new_nodes_set), - Some(ml.old_set_signature.clone()), - Some(ml.new_set_signature.clone())).unwrap(); - ml.run(); + // generate key + let gml = generate_key(n, 1); - // check that session has completed on all nodes - assert!(ml.nodes.values().all(|n| n.session.is_finished())); + // run share add session + let master = gml.0.node(0); + let node_to_isolate = gml.0.node(1); + let add = (0..add).map(|_| Random.generate().unwrap()).collect(); + let isolate = ::std::iter::once(node_to_isolate).collect(); + let ml = MessageLoop::with_gml::(gml, master, Some(add), None, Some(isolate)) + .run_at(master).unwrap(); // check that secret is still the same as before adding the share - check_secret_is_preserved(ml.original_key_pair.clone(), ml.nodes - .iter() - .map(|(k, v)| (k.clone(), v.key_storage.clone())) - .collect()); + ml.check_secret_is_preserved(ml.sessions.keys()); } #[test] fn nodes_add_to_the_node_with_obsolete_version() { - let (n, nodes_to_add) = (3, 3); - - // generate key (2-of-3) && prepare ShareAdd sessions - let old_nodes_set = generate_nodes_ids(n); - let newest_nodes_set = generate_nodes_ids(nodes_to_add); - let new_nodes_set: BTreeSet<_> = old_nodes_set.clone().into_iter().chain(newest_nodes_set.clone()).collect(); - let master_node_id = old_nodes_set.iter().cloned().nth(0).unwrap(); - let isolated_node_id = old_nodes_set.iter().cloned().nth(1).unwrap(); - let oldest_nodes_set: BTreeSet<_> = old_nodes_set.iter().filter(|n| **n != isolated_node_id).cloned().collect(); - let mut ml = MessageLoop::new(1, master_node_id.clone(), old_nodes_set.clone(), new_nodes_set.clone()); - let isolated_key_storage = ml.nodes[&isolated_node_id].key_storage.clone(); - - // now let's isolate 1 of 3 nodes owning key share - ml.nodes.remove(&isolated_node_id); - ml.old_nodes_set.remove(&isolated_node_id); - ml.new_nodes_set.remove(&isolated_node_id); - for (_, node) in ml.nodes.iter_mut() { - node.cluster.remove_node(&isolated_node_id); - } - ml.update_signature(); - - // initialize session on master node && run to completion (2-of-5) - ml.nodes[&master_node_id].session.initialize(Some(ml.version), Some(new_nodes_set), - Some(ml.old_set_signature.clone()), - Some(ml.new_set_signature.clone())).unwrap(); - ml.run(); + let (n, add) = (3, 3); + + // generate key + let gml = generate_key(n, 1); + + // run share add session + let master = gml.0.node(0); + let node_to_isolate_key_pair = gml.0.node_key_pair(1).clone(); + let node_to_isolate = gml.0.node(1); + let isolated_key_storage = gml.0.key_storage(1).clone(); + let mut oldest_nodes_set = gml.0.nodes(); + oldest_nodes_set.remove(&node_to_isolate); + let add = (0..add).map(|_| Random.generate().unwrap()).collect::>(); + let newest_nodes_set = add.iter().map(|kp| *kp.public()).collect::>(); + let isolate = ::std::iter::once(node_to_isolate).collect(); + let ml = MessageLoop::with_gml::(gml, master, Some(add), None, Some(isolate)) + .run_at(master).unwrap(); + let new_key_version = ml.ml.key_storage(0).get(&Default::default()) + .unwrap().unwrap().last_version().unwrap().hash; // now let's add back old node so that key becames 2-of-6 - let new_nodes_set: BTreeSet<_> = ml.nodes.keys().cloned().chain(::std::iter::once(isolated_node_id.clone())).collect(); - let mut ml = MessageLoop::new_additional(master_node_id.clone(), ml, new_nodes_set.clone()); - ml.nodes.get_mut(&isolated_node_id).unwrap().key_storage = isolated_key_storage.clone(); - ml.nodes.get_mut(&isolated_node_id).unwrap().session.core.key_share = isolated_key_storage.get(&Default::default()).unwrap(); - ml.nodes.get_mut(&isolated_node_id).unwrap().session.core.key_storage = isolated_key_storage; - - // initialize session on master node && run to completion (2-of65) - ml.nodes[&master_node_id].session.initialize(Some(ml.version), Some(new_nodes_set), - Some(ml.old_set_signature.clone()), - Some(ml.new_set_signature.clone())).unwrap(); - ml.run(); - - // check that session has completed on all nodes - assert!(ml.nodes.values().all(|n| n.session.is_finished())); + let add = vec![node_to_isolate_key_pair.key_pair().clone()]; + let mut ml = ml.and_then::(master.clone(), Some(add), None, None); + ml.original_key_version = new_key_version; + ml.ml.replace_key_storage_of(&node_to_isolate, isolated_key_storage.clone()); + ml.sessions.get_mut(&node_to_isolate).unwrap().core.key_share = + isolated_key_storage.get(&Default::default()).unwrap(); + ml.sessions.get_mut(&node_to_isolate).unwrap().core.key_storage = isolated_key_storage; + let ml = ml.run_at(master).unwrap(); // check that secret is still the same as before adding the share - check_secret_is_preserved(ml.original_key_pair.clone(), ml.nodes - .iter() - .map(|(k, v)| (k.clone(), v.key_storage.clone())) - .collect()); + ml.check_secret_is_preserved(ml.sessions.keys()); // check that all oldest nodes have versions A, B, C // isolated node has version A, C // new nodes have versions B, C - let oldest_key_share = ml.nodes[oldest_nodes_set.iter().nth(0).unwrap()].key_storage.get(&Default::default()).unwrap().unwrap(); + let oldest_key_share = ml.ml.key_storage_of(oldest_nodes_set.iter().nth(0).unwrap()) + .get(&Default::default()).unwrap().unwrap(); debug_assert_eq!(oldest_key_share.versions.len(), 3); let version_a = oldest_key_share.versions[0].hash.clone(); let version_b = oldest_key_share.versions[1].hash.clone(); @@ -1287,41 +1080,28 @@ pub mod tests { debug_assert!(version_a != version_b && version_b != version_c); debug_assert!(oldest_nodes_set.iter().all(|n| vec![version_a.clone(), version_b.clone(), version_c.clone()] == - ml.nodes[n].key_storage.get(&Default::default()).unwrap().unwrap().versions.iter().map(|v| v.hash.clone()).collect::>())); - debug_assert!(::std::iter::once(&isolated_node_id).all(|n| vec![version_a.clone(), version_c.clone()] == - ml.nodes[n].key_storage.get(&Default::default()).unwrap().unwrap().versions.iter().map(|v| v.hash.clone()).collect::>())); + ml.ml.key_storage_of(n).get(&Default::default()).unwrap().unwrap() + .versions.iter().map(|v| v.hash).collect::>())); + debug_assert!(::std::iter::once(&node_to_isolate).all(|n| vec![version_a.clone(), version_c.clone()] == + ml.ml.key_storage_of(n).get(&Default::default()).unwrap().unwrap() + .versions.iter().map(|v| v.hash).collect::>())); debug_assert!(newest_nodes_set.iter().all(|n| vec![version_b.clone(), version_c.clone()] == - ml.nodes[n].key_storage.get(&Default::default()).unwrap().unwrap().versions.iter().map(|v| v.hash.clone()).collect::>())); + ml.ml.key_storage_of(n).get(&Default::default()).unwrap().unwrap() + .versions.iter().map(|v| v.hash).collect::>())); } #[test] fn nodes_add_fails_when_not_enough_share_owners_are_connected() { - let (n, nodes_to_add) = (3, 3); - - // generate key (2-of-3) && prepare ShareAdd sessions - let old_nodes_set = generate_nodes_ids(n); - let new_nodes_set: BTreeSet<_> = old_nodes_set.clone().into_iter().chain(generate_nodes_ids(nodes_to_add)).collect(); - let master_node_id = old_nodes_set.iter().cloned().nth(0).unwrap(); - let isolated_node_id1 = old_nodes_set.iter().cloned().nth(1).unwrap(); - let isolated_node_id2 = old_nodes_set.iter().cloned().nth(2).unwrap(); - let mut ml = MessageLoop::new(1, master_node_id.clone(), old_nodes_set.clone(), new_nodes_set.clone()); - - // now let's isolate 2 of 3 nodes owning key share - ml.nodes.remove(&isolated_node_id1); - ml.nodes.remove(&isolated_node_id2); - ml.old_nodes_set.remove(&isolated_node_id1); - ml.new_nodes_set.remove(&isolated_node_id1); - ml.old_nodes_set.remove(&isolated_node_id2); - ml.new_nodes_set.remove(&isolated_node_id2); - for (_, node) in ml.nodes.iter_mut() { - node.cluster.remove_node(&isolated_node_id1); - node.cluster.remove_node(&isolated_node_id2); - } - ml.update_signature(); + let (n, add) = (3, 3); + + // generate key + let gml = generate_key(n, 1); - // initialize session on master node && run to completion (2-of-5) - assert_eq!(ml.nodes[&master_node_id].session.initialize(Some(ml.version), Some(new_nodes_set), - Some(ml.old_set_signature.clone()), - Some(ml.new_set_signature.clone())).map(|_| ()), Err(Error::ConsensusUnreachable)); + // run share add session + let master = gml.0.node(0); + let add = (0..add).map(|_| Random.generate().unwrap()).collect::>(); + let isolate = vec![gml.0.node(1), gml.0.node(2)].into_iter().collect(); + assert_eq!(MessageLoop::with_gml::(gml, master, Some(add), None, Some(isolate)) + .run_at(master).unwrap_err(), Error::ConsensusUnreachable); } } diff --git a/secret-store/src/key_server_cluster/client_sessions/generation_session.rs b/secret-store/src/key_server_cluster/client_sessions/generation_session.rs index da2ffebc72..0fa805f571 100644 --- a/secret-store/src/key_server_cluster/client_sessions/generation_session.rs +++ b/secret-store/src/key_server_cluster/client_sessions/generation_session.rs @@ -940,406 +940,315 @@ fn check_threshold(threshold: usize, nodes: &BTreeSet) -> Result<(), Err #[cfg(test)] pub mod tests { use std::sync::Arc; - use std::collections::{BTreeSet, BTreeMap, VecDeque}; - use std::time::Duration; - use ethereum_types::Address; - use ethkey::{Random, Generator, KeyPair}; - use key_server_cluster::{NodeId, SessionId, Error, KeyStorage, DummyKeyStorage}; - use key_server_cluster::message::{self, Message, GenerationMessage}; - use key_server_cluster::cluster::tests::{DummyCluster, make_clusters, run_clusters, loop_until, - all_connections_established, new_runtime}; + use ethereum_types::H256; + use ethkey::{Random, Generator, KeyPair, Secret}; + use key_server_cluster::{NodeId, Error, KeyStorage}; + use key_server_cluster::message::{self, Message, GenerationMessage, KeysDissemination, + PublicKeyShare, ConfirmInitialization}; + use key_server_cluster::cluster::tests::{MessageLoop as ClusterMessageLoop, make_clusters_and_preserve_sessions}; use key_server_cluster::cluster_sessions::ClusterSession; - use key_server_cluster::generation_session::{SessionImpl, SessionState, SessionParams}; + use key_server_cluster::generation_session::{SessionImpl, SessionState}; use key_server_cluster::math; use key_server_cluster::math::tests::do_encryption_and_decryption; - pub struct Node { - pub cluster: Arc, - pub key_storage: Arc, - pub session: SessionImpl, - } - - pub struct MessageLoop { - pub session_id: SessionId, - pub nodes: BTreeMap, - pub queue: VecDeque<(NodeId, NodeId, Message)>, - } - - pub fn generate_nodes_ids(n: usize) -> BTreeSet { - (0..n).map(|_| math::generate_random_point().unwrap()).collect() - } + #[derive(Debug)] + pub struct MessageLoop(pub ClusterMessageLoop); impl MessageLoop { - pub fn new(nodes_num: usize) -> Self { - Self::with_nodes_ids(generate_nodes_ids(nodes_num)) + pub fn new(num_nodes: usize) -> Self { + MessageLoop(make_clusters_and_preserve_sessions(num_nodes)) } - pub fn with_nodes_ids(nodes_ids: BTreeSet) -> Self { - let mut nodes = BTreeMap::new(); - let session_id = SessionId::default(); - for node_id in nodes_ids { - let cluster = Arc::new(DummyCluster::new(node_id.clone())); - let key_storage = Arc::new(DummyKeyStorage::default()); - let session = SessionImpl::new(SessionParams { - id: session_id.clone(), - self_node_id: node_id.clone(), - key_storage: Some(key_storage.clone()), - cluster: cluster.clone(), - nonce: Some(0), - }); - nodes.insert(node_id, Node { cluster: cluster, key_storage: key_storage, session: session }); - } - - let nodes_ids: Vec<_> = nodes.keys().cloned().collect(); - for node in nodes.values() { - for node_id in &nodes_ids { - node.cluster.add_node(node_id.clone()); - } - } - - MessageLoop { - session_id: session_id, - nodes: nodes, - queue: VecDeque::new(), - } + pub fn init(self, threshold: usize) -> Result { + self.0.cluster(0).client().new_generation_session(Default::default(), None, Default::default(), threshold) + .map(|_| self) } - pub fn master(&self) -> &SessionImpl { - &self.nodes.values().nth(0).unwrap().session + pub fn session_at(&self, idx: usize) -> Arc { + self.0.sessions(idx).generation_sessions.first().unwrap() } - pub fn first_slave(&self) -> &SessionImpl { - &self.nodes.values().nth(1).unwrap().session + pub fn session_of(&self, node: &NodeId) -> Arc { + self.0.sessions_of(node).generation_sessions.first().unwrap() } - pub fn second_slave(&self) -> &SessionImpl { - &self.nodes.values().nth(2).unwrap().session + pub fn take_message_confirm_initialization(&self) -> (NodeId, NodeId, ConfirmInitialization) { + match self.0.take_message() { + Some((from, to, Message::Generation(GenerationMessage::ConfirmInitialization(msg)))) => + (from, to, msg), + _ => panic!("unexpected"), + } } - pub fn take_message(&mut self) -> Option<(NodeId, NodeId, Message)> { - self.nodes.values() - .filter_map(|n| n.cluster.take_message().map(|m| (n.session.node().clone(), m.0, m.1))) - .nth(0) - .or_else(|| self.queue.pop_front()) + pub fn take_message_keys_dissemination(&self) -> (NodeId, NodeId, KeysDissemination) { + match self.0.take_message() { + Some((from, to, Message::Generation(GenerationMessage::KeysDissemination(msg)))) => + (from, to, msg), + _ => panic!("unexpected"), + } } - pub fn process_message(&mut self, msg: (NodeId, NodeId, Message)) -> Result<(), Error> { - match { - match msg.2 { - Message::Generation(GenerationMessage::InitializeSession(ref message)) => self.nodes[&msg.1].session.on_initialize_session(msg.0.clone(), &message), - Message::Generation(GenerationMessage::ConfirmInitialization(ref message)) => self.nodes[&msg.1].session.on_confirm_initialization(msg.0.clone(), &message), - Message::Generation(GenerationMessage::CompleteInitialization(ref message)) => self.nodes[&msg.1].session.on_complete_initialization(msg.0.clone(), &message), - Message::Generation(GenerationMessage::KeysDissemination(ref message)) => self.nodes[&msg.1].session.on_keys_dissemination(msg.0.clone(), &message), - Message::Generation(GenerationMessage::PublicKeyShare(ref message)) => self.nodes[&msg.1].session.on_public_key_share(msg.0.clone(), &message), - Message::Generation(GenerationMessage::SessionCompleted(ref message)) => self.nodes[&msg.1].session.on_session_completed(msg.0.clone(), &message), - _ => panic!("unexpected"), - } - } { - Ok(_) => Ok(()), - Err(Error::TooEarlyForRequest) => { - self.queue.push_back(msg); - Ok(()) - }, - Err(err) => Err(err), + pub fn take_message_public_key_share(&self) -> (NodeId, NodeId, PublicKeyShare) { + match self.0.take_message() { + Some((from, to, Message::Generation(GenerationMessage::PublicKeyShare(msg)))) => + (from, to, msg), + _ => panic!("unexpected"), } } - pub fn take_and_process_message(&mut self) -> Result<(), Error> { - let msg = self.take_message().unwrap(); - self.process_message(msg) + pub fn nodes_id_numbers(&self) -> Vec { + let session = self.session_at(0); + let session_data = session.data.lock(); + session_data.nodes.values().map(|n| n.id_number.clone()).collect() } - pub fn compute_key_pair(&self, t: usize) -> KeyPair { - let secret_shares = self.nodes.values() - .map(|nd| nd.key_storage.get(&SessionId::default()).unwrap().unwrap().last_version().unwrap().secret_share.clone()) - .take(t + 1) - .collect::>(); - let secret_shares = secret_shares.iter().collect::>(); - let id_numbers = self.nodes.iter() - .map(|(n, nd)| nd.key_storage.get(&SessionId::default()).unwrap().unwrap().last_version().unwrap().id_numbers[n].clone()) - .take(t + 1) - .collect::>(); - let id_numbers = id_numbers.iter().collect::>(); - let joint_secret1 = math::compute_joint_secret_from_shares(t, &secret_shares, &id_numbers).unwrap(); - - let secret_values: Vec<_> = self.nodes.values().map(|s| s.session.joint_public_and_secret().unwrap().unwrap().1).collect(); - let joint_secret2 = math::compute_joint_secret(secret_values.iter()).unwrap(); - assert_eq!(joint_secret1, joint_secret2); - - KeyPair::from_secret(joint_secret1).unwrap() + pub fn nodes_secret_shares(&self) -> Vec { + (0..self.0.nodes().len()).map(|i| { + let session = self.session_at(i); + let session_data = session.data.lock(); + session_data.secret_share.as_ref().unwrap().clone() + }).collect() } - } - fn make_simple_cluster(threshold: usize, num_nodes: usize) -> Result<(SessionId, NodeId, NodeId, MessageLoop), Error> { - let l = MessageLoop::new(num_nodes); - l.master().initialize(Default::default(), Default::default(), false, threshold, l.nodes.keys().cloned().collect::>().into())?; + pub fn compute_key_pair(&self) -> KeyPair { + let t = self.0.key_storage(0).get(&Default::default()).unwrap().unwrap().threshold; + let secret_shares = self.nodes_secret_shares(); + let id_numbers = self.nodes_id_numbers(); + let secret_shares = secret_shares.iter().take(t + 1).collect::>(); + let id_numbers = id_numbers.iter().take(t + 1).collect::>(); + let joint_secret = math::compute_joint_secret_from_shares(t, &secret_shares, &id_numbers).unwrap(); + + KeyPair::from_secret(joint_secret).unwrap() + } - let session_id = l.session_id.clone(); - let master_id = l.master().node().clone(); - let slave_id = l.first_slave().node().clone(); - Ok((session_id, master_id, slave_id, l)) + pub fn key_version(&self) -> H256 { + self.0.key_storage(0).get(&Default::default()) + .unwrap().unwrap().versions.iter().last().unwrap().hash + } } #[test] fn initializes_in_cluster_of_single_node() { - let l = MessageLoop::new(1); - assert!(l.master().initialize(Default::default(), Default::default(), false, 0, l.nodes.keys().cloned().collect::>().into()).is_ok()); + MessageLoop::new(1).init(0).unwrap(); } #[test] fn fails_to_initialize_if_threshold_is_wrong() { - match make_simple_cluster(2, 2) { - Err(Error::NotEnoughNodesForThreshold) => (), - _ => panic!("unexpected"), - } + assert_eq!(MessageLoop::new(2).init(2).unwrap_err(), Error::NotEnoughNodesForThreshold); } #[test] fn fails_to_initialize_when_already_initialized() { - let (_, _, _, l) = make_simple_cluster(0, 2).unwrap(); - assert_eq!(l.master().initialize(Default::default(), Default::default(), false, 0, l.nodes.keys().cloned().collect::>().into()).unwrap_err(), - Error::InvalidStateForRequest); + let ml = MessageLoop::new(2).init(0).unwrap(); + assert_eq!( + ml.session_at(0).initialize(Default::default(), Default::default(), false, 0, ml.0.nodes().into()), + Err(Error::InvalidStateForRequest), + ); } #[test] fn fails_to_accept_initialization_when_already_initialized() { - let (_, _, _, mut l) = make_simple_cluster(0, 2).unwrap(); - let message = l.take_message().unwrap(); - l.process_message(message.clone()).unwrap(); - assert_eq!(l.process_message(message.clone()).unwrap_err(), Error::InvalidStateForRequest); + let ml = MessageLoop::new(2).init(0).unwrap(); + let (from, to, msg) = ml.0.take_message().unwrap(); + ml.0.process_message(from, to, msg.clone()); + assert_eq!( + ml.session_of(&to).on_message(&from, &msg), + Err(Error::InvalidStateForRequest), + ); } #[test] fn slave_updates_derived_point_on_initialization() { - let (_, _, _, mut l) = make_simple_cluster(0, 2).unwrap(); - let passed_point = match l.take_message().unwrap() { - (f, t, Message::Generation(GenerationMessage::InitializeSession(message))) => { - let point = message.derived_point.clone(); - l.process_message((f, t, Message::Generation(GenerationMessage::InitializeSession(message)))).unwrap(); - point + let ml = MessageLoop::new(2).init(0).unwrap(); + let original_point = match ml.0.take_message().unwrap() { + (from, to, Message::Generation(GenerationMessage::InitializeSession(msg))) => { + let original_point = msg.derived_point.clone(); + let msg = Message::Generation(GenerationMessage::InitializeSession(msg)); + ml.0.process_message(from, to, msg); + original_point }, _ => panic!("unexpected"), }; - match l.take_message().unwrap() { - (_, _, Message::Generation(GenerationMessage::ConfirmInitialization(message))) => assert!(passed_point != message.derived_point), + match ml.0.take_message().unwrap() { + (_, _, Message::Generation(GenerationMessage::ConfirmInitialization(msg))) => + assert!(original_point != msg.derived_point), _ => panic!("unexpected"), } } #[test] fn fails_to_accept_initialization_confirmation_if_already_accepted_from_the_same_node() { - let (sid, _, s, mut l) = make_simple_cluster(0, 3).unwrap(); - l.take_and_process_message().unwrap(); - l.take_and_process_message().unwrap(); - l.take_and_process_message().unwrap(); - assert_eq!(l.master().on_confirm_initialization(s, &message::ConfirmInitialization { - session: sid.into(), - session_nonce: 0, - derived_point: math::generate_random_point().unwrap().into(), - }).unwrap_err(), Error::InvalidStateForRequest); + let ml = MessageLoop::new(3).init(0).unwrap(); + ml.0.take_and_process_message(); + + let (from, to, msg) = ml.take_message_confirm_initialization(); + ml.0.process_message(from, to, Message::Generation(GenerationMessage::ConfirmInitialization(msg.clone()))); + assert_eq!(ml.session_of(&to).on_confirm_initialization(from, &msg), Err(Error::InvalidStateForRequest)); } #[test] fn fails_to_accept_initialization_confirmation_if_initialization_already_completed() { - let (sid, _, s, mut l) = make_simple_cluster(0, 2).unwrap(); - l.take_and_process_message().unwrap(); - l.take_and_process_message().unwrap(); - assert_eq!(l.master().on_confirm_initialization(s, &message::ConfirmInitialization { - session: sid.into(), + let ml = MessageLoop::new(2).init(0).unwrap(); + ml.0.take_and_process_message(); + ml.0.take_and_process_message(); + assert_eq!(ml.session_at(0).on_confirm_initialization(ml.0.node(1), &message::ConfirmInitialization { + session: Default::default(), session_nonce: 0, derived_point: math::generate_random_point().unwrap().into(), - }).unwrap_err(), Error::InvalidStateForRequest); + }), Err(Error::InvalidStateForRequest)); } #[test] fn master_updates_derived_point_on_initialization_completion() { - let (_, _, _, mut l) = make_simple_cluster(0, 2).unwrap(); - l.take_and_process_message().unwrap(); - let passed_point = match l.take_message().unwrap() { - (f, t, Message::Generation(GenerationMessage::ConfirmInitialization(message))) => { - let point = message.derived_point.clone(); - l.process_message((f, t, Message::Generation(GenerationMessage::ConfirmInitialization(message)))).unwrap(); - point + let ml = MessageLoop::new(2).init(0).unwrap(); + ml.0.take_and_process_message(); + let original_point = match ml.0.take_message().unwrap() { + (from, to, Message::Generation(GenerationMessage::ConfirmInitialization(msg))) => { + let original_point = msg.derived_point.clone(); + let msg = Message::Generation(GenerationMessage::ConfirmInitialization(msg)); + ml.session_of(&to).on_message(&from, &msg).unwrap(); + original_point }, _ => panic!("unexpected"), }; - assert!(l.master().derived_point().unwrap() != passed_point.into()); - } - - #[test] - fn fails_to_complete_initialization_if_threshold_is_wrong() { - let (sid, m, s, l) = make_simple_cluster(0, 2).unwrap(); - let mut nodes = BTreeMap::new(); - nodes.insert(m, math::generate_random_scalar().unwrap()); - nodes.insert(s, math::generate_random_scalar().unwrap()); - assert_eq!(l.first_slave().on_initialize_session(m, &message::InitializeSession { - session: sid.into(), - session_nonce: 0, - origin: None, - author: Address::default().into(), - nodes: nodes.into_iter().map(|(k, v)| (k.into(), v.into())).collect(), - is_zero: false, - threshold: 2, - derived_point: math::generate_random_point().unwrap().into(), - }).unwrap_err(), Error::NotEnoughNodesForThreshold); + assert!(ml.session_at(0).derived_point().unwrap() != original_point.into()); } #[test] fn fails_to_complete_initialization_if_not_waiting_for_it() { - let (sid, m, _, l) = make_simple_cluster(0, 2).unwrap(); - assert_eq!(l.first_slave().on_complete_initialization(m, &message::CompleteInitialization { - session: sid.into(), + let ml = MessageLoop::new(2).init(0).unwrap(); + ml.0.take_and_process_message(); + assert_eq!(ml.session_at(0).on_complete_initialization(ml.0.node(1), &message::CompleteInitialization { + session: Default::default(), session_nonce: 0, derived_point: math::generate_random_point().unwrap().into(), - }).unwrap_err(), Error::InvalidStateForRequest); + }), Err(Error::InvalidStateForRequest)); } #[test] fn fails_to_complete_initialization_from_non_master_node() { - let (sid, _, _, mut l) = make_simple_cluster(0, 3).unwrap(); - l.take_and_process_message().unwrap(); - l.take_and_process_message().unwrap(); - l.take_and_process_message().unwrap(); - l.take_and_process_message().unwrap(); - assert_eq!(l.first_slave().on_complete_initialization(l.second_slave().node().clone(), &message::CompleteInitialization { - session: sid.into(), + let ml = MessageLoop::new(3).init(0).unwrap(); + ml.0.take_and_process_message(); + ml.0.take_and_process_message(); + ml.0.take_and_process_message(); + ml.0.take_and_process_message(); + assert_eq!(ml.session_at(1).on_complete_initialization(ml.0.node(2), &message::CompleteInitialization { + session: Default::default(), session_nonce: 0, derived_point: math::generate_random_point().unwrap().into(), - }).unwrap_err(), Error::InvalidMessage); + }), Err(Error::InvalidMessage)); } #[test] fn fails_to_accept_keys_dissemination_if_not_waiting_for_it() { - let (sid, _, s, l) = make_simple_cluster(0, 2).unwrap(); - assert_eq!(l.master().on_keys_dissemination(s, &message::KeysDissemination { - session: sid.into(), + let ml = MessageLoop::new(2).init(0).unwrap(); + assert_eq!(ml.session_at(0).on_keys_dissemination(ml.0.node(1), &message::KeysDissemination { + session: Default::default(), session_nonce: 0, secret1: math::generate_random_scalar().unwrap().into(), secret2: math::generate_random_scalar().unwrap().into(), publics: vec![math::generate_random_point().unwrap().into()], - }).unwrap_err(), Error::TooEarlyForRequest); + }), Err(Error::TooEarlyForRequest)); } #[test] fn fails_to_accept_keys_dissemination_if_wrong_number_of_publics_passed() { - let (sid, m, _, mut l) = make_simple_cluster(0, 3).unwrap(); - l.take_and_process_message().unwrap(); // m -> s1: InitializeSession - l.take_and_process_message().unwrap(); // m -> s2: InitializeSession - l.take_and_process_message().unwrap(); // s1 -> m: ConfirmInitialization - l.take_and_process_message().unwrap(); // s2 -> m: ConfirmInitialization - l.take_and_process_message().unwrap(); // m -> s1: CompleteInitialization - l.take_and_process_message().unwrap(); // m -> s2: CompleteInitialization - l.take_and_process_message().unwrap(); // m -> s1: KeysDissemination - assert_eq!(l.first_slave().on_keys_dissemination(m, &message::KeysDissemination { - session: sid.into(), - session_nonce: 0, - secret1: math::generate_random_scalar().unwrap().into(), - secret2: math::generate_random_scalar().unwrap().into(), - publics: vec![math::generate_random_point().unwrap().into(), math::generate_random_point().unwrap().into()], - }).unwrap_err(), Error::InvalidMessage); + let ml = MessageLoop::new(3).init(0).unwrap(); + ml.0.take_and_process_message(); // m -> s1: InitializeSession + ml.0.take_and_process_message(); // m -> s2: InitializeSession + ml.0.take_and_process_message(); // s1 -> m: ConfirmInitialization + ml.0.take_and_process_message(); // s2 -> m: ConfirmInitialization + ml.0.take_and_process_message(); // m -> s1: CompleteInitialization + ml.0.take_and_process_message(); // m -> s2: CompleteInitialization + + let (from, to, mut msg) = ml.take_message_keys_dissemination(); + msg.publics.clear(); + assert_eq!(ml.session_of(&to).on_keys_dissemination(from, &msg), Err(Error::InvalidMessage)); } #[test] fn fails_to_accept_keys_dissemination_second_time_from_the_same_node() { - let (sid, m, _, mut l) = make_simple_cluster(0, 3).unwrap(); - l.take_and_process_message().unwrap(); // m -> s1: InitializeSession - l.take_and_process_message().unwrap(); // m -> s2: InitializeSession - l.take_and_process_message().unwrap(); // s1 -> m: ConfirmInitialization - l.take_and_process_message().unwrap(); // s2 -> m: ConfirmInitialization - l.take_and_process_message().unwrap(); // m -> s1: CompleteInitialization - l.take_and_process_message().unwrap(); // m -> s2: CompleteInitialization - l.take_and_process_message().unwrap(); // m -> s1: KeysDissemination - assert_eq!(l.first_slave().on_keys_dissemination(m, &message::KeysDissemination { - session: sid.into(), - session_nonce: 0, - secret1: math::generate_random_scalar().unwrap().into(), - secret2: math::generate_random_scalar().unwrap().into(), - publics: vec![math::generate_random_point().unwrap().into()], - }).unwrap_err(), Error::InvalidStateForRequest); + let ml = MessageLoop::new(3).init(0).unwrap(); + ml.0.take_and_process_message(); // m -> s1: InitializeSession + ml.0.take_and_process_message(); // m -> s2: InitializeSession + ml.0.take_and_process_message(); // s1 -> m: ConfirmInitialization + ml.0.take_and_process_message(); // s2 -> m: ConfirmInitialization + ml.0.take_and_process_message(); // m -> s1: CompleteInitialization + ml.0.take_and_process_message(); // m -> s2: CompleteInitialization + + let (from, to, msg) = ml.take_message_keys_dissemination(); + ml.0.process_message(from, to, Message::Generation(GenerationMessage::KeysDissemination(msg.clone()))); + assert_eq!(ml.session_of(&to).on_keys_dissemination(from, &msg), Err(Error::InvalidStateForRequest)); } #[test] fn should_not_accept_public_key_share_when_is_not_waiting_for_it() { - let (sid, _, s, l) = make_simple_cluster(1, 3).unwrap(); - assert_eq!(l.master().on_public_key_share(s, &message::PublicKeyShare { - session: sid.into(), + let ml = MessageLoop::new(3).init(1).unwrap(); + assert_eq!(ml.session_at(0).on_public_key_share(ml.0.node(1), &message::PublicKeyShare { + session: Default::default(), session_nonce: 0, public_share: math::generate_random_point().unwrap().into(), - }).unwrap_err(), Error::InvalidStateForRequest); + }), Err(Error::InvalidStateForRequest)); } #[test] fn should_not_accept_public_key_share_when_receiving_twice() { - let (sid, m, _, mut l) = make_simple_cluster(0, 3).unwrap(); - l.take_and_process_message().unwrap(); // m -> s1: InitializeSession - l.take_and_process_message().unwrap(); // m -> s2: InitializeSession - l.take_and_process_message().unwrap(); // s1 -> m: ConfirmInitialization - l.take_and_process_message().unwrap(); // s2 -> m: ConfirmInitialization - l.take_and_process_message().unwrap(); // m -> s1: CompleteInitialization - l.take_and_process_message().unwrap(); // m -> s2: CompleteInitialization - l.take_and_process_message().unwrap(); // m -> s1: KeysDissemination - l.take_and_process_message().unwrap(); // m -> s2: KeysDissemination - l.take_and_process_message().unwrap(); // s1 -> m: KeysDissemination - l.take_and_process_message().unwrap(); // s1 -> s2: KeysDissemination - l.take_and_process_message().unwrap(); // s2 -> m: KeysDissemination - l.take_and_process_message().unwrap(); // s2 -> s1: KeysDissemination - let (f, t, msg) = match l.take_message() { - Some((f, t, Message::Generation(GenerationMessage::PublicKeyShare(msg)))) => (f, t, msg), - _ => panic!("unexpected"), - }; - assert_eq!(&f, l.master().node()); - assert_eq!(&t, l.second_slave().node()); - l.process_message((f, t, Message::Generation(GenerationMessage::PublicKeyShare(msg.clone())))).unwrap(); - assert_eq!(l.second_slave().on_public_key_share(m, &message::PublicKeyShare { - session: sid.into(), - session_nonce: 0, - public_share: math::generate_random_point().unwrap().into(), - }).unwrap_err(), Error::InvalidMessage); + let ml = MessageLoop::new(3).init(0).unwrap(); + ml.0.take_and_process_message(); // m -> s1: InitializeSession + ml.0.take_and_process_message(); // m -> s2: InitializeSession + ml.0.take_and_process_message(); // s1 -> m: ConfirmInitialization + ml.0.take_and_process_message(); // s2 -> m: ConfirmInitialization + ml.0.take_and_process_message(); // m -> s1: CompleteInitialization + ml.0.take_and_process_message(); // m -> s2: CompleteInitialization + ml.0.take_and_process_message(); // m -> s1: KeysDissemination + ml.0.take_and_process_message(); // m -> s2: KeysDissemination + ml.0.take_and_process_message(); // s1 -> m: KeysDissemination + ml.0.take_and_process_message(); // s1 -> s2: KeysDissemination + ml.0.take_and_process_message(); // s2 -> m: KeysDissemination + ml.0.take_and_process_message(); // s2 -> s1: KeysDissemination + + let (from, to, msg) = ml.take_message_public_key_share(); + ml.0.process_message(from, to, Message::Generation(GenerationMessage::PublicKeyShare(msg.clone()))); + assert_eq!(ml.session_of(&to).on_public_key_share(from, &msg), Err(Error::InvalidMessage)); } #[test] fn encryption_fails_on_session_timeout() { - let (_, _, _, l) = make_simple_cluster(0, 2).unwrap(); - assert!(l.master().joint_public_and_secret().is_none()); - l.master().on_session_timeout(); - assert!(l.master().joint_public_and_secret().unwrap().unwrap_err() == Error::NodeDisconnected); + let ml = MessageLoop::new(2).init(0).unwrap(); + assert!(ml.session_at(0).joint_public_and_secret().is_none()); + ml.session_at(0).on_session_timeout(); + assert_eq!(ml.session_at(0).joint_public_and_secret().unwrap(), Err(Error::NodeDisconnected)); } #[test] fn encryption_fails_on_node_timeout() { - let (_, _, _, l) = make_simple_cluster(0, 2).unwrap(); - assert!(l.master().joint_public_and_secret().is_none()); - l.master().on_node_timeout(l.first_slave().node()); - assert!(l.master().joint_public_and_secret().unwrap().unwrap_err() == Error::NodeDisconnected); + let ml = MessageLoop::new(2).init(0).unwrap(); + assert!(ml.session_at(0).joint_public_and_secret().is_none()); + ml.session_at(0).on_node_timeout(&ml.0.node(1)); + assert_eq!(ml.session_at(0).joint_public_and_secret().unwrap(), Err(Error::NodeDisconnected)); } #[test] fn complete_enc_dec_session() { let test_cases = [(0, 5), (2, 5), (3, 5)]; for &(threshold, num_nodes) in &test_cases { - let mut l = MessageLoop::new(num_nodes); - l.master().initialize(Default::default(), Default::default(), false, threshold, l.nodes.keys().cloned().collect::>().into()).unwrap(); - assert_eq!(l.nodes.len(), num_nodes); - - // let nodes do initialization + keys dissemination - while let Some((from, to, message)) = l.take_message() { - l.process_message((from, to, message)).unwrap(); - } + let ml = MessageLoop::new(num_nodes).init(threshold).unwrap(); + ml.0.loop_until(|| ml.0.is_empty()); // check that all nodes has finished joint public generation - let joint_public_key = l.master().joint_public_and_secret().unwrap().unwrap().0; - for node in l.nodes.values() { - let state = node.session.state(); - assert_eq!(state, SessionState::Finished); - assert_eq!(node.session.joint_public_and_secret().map(|p| p.map(|p| p.0)), Some(Ok(joint_public_key))); + let joint_public_key = ml.session_at(0).joint_public_and_secret().unwrap().unwrap().0; + for i in 0..num_nodes { + let session = ml.session_at(i); + assert_eq!(session.state(), SessionState::Finished); + assert_eq!(session.joint_public_and_secret().map(|p| p.map(|p| p.0)), Some(Ok(joint_public_key))); } // now let's encrypt some secret (which is a point on EC) let document_secret_plain = Random.generate().unwrap().public().clone(); - let all_nodes_id_numbers: Vec<_> = l.master().data.lock().nodes.values().map(|n| n.id_number.clone()).collect(); - let all_nodes_secret_shares: Vec<_> = l.nodes.values().map(|n| n.session.data.lock().secret_share.as_ref().unwrap().clone()).collect(); + let all_nodes_id_numbers = ml.nodes_id_numbers(); + let all_nodes_secret_shares = ml.nodes_secret_shares(); let document_secret_decrypted = do_encryption_and_decryption(threshold, &joint_public_key, &all_nodes_id_numbers, &all_nodes_secret_shares, @@ -1350,41 +1259,18 @@ pub mod tests { } } - #[test] - fn encryption_session_works_over_network() { - const CONN_TIMEOUT: Duration = Duration::from_millis(300); - const SESSION_TIMEOUT: Duration = Duration::from_millis(1000); - - let test_cases = [(1, 3)]; - for &(threshold, num_nodes) in &test_cases { - let mut core = new_runtime(); - - // prepare cluster objects for each node - let clusters = make_clusters(&core, 6031, num_nodes); - run_clusters(&clusters); - - // `clusters` contains `Arc` and clones will refer to the same cores. - let clusters_clone = clusters.clone(); - - // establish connections - loop_until(&core.executor(), CONN_TIMEOUT, move || clusters_clone.iter().all(all_connections_established)); - - // run session to completion - let session_id = SessionId::default(); - let session = clusters[0].client().new_generation_session(session_id, Default::default(), Default::default(), threshold).unwrap(); - loop_until(&core.executor(), SESSION_TIMEOUT, move || session.joint_public_and_secret().is_some()); - } - } - #[test] fn generation_message_fails_when_nonce_is_wrong() { - let (sid, m, _, l) = make_simple_cluster(0, 2).unwrap(); - assert_eq!(l.first_slave().process_message(&m, &message::GenerationMessage::KeysDissemination(message::KeysDissemination { - session: sid.into(), + let ml = MessageLoop::new(2).init(0).unwrap(); + ml.0.take_and_process_message(); + + let msg = message::GenerationMessage::KeysDissemination(message::KeysDissemination { + session: Default::default(), session_nonce: 10, secret1: math::generate_random_scalar().unwrap().into(), secret2: math::generate_random_scalar().unwrap().into(), publics: vec![math::generate_random_point().unwrap().into()], - })).unwrap_err(), Error::ReplayProtection); + }); + assert_eq!(ml.session_at(1).process_message(&ml.0.node(0), &msg).unwrap_err(), Error::ReplayProtection); } } diff --git a/secret-store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs b/secret-store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs index 3744f6c204..fe3bd4f114 100644 --- a/secret-store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs +++ b/secret-store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs @@ -1061,140 +1061,65 @@ impl JobTransport for SigningJobTransport { #[cfg(test)] mod tests { use std::sync::Arc; - use std::collections::{BTreeSet, BTreeMap, VecDeque}; use ethereum_types::H256; - use ethkey::{self, Random, Generator, KeyPair, verify_public, public_to_address}; - use acl_storage::DummyAclStorage; - use key_server_cluster::{NodeId, DummyKeyStorage, SessionId, SessionMeta, Error, KeyStorage}; - use key_server_cluster::cluster_sessions::ClusterSession; - use key_server_cluster::cluster::tests::DummyCluster; - use key_server_cluster::generation_session::tests::MessageLoop as KeyGenerationMessageLoop; - use key_server_cluster::message::Message; - use key_server_cluster::signing_session_ecdsa::{SessionImpl, SessionParams}; - - struct Node { - pub node_id: NodeId, - pub cluster: Arc, - pub key_storage: Arc, - pub session: SessionImpl, - } + use ethkey::{self, Random, Generator, Public, verify_public, public_to_address}; + use key_server_cluster::{SessionId, Error, KeyStorage}; + use key_server_cluster::cluster::tests::{MessageLoop as ClusterMessageLoop}; + use key_server_cluster::signing_session_ecdsa::SessionImpl; + use key_server_cluster::generation_session::tests::MessageLoop as GenerationMessageLoop; - struct MessageLoop { - pub session_id: SessionId, - pub requester: KeyPair, - pub nodes: BTreeMap, - pub queue: VecDeque<(NodeId, NodeId, Message)>, - pub acl_storages: Vec>, - pub version: H256, - } + #[derive(Debug)] + pub struct MessageLoop(pub ClusterMessageLoop); impl MessageLoop { - pub fn new(gl: &KeyGenerationMessageLoop) -> Self { - let version = gl.nodes.values().nth(0).unwrap().key_storage.get(&Default::default()).unwrap().unwrap().versions.iter().last().unwrap().hash; - let mut nodes = BTreeMap::new(); - let session_id = gl.session_id.clone(); - let requester = Random.generate().unwrap(); - let signature = Some(ethkey::sign(requester.secret(), &SessionId::default()).unwrap()); - let master_node_id = gl.nodes.keys().nth(0).unwrap().clone(); - let mut acl_storages = Vec::new(); - for (i, (gl_node_id, gl_node)) in gl.nodes.iter().enumerate() { - let acl_storage = Arc::new(DummyAclStorage::default()); - acl_storages.push(acl_storage.clone()); - let cluster = Arc::new(DummyCluster::new(gl_node_id.clone())); - let session = SessionImpl::new(SessionParams { - meta: SessionMeta { - id: session_id.clone(), - self_node_id: gl_node_id.clone(), - master_node_id: master_node_id.clone(), - threshold: gl_node.key_storage.get(&session_id).unwrap().unwrap().threshold, - configured_nodes_count: gl.nodes.len(), - connected_nodes_count: gl.nodes.len(), - }, - access_key: "834cb736f02d9c968dfaf0c37658a1d86ff140554fc8b59c9fdad5a8cf810eec".parse().unwrap(), - key_share: Some(gl_node.key_storage.get(&session_id).unwrap().unwrap()), - acl_storage: acl_storage, - cluster: cluster.clone(), - nonce: 0, - }, if i == 0 { signature.clone().map(Into::into) } else { None }).unwrap(); - nodes.insert(gl_node_id.clone(), Node { node_id: gl_node_id.clone(), cluster: cluster, key_storage: gl_node.key_storage.clone(), session: session }); - } + pub fn new(num_nodes: usize, threshold: usize) -> Result { + let ml = GenerationMessageLoop::new(num_nodes).init(threshold)?; + ml.0.loop_until(|| ml.0.is_empty()); // complete generation session - let nodes_ids: Vec<_> = nodes.keys().cloned().collect(); - for node in nodes.values() { - for node_id in &nodes_ids { - node.cluster.add_node(node_id.clone()); - } - } + Ok(MessageLoop(ml.0)) + } - MessageLoop { - session_id: session_id, - requester: requester, - nodes: nodes, - queue: VecDeque::new(), - acl_storages: acl_storages, - version: version, - } + pub fn init_with_version(self, key_version: Option) -> Result<(Self, Public, H256), Error> { + let message_hash = H256::random(); + let requester = Random.generate().unwrap(); + let signature = ethkey::sign(requester.secret(), &SessionId::default()).unwrap(); + self.0.cluster(0).client() + .new_ecdsa_signing_session(Default::default(), signature.into(), key_version, message_hash) + .map(|_| (self, *requester.public(), message_hash)) } - pub fn master(&self) -> &SessionImpl { - &self.nodes.values().nth(0).unwrap().session + pub fn init(self) -> Result<(Self, Public, H256), Error> { + let key_version = self.0.key_storage(0).get(&Default::default()) + .unwrap().unwrap().versions.iter().last().unwrap().hash; + self.init_with_version(Some(key_version)) } - pub fn take_message(&mut self) -> Option<(NodeId, NodeId, Message)> { - self.nodes.values() - .filter_map(|n| n.cluster.take_message().map(|m| (n.node_id.clone(), m.0, m.1))) - .nth(0) - .or_else(|| self.queue.pop_front()) + pub fn init_delegated(self) -> Result<(Self, Public, H256), Error> { + self.0.key_storage(0).remove(&Default::default()).unwrap(); + self.init_with_version(None) } - pub fn process_message(&mut self, mut msg: (NodeId, NodeId, Message)) -> Result<(), Error> { - let mut is_queued_message = false; - loop { - match self.nodes[&msg.1].session.on_message(&msg.0, &msg.2) { - Ok(_) => { - if let Some(message) = self.queue.pop_front() { - msg = message; - is_queued_message = true; - continue; - } - return Ok(()); - }, - Err(Error::TooEarlyForRequest) => { - if is_queued_message { - self.queue.push_front(msg); - } else { - self.queue.push_back(msg); - } - return Ok(()); - }, - Err(err) => return Err(err), - } - } + pub fn init_with_isolated(self) -> Result<(Self, Public, H256), Error> { + self.0.isolate(1); + self.init() } - } - fn prepare_signing_sessions(threshold: usize, num_nodes: usize) -> (KeyGenerationMessageLoop, MessageLoop) { - // run key generation sessions - let mut gl = KeyGenerationMessageLoop::new(num_nodes); - gl.master().initialize(Default::default(), Default::default(), false, threshold, gl.nodes.keys().cloned().collect::>().into()).unwrap(); - while let Some((from, to, message)) = gl.take_message() { - gl.process_message((from, to, message)).unwrap(); + pub fn session_at(&self, idx: usize) -> Arc { + self.0.sessions(idx).ecdsa_signing_sessions.first().unwrap() } - // run signing session - let sl = MessageLoop::new(&gl); - (gl, sl) + pub fn ensure_completed(&self) { + self.0.loop_until(|| self.0.is_empty()); + assert!(self.session_at(0).wait().is_ok()); + } } #[test] fn failed_gen_ecdsa_sign_session_when_threshold_is_too_low() { let test_cases = [(1, 2), (2, 4), (3, 6), (4, 6)]; for &(threshold, num_nodes) in &test_cases { - let (_, sl) = prepare_signing_sessions(threshold, num_nodes); - - // run signing session - let message_hash = H256::random(); - assert_eq!(sl.master().initialize(sl.version.clone(), message_hash).unwrap_err(), Error::ConsensusUnreachable); + assert_eq!(MessageLoop::new(num_nodes, threshold).unwrap().init().unwrap_err(), + Error::ConsensusUnreachable); } } @@ -1202,112 +1127,46 @@ mod tests { fn complete_gen_ecdsa_sign_session() { let test_cases = [(0, 1), (2, 5), (2, 6), (3, 11), (4, 11)]; for &(threshold, num_nodes) in &test_cases { - let (gl, mut sl) = prepare_signing_sessions(threshold, num_nodes); - let key_pair = gl.compute_key_pair(threshold); - - // run signing session - let message_hash = H256::random(); - sl.master().initialize(sl.version.clone(), message_hash).unwrap(); - while let Some((from, to, message)) = sl.take_message() { - sl.process_message((from, to, message)).unwrap(); - } + let (ml, _, message) = MessageLoop::new(num_nodes, threshold).unwrap().init().unwrap(); + ml.0.loop_until(|| ml.0.is_empty()); - // verify signature - let signature = sl.master().wait().unwrap(); - assert!(verify_public(key_pair.public(), &signature, &message_hash).unwrap()); + let signer_public = ml.0.key_storage(0).get(&Default::default()).unwrap().unwrap().public; + let signature = ml.session_at(0).wait().unwrap(); + assert!(verify_public(&signer_public, &signature, &message).unwrap()); } } #[test] fn ecdsa_complete_signing_session_with_single_node_failing() { - let (_, mut sl) = prepare_signing_sessions(1, 4); - sl.master().initialize(sl.version.clone(), 777.into()).unwrap(); + let (ml, requester, _) = MessageLoop::new(4, 1).unwrap().init().unwrap(); // we need at least 3-of-4 nodes to agree to reach consensus // let's say 1 of 4 nodes disagee - sl.acl_storages[1].prohibit(public_to_address(sl.requester.public()), SessionId::default()); + ml.0.acl_storage(1).prohibit(public_to_address(&requester), Default::default()); // then consensus reachable, but single node will disagree - while let Some((from, to, message)) = sl.take_message() { - sl.process_message((from, to, message)).unwrap(); - } - - let data = sl.master().data.lock(); - match data.result { - Some(Ok(_)) => (), - _ => unreachable!(), - } + ml.ensure_completed(); } #[test] fn ecdsa_complete_signing_session_with_acl_check_failed_on_master() { - let (_, mut sl) = prepare_signing_sessions(1, 4); - sl.master().initialize(sl.version.clone(), 777.into()).unwrap(); + let (ml, requester, _) = MessageLoop::new(4, 1).unwrap().init().unwrap(); // we need at least 3-of-4 nodes to agree to reach consensus - // let's say 1 of 4 nodes disagee - sl.acl_storages[0].prohibit(public_to_address(sl.requester.public()), SessionId::default()); + // let's say 1 of 4 nodes (here: master) disagee + ml.0.acl_storage(0).prohibit(public_to_address(&requester), Default::default()); // then consensus reachable, but single node will disagree - while let Some((from, to, message)) = sl.take_message() { - sl.process_message((from, to, message)).unwrap(); - } - - let data = sl.master().data.lock(); - match data.result { - Some(Ok(_)) => (), - _ => unreachable!(), - } + ml.ensure_completed(); } #[test] fn ecdsa_signing_works_when_delegated_to_other_node() { - let (_, mut sl) = prepare_signing_sessions(1, 4); - - // let's say node1 doesn't have a share && delegates decryption request to node0 - // initially session is created on node1 => node1 is master for itself, but for other nodes node0 is still master - let actual_master = sl.nodes.keys().nth(0).cloned().unwrap(); - let requested_node = sl.nodes.keys().skip(1).nth(0).cloned().unwrap(); - let version = sl.nodes[&actual_master].key_storage.get(&Default::default()).unwrap().unwrap().last_version().unwrap().hash.clone(); - sl.nodes[&requested_node].key_storage.remove(&Default::default()).unwrap(); - sl.nodes.get_mut(&requested_node).unwrap().session.core.key_share = None; - sl.nodes.get_mut(&requested_node).unwrap().session.core.meta.master_node_id = sl.nodes[&requested_node].session.core.meta.self_node_id.clone(); - sl.nodes[&requested_node].session.data.lock().consensus_session.consensus_job_mut().executor_mut().set_requester( - sl.nodes[&actual_master].session.data.lock().consensus_session.consensus_job().executor().requester().unwrap().clone() - ); - - // now let's try to do a decryption - sl.nodes[&requested_node].session.delegate(actual_master, version, H256::random()).unwrap(); - - // then consensus reachable, but single node will disagree - while let Some((from, to, message)) = sl.take_message() { - sl.process_message((from, to, message)).unwrap(); - } + MessageLoop::new(4, 1).unwrap().init_delegated().unwrap().0.ensure_completed(); } #[test] fn ecdsa_signing_works_when_share_owners_are_isolated() { - let (_, mut sl) = prepare_signing_sessions(2, 6); - - // we need 5 out of 6 nodes to agree to do a decryption - // let's say that 1 of these nodes (master) is isolated - let isolated_node_id = sl.nodes.keys().skip(2).nth(0).cloned().unwrap(); - for node in sl.nodes.values() { - node.cluster.remove_node(&isolated_node_id); - } - - // now let's try to do a signing - sl.master().initialize(sl.version.clone(), H256::random()).unwrap(); - - // then consensus reachable, but single node will disagree - while let Some((from, to, message)) = sl.take_message() { - sl.process_message((from, to, message)).unwrap(); - } - - let data = sl.master().data.lock(); - match data.result { - Some(Ok(_)) => (), - _ => unreachable!(), - } + MessageLoop::new(6, 2).unwrap().init_with_isolated().unwrap().0.ensure_completed(); } } diff --git a/secret-store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs b/secret-store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs index 075e456fdb..0b0619f967 100644 --- a/secret-store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs +++ b/secret-store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs @@ -809,279 +809,150 @@ impl JobTransport for SigningJobTransport { mod tests { use std::sync::Arc; use std::str::FromStr; - use std::collections::{BTreeSet, BTreeMap, VecDeque}; + use std::collections::BTreeMap; use ethereum_types::{Address, H256}; - use ethkey::{self, Random, Generator, Public, Secret, KeyPair, public_to_address}; + use ethkey::{self, Random, Generator, Public, Secret, public_to_address}; use acl_storage::DummyAclStorage; - use key_server_cluster::{NodeId, DummyKeyStorage, DocumentKeyShare, DocumentKeyShareVersion, SessionId, - Requester, SessionMeta, Error, KeyStorage}; - use key_server_cluster::cluster_sessions::ClusterSession; - use key_server_cluster::cluster::tests::DummyCluster; - use key_server_cluster::generation_session::tests::MessageLoop as KeyGenerationMessageLoop; + use key_server_cluster::{SessionId, Requester, SessionMeta, Error, KeyStorage}; + use key_server_cluster::cluster::tests::MessageLoop as ClusterMessageLoop; + use key_server_cluster::generation_session::tests::MessageLoop as GenerationMessageLoop; use key_server_cluster::math; - use key_server_cluster::message::{Message, SchnorrSigningMessage, SchnorrSigningConsensusMessage, ConsensusMessage, ConfirmConsensusInitialization, - SchnorrSigningGenerationMessage, GenerationMessage, ConfirmInitialization, InitializeSession, SchnorrRequestPartialSignature}; + use key_server_cluster::message::{SchnorrSigningMessage, SchnorrSigningConsensusMessage, + ConsensusMessage, ConfirmConsensusInitialization, SchnorrSigningGenerationMessage, GenerationMessage, + ConfirmInitialization, InitializeSession, SchnorrRequestPartialSignature}; use key_server_cluster::signing_session_schnorr::{SessionImpl, SessionState, SessionParams}; - struct Node { - pub node_id: NodeId, - pub cluster: Arc, - pub key_storage: Arc, - pub session: SessionImpl, - } - - struct MessageLoop { - pub session_id: SessionId, - pub requester: KeyPair, - pub nodes: BTreeMap, - pub queue: VecDeque<(NodeId, NodeId, Message)>, - pub acl_storages: Vec>, - pub version: H256, - } + #[derive(Debug)] + pub struct MessageLoop(pub ClusterMessageLoop); impl MessageLoop { - pub fn new(gl: &KeyGenerationMessageLoop) -> Self { - let version = gl.nodes.values().nth(0).unwrap().key_storage.get(&Default::default()).unwrap().unwrap().versions.iter().last().unwrap().hash; - let mut nodes = BTreeMap::new(); - let session_id = gl.session_id.clone(); - let requester = Random.generate().unwrap(); - let signature = Some(ethkey::sign(requester.secret(), &SessionId::default()).unwrap()); - let master_node_id = gl.nodes.keys().nth(0).unwrap().clone(); - let mut acl_storages = Vec::new(); - for (i, (gl_node_id, gl_node)) in gl.nodes.iter().enumerate() { - let acl_storage = Arc::new(DummyAclStorage::default()); - acl_storages.push(acl_storage.clone()); - let cluster = Arc::new(DummyCluster::new(gl_node_id.clone())); - let session = SessionImpl::new(SessionParams { - meta: SessionMeta { - id: session_id.clone(), - self_node_id: gl_node_id.clone(), - master_node_id: master_node_id.clone(), - threshold: gl_node.key_storage.get(&session_id).unwrap().unwrap().threshold, - configured_nodes_count: gl.nodes.len(), - connected_nodes_count: gl.nodes.len(), - }, - access_key: "834cb736f02d9c968dfaf0c37658a1d86ff140554fc8b59c9fdad5a8cf810eec".parse().unwrap(), - key_share: Some(gl_node.key_storage.get(&session_id).unwrap().unwrap()), - acl_storage: acl_storage, - cluster: cluster.clone(), - nonce: 0, - }, if i == 0 { signature.clone().map(Into::into) } else { None }).unwrap(); - nodes.insert(gl_node_id.clone(), Node { node_id: gl_node_id.clone(), cluster: cluster, key_storage: gl_node.key_storage.clone(), session: session }); - } + pub fn new(num_nodes: usize, threshold: usize) -> Result { + let ml = GenerationMessageLoop::new(num_nodes).init(threshold)?; + ml.0.loop_until(|| ml.0.is_empty()); // complete generation session - let nodes_ids: Vec<_> = nodes.keys().cloned().collect(); - for node in nodes.values() { - for node_id in &nodes_ids { - node.cluster.add_node(node_id.clone()); - } - } + Ok(MessageLoop(ml.0)) + } - MessageLoop { - session_id: session_id, - requester: requester, - nodes: nodes, - queue: VecDeque::new(), - acl_storages: acl_storages, - version: version, - } + pub fn into_session(&self, at_node: usize) -> SessionImpl { + let requester = Some(Requester::Signature(ethkey::sign(Random.generate().unwrap().secret(), + &SessionId::default()).unwrap())); + SessionImpl::new(SessionParams { + meta: SessionMeta { + id: SessionId::default(), + self_node_id: self.0.node(at_node), + master_node_id: self.0.node(0), + threshold: self.0.key_storage(at_node).get(&Default::default()).unwrap().unwrap().threshold, + configured_nodes_count: self.0.nodes().len(), + connected_nodes_count: self.0.nodes().len(), + }, + access_key: Random.generate().unwrap().secret().clone(), + key_share: self.0.key_storage(at_node).get(&Default::default()).unwrap(), + acl_storage: Arc::new(DummyAclStorage::default()), + cluster: self.0.cluster(0).view().unwrap(), + nonce: 0, + }, requester).unwrap() } - pub fn master(&self) -> &SessionImpl { - &self.nodes.values().nth(0).unwrap().session + pub fn init_with_version(self, key_version: Option) -> Result<(Self, Public, H256), Error> { + let message_hash = H256::random(); + let requester = Random.generate().unwrap(); + let signature = ethkey::sign(requester.secret(), &SessionId::default()).unwrap(); + self.0.cluster(0).client().new_schnorr_signing_session( + Default::default(), + signature.into(), + key_version, + message_hash).map(|_| (self, *requester.public(), message_hash)) } - pub fn take_message(&mut self) -> Option<(NodeId, NodeId, Message)> { - self.nodes.values() - .filter_map(|n| n.cluster.take_message().map(|m| (n.node_id.clone(), m.0, m.1))) - .nth(0) - .or_else(|| self.queue.pop_front()) + pub fn init(self) -> Result<(Self, Public, H256), Error> { + let key_version = self.key_version(); + self.init_with_version(Some(key_version)) } - pub fn process_message(&mut self, mut msg: (NodeId, NodeId, Message)) -> Result<(), Error> { - let mut is_queued_message = false; - loop { - match self.nodes[&msg.1].session.on_message(&msg.0, &msg.2) { - Ok(_) => { - if let Some(message) = self.queue.pop_front() { - msg = message; - is_queued_message = true; - continue; - } - return Ok(()); - }, - Err(Error::TooEarlyForRequest) => { - if is_queued_message { - self.queue.push_front(msg); - } else { - self.queue.push_back(msg); - } - return Ok(()); - }, - Err(err) => return Err(err), - } - } + pub fn init_delegated(self) -> Result<(Self, Public, H256), Error> { + self.0.key_storage(0).remove(&Default::default()).unwrap(); + self.init_with_version(None) } - pub fn run_until bool>(&mut self, predicate: F) -> Result<(), Error> { - while let Some((from, to, message)) = self.take_message() { - if predicate(self) { - return Ok(()); - } + pub fn init_with_isolated(self) -> Result<(Self, Public, H256), Error> { + self.0.isolate(1); + self.init() + } - self.process_message((from, to, message))?; - } + pub fn init_without_share(self) -> Result<(Self, Public, H256), Error> { + let key_version = self.key_version(); + self.0.key_storage(0).remove(&Default::default()).unwrap(); + self.init_with_version(Some(key_version)) + } - unreachable!("either wrong predicate, or failing test") + pub fn session_at(&self, idx: usize) -> Arc { + self.0.sessions(idx).schnorr_signing_sessions.first().unwrap() } - } - fn prepare_signing_sessions(threshold: usize, num_nodes: usize) -> (KeyGenerationMessageLoop, MessageLoop) { - // run key generation sessions - let mut gl = KeyGenerationMessageLoop::new(num_nodes); - gl.master().initialize(Default::default(), Default::default(), false, threshold, gl.nodes.keys().cloned().collect::>().into()).unwrap(); - while let Some((from, to, message)) = gl.take_message() { - gl.process_message((from, to, message)).unwrap(); + pub fn ensure_completed(&self) { + self.0.loop_until(|| self.0.is_empty()); + assert!(self.session_at(0).wait().is_ok()); } - // run signing session - let sl = MessageLoop::new(&gl); - (gl, sl) + pub fn key_version(&self) -> H256 { + self.0.key_storage(0).get(&Default::default()) + .unwrap().unwrap().versions.iter().last().unwrap().hash + } } #[test] fn schnorr_complete_gen_sign_session() { let test_cases = [(0, 1), (0, 5), (2, 5), (3, 5)]; for &(threshold, num_nodes) in &test_cases { - let (gl, mut sl) = prepare_signing_sessions(threshold, num_nodes); + let (ml, _, message) = MessageLoop::new(num_nodes, threshold).unwrap().init().unwrap(); + ml.0.loop_until(|| ml.0.is_empty()); - // run signing session - let message_hash = H256::from(777); - sl.master().initialize(sl.version.clone(), message_hash).unwrap(); - while let Some((from, to, message)) = sl.take_message() { - sl.process_message((from, to, message)).unwrap(); - } - - // verify signature - let public = gl.master().joint_public_and_secret().unwrap().unwrap().0; - let signature = sl.master().wait().unwrap(); - assert!(math::verify_schnorr_signature(&public, &signature, &message_hash).unwrap()); + let signer_public = ml.0.key_storage(0).get(&Default::default()).unwrap().unwrap().public; + let signature = ml.session_at(0).wait().unwrap(); + assert!(math::verify_schnorr_signature(&signer_public, &signature, &message).unwrap()); } } #[test] fn schnorr_constructs_in_cluster_of_single_node() { - let mut nodes = BTreeMap::new(); - let self_node_id = Random.generate().unwrap().public().clone(); - nodes.insert(self_node_id, Random.generate().unwrap().secret().clone()); - match SessionImpl::new(SessionParams { - meta: SessionMeta { - id: SessionId::default(), - self_node_id: self_node_id.clone(), - master_node_id: self_node_id.clone(), - threshold: 0, - configured_nodes_count: 1, - connected_nodes_count: 1, - }, - access_key: Random.generate().unwrap().secret().clone(), - key_share: Some(DocumentKeyShare { - author: Default::default(), - threshold: 0, - public: Default::default(), - common_point: Some(Random.generate().unwrap().public().clone()), - encrypted_point: Some(Random.generate().unwrap().public().clone()), - versions: vec![DocumentKeyShareVersion { - hash: Default::default(), - id_numbers: nodes, - secret_share: Random.generate().unwrap().secret().clone(), - }], - }), - acl_storage: Arc::new(DummyAclStorage::default()), - cluster: Arc::new(DummyCluster::new(self_node_id.clone())), - nonce: 0, - }, Some(Requester::Signature(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap()))) { - Ok(_) => (), - _ => panic!("unexpected"), - } + MessageLoop::new(1, 0).unwrap().init().unwrap(); } #[test] fn schnorr_fails_to_initialize_if_does_not_have_a_share() { - let self_node_id = Random.generate().unwrap().public().clone(); - let session = SessionImpl::new(SessionParams { - meta: SessionMeta { - id: SessionId::default(), - self_node_id: self_node_id.clone(), - master_node_id: self_node_id.clone(), - threshold: 0, - configured_nodes_count: 1, - connected_nodes_count: 1, - }, - access_key: Random.generate().unwrap().secret().clone(), - key_share: None, - acl_storage: Arc::new(DummyAclStorage::default()), - cluster: Arc::new(DummyCluster::new(self_node_id.clone())), - nonce: 0, - }, Some(Requester::Signature(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap()))).unwrap(); - assert_eq!(session.initialize(Default::default(), Default::default()), Err(Error::InvalidMessage)); + assert!(MessageLoop::new(2, 1).unwrap().init_without_share().is_err()); } #[test] fn schnorr_fails_to_initialize_if_threshold_is_wrong() { - let mut nodes = BTreeMap::new(); - let self_node_id = Random.generate().unwrap().public().clone(); - nodes.insert(self_node_id.clone(), Random.generate().unwrap().secret().clone()); - nodes.insert(Random.generate().unwrap().public().clone(), Random.generate().unwrap().secret().clone()); - let session = SessionImpl::new(SessionParams { - meta: SessionMeta { - id: SessionId::default(), - self_node_id: self_node_id.clone(), - master_node_id: self_node_id.clone(), - threshold: 2, - configured_nodes_count: 1, - connected_nodes_count: 1, - }, - access_key: Random.generate().unwrap().secret().clone(), - key_share: Some(DocumentKeyShare { - author: Default::default(), - threshold: 2, - public: Default::default(), - common_point: Some(Random.generate().unwrap().public().clone()), - encrypted_point: Some(Random.generate().unwrap().public().clone()), - versions: vec![DocumentKeyShareVersion { - hash: Default::default(), - id_numbers: nodes, - secret_share: Random.generate().unwrap().secret().clone(), - }], - }), - acl_storage: Arc::new(DummyAclStorage::default()), - cluster: Arc::new(DummyCluster::new(self_node_id.clone())), - nonce: 0, - }, Some(Requester::Signature(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap()))).unwrap(); - assert_eq!(session.initialize(Default::default(), Default::default()), Err(Error::ConsensusUnreachable)); + let mut ml = MessageLoop::new(3, 2).unwrap(); + ml.0.exclude(2); + assert_eq!(ml.init().unwrap_err(), Error::ConsensusUnreachable); } #[test] fn schnorr_fails_to_initialize_when_already_initialized() { - let (_, sl) = prepare_signing_sessions(1, 3); - assert_eq!(sl.master().initialize(sl.version.clone(), 777.into()), Ok(())); - assert_eq!(sl.master().initialize(sl.version.clone(), 777.into()), Err(Error::InvalidStateForRequest)); + let (ml, _, _) = MessageLoop::new(1, 0).unwrap().init().unwrap(); + assert_eq!(ml.session_at(0).initialize(ml.key_version(), 777.into()), + Err(Error::InvalidStateForRequest)); } #[test] fn schnorr_does_not_fail_when_consensus_message_received_after_consensus_established() { - let (_, mut sl) = prepare_signing_sessions(1, 3); - sl.master().initialize(sl.version.clone(), 777.into()).unwrap(); + let (ml, _, _) = MessageLoop::new(3, 1).unwrap().init().unwrap(); + // consensus is established - sl.run_until(|sl| sl.master().state() == SessionState::SessionKeyGeneration).unwrap(); + let session = ml.session_at(0); + ml.0.loop_until(|| session.state() == SessionState::SessionKeyGeneration); + // but 3rd node continues to send its messages // this should not fail session - let consensus_group = sl.master().data.lock().consensus_session.select_consensus_group().unwrap().clone(); + let consensus_group = session.data.lock().consensus_session.select_consensus_group().unwrap().clone(); let mut had_3rd_message = false; - while let Some((from, to, message)) = sl.take_message() { + while let Some((from, to, message)) = ml.0.take_message() { if !consensus_group.contains(&from) { had_3rd_message = true; - sl.process_message((from, to, message)).unwrap(); + ml.0.process_message(from, to, message); } } assert!(had_3rd_message); @@ -1089,10 +960,11 @@ mod tests { #[test] fn schnorr_fails_when_consensus_message_is_received_when_not_initialized() { - let (_, sl) = prepare_signing_sessions(1, 3); - assert_eq!(sl.master().on_consensus_message(sl.nodes.keys().nth(1).unwrap(), &SchnorrSigningConsensusMessage { + let ml = MessageLoop::new(3, 1).unwrap(); + let session = ml.into_session(0); + assert_eq!(session.on_consensus_message(&ml.0.node(1), &SchnorrSigningConsensusMessage { session: SessionId::default().into(), - sub_session: sl.master().core.access_key.clone().into(), + sub_session: session.core.access_key.clone().into(), session_nonce: 0, message: ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { is_confirmed: true, @@ -1102,10 +974,11 @@ mod tests { #[test] fn schnorr_fails_when_generation_message_is_received_when_not_initialized() { - let (_, sl) = prepare_signing_sessions(1, 3); - assert_eq!(sl.master().on_generation_message(sl.nodes.keys().nth(1).unwrap(), &SchnorrSigningGenerationMessage { + let ml = MessageLoop::new(3, 1).unwrap(); + let session = ml.into_session(0); + assert_eq!(session.on_generation_message(&ml.0.node(1), &SchnorrSigningGenerationMessage { session: SessionId::default().into(), - sub_session: sl.master().core.access_key.clone().into(), + sub_session: session.core.access_key.clone().into(), session_nonce: 0, message: GenerationMessage::ConfirmInitialization(ConfirmInitialization { session: SessionId::default().into(), @@ -1117,16 +990,16 @@ mod tests { #[test] fn schnorr_fails_when_generation_sesson_is_initialized_by_slave_node() { - let (_, mut sl) = prepare_signing_sessions(1, 3); - sl.master().initialize(sl.version.clone(), 777.into()).unwrap(); - sl.run_until(|sl| sl.master().state() == SessionState::SessionKeyGeneration).unwrap(); + let (ml, _, _) = MessageLoop::new(3, 1).unwrap().init().unwrap(); + let session = ml.session_at(0); + ml.0.loop_until(|| session.state() == SessionState::SessionKeyGeneration); - let slave2_id = sl.nodes.keys().nth(2).unwrap().clone(); - let slave1 = &sl.nodes.values().nth(1).unwrap().session; + let slave2_id = ml.0.node(2); + let slave1_session = ml.session_at(1); - assert_eq!(slave1.on_generation_message(&slave2_id, &SchnorrSigningGenerationMessage { + assert_eq!(slave1_session.on_generation_message(&slave2_id, &SchnorrSigningGenerationMessage { session: SessionId::default().into(), - sub_session: sl.master().core.access_key.clone().into(), + sub_session: session.core.access_key.clone().into(), session_nonce: 0, message: GenerationMessage::InitializeSession(InitializeSession { session: SessionId::default().into(), @@ -1143,11 +1016,11 @@ mod tests { #[test] fn schnorr_fails_when_signature_requested_when_not_initialized() { - let (_, sl) = prepare_signing_sessions(1, 3); - let slave1 = &sl.nodes.values().nth(1).unwrap().session; - assert_eq!(slave1.on_partial_signature_requested(sl.nodes.keys().nth(0).unwrap(), &SchnorrRequestPartialSignature { + let ml = MessageLoop::new(3, 1).unwrap(); + let session = ml.into_session(1); + assert_eq!(session.on_partial_signature_requested(&ml.0.node(0), &SchnorrRequestPartialSignature { session: SessionId::default().into(), - sub_session: sl.master().core.access_key.clone().into(), + sub_session: session.core.access_key.clone().into(), session_nonce: 0, request_id: Secret::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap().into(), message_hash: H256::default().into(), @@ -1157,10 +1030,11 @@ mod tests { #[test] fn schnorr_fails_when_signature_requested_by_slave_node() { - let (_, sl) = prepare_signing_sessions(1, 3); - assert_eq!(sl.master().on_partial_signature_requested(sl.nodes.keys().nth(1).unwrap(), &SchnorrRequestPartialSignature { + let ml = MessageLoop::new(3, 1).unwrap(); + let session = ml.into_session(0); + assert_eq!(session.on_partial_signature_requested(&ml.0.node(1), &SchnorrRequestPartialSignature { session: SessionId::default().into(), - sub_session: sl.master().core.access_key.clone().into(), + sub_session: session.core.access_key.clone().into(), session_nonce: 0, request_id: Secret::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap().into(), message_hash: H256::default().into(), @@ -1170,123 +1044,68 @@ mod tests { #[test] fn schnorr_failed_signing_session() { - let (_, mut sl) = prepare_signing_sessions(1, 3); - sl.master().initialize(sl.version.clone(), 777.into()).unwrap(); + let (ml, requester, _) = MessageLoop::new(3, 1).unwrap().init().unwrap(); // we need at least 2-of-3 nodes to agree to reach consensus // let's say 2 of 3 nodes disagee - sl.acl_storages[1].prohibit(public_to_address(sl.requester.public()), SessionId::default()); - sl.acl_storages[2].prohibit(public_to_address(sl.requester.public()), SessionId::default()); + ml.0.acl_storage(1).prohibit(public_to_address(&requester), SessionId::default()); + ml.0.acl_storage(2).prohibit(public_to_address(&requester), SessionId::default()); // then consensus is unreachable - assert_eq!(sl.run_until(|_| false), Err(Error::ConsensusUnreachable)); + ml.0.loop_until(|| ml.0.is_empty()); + assert_eq!(ml.session_at(0).wait().unwrap_err(), Error::ConsensusUnreachable); } #[test] fn schnorr_complete_signing_session_with_single_node_failing() { - let (_, mut sl) = prepare_signing_sessions(1, 3); - sl.master().initialize(sl.version.clone(), 777.into()).unwrap(); + let (ml, requester, _) = MessageLoop::new(3, 1).unwrap().init().unwrap(); // we need at least 2-of-3 nodes to agree to reach consensus // let's say 1 of 3 nodes disagee - sl.acl_storages[1].prohibit(public_to_address(sl.requester.public()), SessionId::default()); + ml.0.acl_storage(1).prohibit(public_to_address(&requester), SessionId::default()); // then consensus reachable, but single node will disagree - while let Some((from, to, message)) = sl.take_message() { - sl.process_message((from, to, message)).unwrap(); - } - - let data = sl.master().data.lock(); - match data.result { - Some(Ok(_)) => (), - _ => unreachable!(), - } + ml.ensure_completed(); } #[test] fn schnorr_complete_signing_session_with_acl_check_failed_on_master() { - let (_, mut sl) = prepare_signing_sessions(1, 3); - sl.master().initialize(sl.version.clone(), 777.into()).unwrap(); + let (ml, requester, _) = MessageLoop::new(3, 1).unwrap().init().unwrap(); // we need at least 2-of-3 nodes to agree to reach consensus // let's say 1 of 3 nodes disagee - sl.acl_storages[0].prohibit(public_to_address(sl.requester.public()), SessionId::default()); + ml.0.acl_storage(0).prohibit(public_to_address(&requester), SessionId::default()); // then consensus reachable, but single node will disagree - while let Some((from, to, message)) = sl.take_message() { - sl.process_message((from, to, message)).unwrap(); - } - - let data = sl.master().data.lock(); - match data.result { - Some(Ok(_)) => (), - _ => unreachable!(), - } + ml.ensure_completed(); } #[test] fn schnorr_signing_message_fails_when_nonce_is_wrong() { - let (_, sl) = prepare_signing_sessions(1, 3); - assert_eq!(sl.master().process_message(sl.nodes.keys().nth(1).unwrap(), &SchnorrSigningMessage::SchnorrSigningGenerationMessage(SchnorrSigningGenerationMessage { + let ml = MessageLoop::new(3, 1).unwrap(); + let session = ml.into_session(1); + let msg = SchnorrSigningMessage::SchnorrSigningGenerationMessage(SchnorrSigningGenerationMessage { session: SessionId::default().into(), - sub_session: sl.master().core.access_key.clone().into(), + sub_session: session.core.access_key.clone().into(), session_nonce: 10, message: GenerationMessage::ConfirmInitialization(ConfirmInitialization { session: SessionId::default().into(), session_nonce: 0, derived_point: Public::default().into(), }), - })), Err(Error::ReplayProtection)); + }); + assert_eq!(session.process_message(&ml.0.node(1), &msg), Err(Error::ReplayProtection)); } #[test] fn schnorr_signing_works_when_delegated_to_other_node() { - let (_, mut sl) = prepare_signing_sessions(1, 3); - - // let's say node1 doesn't have a share && delegates decryption request to node0 - // initially session is created on node1 => node1 is master for itself, but for other nodes node0 is still master - let actual_master = sl.nodes.keys().nth(0).cloned().unwrap(); - let requested_node = sl.nodes.keys().skip(1).nth(0).cloned().unwrap(); - let version = sl.nodes[&actual_master].key_storage.get(&Default::default()).unwrap().unwrap().last_version().unwrap().hash.clone(); - sl.nodes[&requested_node].key_storage.remove(&Default::default()).unwrap(); - sl.nodes.get_mut(&requested_node).unwrap().session.core.key_share = None; - sl.nodes.get_mut(&requested_node).unwrap().session.core.meta.master_node_id = sl.nodes[&requested_node].session.core.meta.self_node_id.clone(); - sl.nodes[&requested_node].session.data.lock().consensus_session.consensus_job_mut().executor_mut().set_requester( - sl.nodes[&actual_master].session.data.lock().consensus_session.consensus_job().executor().requester().unwrap().clone() - ); - - // now let's try to do a decryption - sl.nodes[&requested_node].session.delegate(actual_master, version, Default::default()).unwrap(); - - // then consensus reachable, but single node will disagree - while let Some((from, to, message)) = sl.take_message() { - sl.process_message((from, to, message)).unwrap(); - } + let (ml, _, _) = MessageLoop::new(3, 1).unwrap().init_delegated().unwrap(); + ml.ensure_completed(); } #[test] fn schnorr_signing_works_when_share_owners_are_isolated() { - let (_, mut sl) = prepare_signing_sessions(1, 3); - - // we need 2 out of 3 nodes to agree to do a decryption - // let's say that 1 of these nodes (master) is isolated - let isolated_node_id = sl.nodes.keys().skip(2).nth(0).cloned().unwrap(); - for node in sl.nodes.values() { - node.cluster.remove_node(&isolated_node_id); - } - - // now let's try to do a signing - sl.master().initialize(sl.version.clone(), 777.into()).unwrap(); - - // then consensus reachable, but single node will disagree - while let Some((from, to, message)) = sl.take_message() { - sl.process_message((from, to, message)).unwrap(); - } - - let data = sl.master().data.lock(); - match data.result { - Some(Ok(_)) => (), - _ => unreachable!(), - } + let (ml, _, _) = MessageLoop::new(3, 1).unwrap().init_with_isolated().unwrap(); + ml.ensure_completed(); } } diff --git a/secret-store/src/key_server_cluster/cluster.rs b/secret-store/src/key_server_cluster/cluster.rs index 09a1a6a5a8..a8416a8f70 100644 --- a/secret-store/src/key_server_cluster/cluster.rs +++ b/secret-store/src/key_server_cluster/cluster.rs @@ -14,26 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use std::io; -use std::time::{Duration, Instant}; use std::sync::Arc; -use std::sync::atomic::{AtomicBool, Ordering}; use std::collections::{BTreeMap, BTreeSet}; -use std::collections::btree_map::Entry; -use std::net::{SocketAddr, IpAddr}; -use futures::{future, Future, Stream}; -use parking_lot::{Mutex, RwLock}; -use tokio_io::IoFuture; -use tokio::timer::{Interval, timeout::Error as TimeoutError}; -use tokio::net::{TcpListener, TcpStream}; -use ethkey::{Public, KeyPair, Signature, Random, Generator}; +use parking_lot::RwLock; +use ethkey::{Public, Signature, Random, Generator}; use ethereum_types::{Address, H256}; use parity_runtime::Executor; use key_server_cluster::{Error, NodeId, SessionId, Requester, AclStorage, KeyStorage, KeyServerSet, NodeKeyPair}; use key_server_cluster::cluster_sessions::{ClusterSession, AdminSession, ClusterSessions, SessionIdWithSubSession, - ClusterSessionsContainer, SERVERS_SET_CHANGE_SESSION_ID, create_cluster_view, AdminSessionCreationData, ClusterSessionsListener}; -use key_server_cluster::cluster_sessions_creator::{ClusterSessionCreator, IntoSessionId}; -use key_server_cluster::message::{self, Message, ClusterMessage}; + ClusterSessionsContainer, SERVERS_SET_CHANGE_SESSION_ID, create_cluster_view, + AdminSessionCreationData, ClusterSessionsListener}; +use key_server_cluster::cluster_sessions_creator::ClusterSessionCreator; +use key_server_cluster::cluster_connections::{ConnectionProvider, ConnectionManager}; +use key_server_cluster::cluster_connections_net::{NetConnectionsManager, + NetConnectionsContainer, NetConnectionsManagerConfig}; +use key_server_cluster::cluster_message_processor::{MessageProcessor, SessionsMessageProcessor}; +use key_server_cluster::message::Message; use key_server_cluster::generation_session::{SessionImpl as GenerationSession}; use key_server_cluster::decryption_session::{SessionImpl as DecryptionSession}; use key_server_cluster::encryption_session::{SessionImpl as EncryptionSession}; @@ -41,31 +37,15 @@ use key_server_cluster::signing_session_ecdsa::{SessionImpl as EcdsaSigningSessi use key_server_cluster::signing_session_schnorr::{SessionImpl as SchnorrSigningSession}; use key_server_cluster::key_version_negotiation_session::{SessionImpl as KeyVersionNegotiationSession, IsolatedSessionTransport as KeyVersionNegotiationSessionTransport, ContinueAction}; -use key_server_cluster::io::{DeadlineStatus, ReadMessage, SharedTcpStream, read_encrypted_message, WriteMessage, write_encrypted_message}; -use key_server_cluster::net::{accept_connection as net_accept_connection, connect as net_connect, Connection as NetConnection}; -use key_server_cluster::connection_trigger::{Maintain, ConnectionTrigger, SimpleConnectionTrigger, ServersSetChangeSessionCreatorConnector}; +use key_server_cluster::connection_trigger::{ConnectionTrigger, + SimpleConnectionTrigger, ServersSetChangeSessionCreatorConnector}; use key_server_cluster::connection_trigger_with_migration::ConnectionTriggerWithMigration; -/// Maintain interval (seconds). Every MAINTAIN_INTERVAL seconds node: -/// 1) checks if connected nodes are responding to KeepAlive messages -/// 2) tries to connect to disconnected nodes -/// 3) checks if enc/dec sessions are time-outed -const MAINTAIN_INTERVAL: u64 = 10; - -/// When no messages have been received from node within KEEP_ALIVE_SEND_INTERVAL seconds, -/// we must send KeepAlive message to the node to check if it still responds to messages. -const KEEP_ALIVE_SEND_INTERVAL: Duration = Duration::from_secs(30); -/// When no messages have been received from node within KEEP_ALIVE_DISCONNECT_INTERVAL seconds, -/// we must treat this node as non-responding && disconnect from it. -const KEEP_ALIVE_DISCONNECT_INTERVAL: Duration = Duration::from_secs(60); - -/// Empty future. -pub type BoxedEmptyFuture = Box + Send>; +#[cfg(test)] +use key_server_cluster::cluster_connections::tests::{MessagesQueue, TestConnections, new_test_connections}; /// Cluster interface for external clients. pub trait ClusterClient: Send + Sync { - /// Get cluster state. - fn cluster_state(&self) -> ClusterState; /// Start new generation session. fn new_generation_session(&self, session_id: SessionId, origin: Option
, author: Address, threshold: usize) -> Result, Error>; /// Start new encryption session. @@ -94,12 +74,11 @@ pub trait ClusterClient: Send + Sync { /// Get active generation session with given id. #[cfg(test)] fn generation_session(&self, session_id: &SessionId) -> Option>; + #[cfg(test)] + fn is_fully_connected(&self) -> bool; /// Try connect to disconnected nodes. #[cfg(test)] fn connect(&self); - /// Get key storage. - #[cfg(test)] - fn key_storage(&self) -> Arc; } /// Cluster access for single session participant. @@ -121,12 +100,8 @@ pub trait Cluster: Send + Sync { /// Cluster initialization parameters. #[derive(Clone)] pub struct ClusterConfiguration { - /// Allow connecting to 'higher' nodes. - pub allow_connecting_to_higher_nodes: bool, /// KeyPair this node holds. pub self_key_pair: Arc, - /// Interface to listen to. - pub listen_address: (String, u16), /// Cluster nodes set. pub key_server_set: Arc, /// Reference to key storage @@ -135,114 +110,132 @@ pub struct ClusterConfiguration { pub acl_storage: Arc, /// Administrator public key. pub admin_public: Option, - /// Should key servers set change session when servers set changes? This - /// will only work when servers set is configured using KeyServerSet - /// contract. - pub auto_migrate_enabled: bool, -} - -/// Cluster state. -pub struct ClusterState { - /// Nodes, to which connections are established. - pub connected: BTreeSet, + /// Do not remove sessions from container. + pub preserve_sessions: bool, } /// Network cluster implementation. -pub struct ClusterCore { - /// Listen address. - listen_address: SocketAddr, +pub struct ClusterCore { /// Cluster data. - data: Arc, + data: Arc>, } /// Network cluster client interface implementation. -pub struct ClusterClientImpl { +pub struct ClusterClientImpl { /// Cluster data. - data: Arc, + data: Arc>, } /// Network cluster view. It is a communication channel, required in single session. pub struct ClusterView { - core: Arc>, configured_nodes_count: usize, - connected_nodes_count: usize, + connected_nodes: BTreeSet, + connections: Arc, + self_key_pair: Arc, } /// Cross-thread shareable cluster data. -pub struct ClusterData { +pub struct ClusterData { /// Cluster configuration. pub config: ClusterConfiguration, - /// Handle to the event loop. - pub executor: Executor, /// KeyPair this node holds. pub self_key_pair: Arc, /// Connections data. - pub connections: ClusterConnections, + pub connections: C, /// Active sessions data. - pub sessions: ClusterSessions, - /// A shutdown flag. - pub is_shutdown: Arc, -} - -/// Connections that are forming the cluster. Lock order: trigger.lock() -> data.lock(). -pub struct ClusterConnections { - /// Self node id. - pub self_node_id: NodeId, - /// All known other key servers. - pub key_server_set: Arc, - /// Connections trigger. - pub trigger: Mutex>, - /// Servers set change session creator connector. - pub connector: Arc, - /// Connections data. - pub data: RwLock, + pub sessions: Arc, + // Messages processor. + pub message_processor: Arc, + /// Link between servers set chnage session and the connections manager. + pub servers_set_change_creator_connector: Arc, } -/// Cluster connections data. -pub struct ClusterConnectionsData { - /// Is this node isolated from cluster? - pub is_isolated: bool, - /// Active key servers set. - pub nodes: BTreeMap, - /// Active connections to key servers. - pub connections: BTreeMap>, -} +/// Create new network-backed cluster. +pub fn new_network_cluster( + executor: Executor, + config: ClusterConfiguration, + net_config: NetConnectionsManagerConfig +) -> Result>, Error> { + let mut nodes = config.key_server_set.snapshot().current_set; + let is_isolated = nodes.remove(config.self_key_pair.public()).is_none(); + let connections_data = Arc::new(RwLock::new(NetConnectionsContainer { + is_isolated, + nodes, + connections: BTreeMap::new(), + })); + + let connection_trigger: Box = match net_config.auto_migrate_enabled { + false => Box::new(SimpleConnectionTrigger::with_config(&config)), + true if config.admin_public.is_none() => Box::new(ConnectionTriggerWithMigration::with_config(&config)), + true => return Err(Error::Internal( + "secret store admininstrator public key is specified with auto-migration enabled".into() + )), + }; -/// Cluster view core. -struct ClusterViewCore { - /// Cluster reference. - cluster: Arc, - /// Subset of nodes, required for this session. - nodes: BTreeSet, + let servers_set_change_creator_connector = connection_trigger.servers_set_change_creator_connector(); + let sessions = Arc::new(ClusterSessions::new(&config, servers_set_change_creator_connector.clone())); + let message_processor = Arc::new(SessionsMessageProcessor::new( + config.self_key_pair.clone(), + servers_set_change_creator_connector.clone(), + sessions.clone(), + connections_data.clone())); + + let connections = NetConnectionsManager::new( + executor, + message_processor.clone(), + connection_trigger, + connections_data, + &config, + net_config)?; + connections.start()?; + + ClusterCore::new(sessions, message_processor, connections, servers_set_change_creator_connector, config) } -/// Connection to single node. -pub struct Connection { - /// Node id. - node_id: NodeId, - /// Node address. - node_address: SocketAddr, - /// Is inbound connection? - is_inbound: bool, - /// Tcp stream. - stream: SharedTcpStream, - /// Connection key. - key: KeyPair, - /// Last message time. - last_message_time: RwLock, +/// Create new in-memory backed cluster +#[cfg(test)] +pub fn new_test_cluster( + messages: MessagesQueue, + config: ClusterConfiguration, +) -> Result>>, Error> { + let nodes = config.key_server_set.snapshot().current_set; + let connections = new_test_connections(messages, *config.self_key_pair.public(), nodes.keys().cloned().collect()); + + let connection_trigger = Box::new(SimpleConnectionTrigger::with_config(&config)); + let servers_set_change_creator_connector = connection_trigger.servers_set_change_creator_connector(); + let mut sessions = ClusterSessions::new(&config, servers_set_change_creator_connector.clone()); + if config.preserve_sessions { + sessions.preserve_sessions(); + } + let sessions = Arc::new(sessions); + + let message_processor = Arc::new(SessionsMessageProcessor::new( + config.self_key_pair.clone(), + servers_set_change_creator_connector.clone(), + sessions.clone(), + connections.provider(), + )); + + ClusterCore::new(sessions, message_processor, connections, servers_set_change_creator_connector, config) } -impl ClusterCore { - pub fn new(executor: Executor, config: ClusterConfiguration) -> Result, Error> { - let listen_address = make_socket_address(&config.listen_address.0, config.listen_address.1)?; - let connections = ClusterConnections::new(&config)?; - let servers_set_change_creator_connector = connections.connector.clone(); - let sessions = ClusterSessions::new(&config, servers_set_change_creator_connector); - let data = ClusterData::new(&executor, config, connections, sessions); - +impl ClusterCore { + pub fn new( + sessions: Arc, + message_processor: Arc, + connections: C, + servers_set_change_creator_connector: Arc, + config: ClusterConfiguration, + ) -> Result, Error> { Ok(Arc::new(ClusterCore { - listen_address: listen_address, - data: data, + data: Arc::new(ClusterData { + self_key_pair: config.self_key_pair.clone(), + connections, + sessions: sessions.clone(), + config, + message_processor, + servers_set_change_creator_connector + }), })) } @@ -251,657 +244,68 @@ impl ClusterCore { Arc::new(ClusterClientImpl::new(self.data.clone())) } - /// Get cluster configuration. - #[cfg(test)] - pub fn config(&self) -> &ClusterConfiguration { - &self.data.config - } - - /// Get connection to given node. - #[cfg(test)] - pub fn connection(&self, node: &NodeId) -> Option> { - self.data.connection(node) - } - /// Run cluster. pub fn run(&self) -> Result<(), Error> { - self.run_listener() - .and_then(|_| self.run_connections())?; - - // schedule maintain procedures - ClusterCore::schedule_maintain(self.data.clone()); - - Ok(()) - } - - /// Start listening for incoming connections. - pub fn run_listener(&self) -> Result<(), Error> { - // start listeining for incoming connections - self.data.spawn(ClusterCore::listen(self.data.clone(), self.listen_address.clone())?); + self.data.connections.connect(); Ok(()) } - /// Start connecting to other nodes. - pub fn run_connections(&self) -> Result<(), Error> { - // try to connect to every other peer - ClusterCore::connect_disconnected_nodes(self.data.clone()); - Ok(()) - } - - /// Connect to peer. - fn connect(data: Arc, node_address: SocketAddr) { - data.clone().spawn(ClusterCore::connect_future(data, node_address)); - } - - /// Connect to socket using given context and executor. - fn connect_future(data: Arc, node_address: SocketAddr) -> BoxedEmptyFuture { - let disconnected_nodes = data.connections.disconnected_nodes().keys().cloned().collect(); - Box::new(net_connect(&node_address, data.self_key_pair.clone(), disconnected_nodes) - .then(move |result| ClusterCore::process_connection_result(data, Some(node_address), result)) - .then(|_| future::ok(()))) - } - - /// Start listening for incoming connections. - fn listen(data: Arc, listen_address: SocketAddr) -> Result { - Ok(Box::new(TcpListener::bind(&listen_address)? - .incoming() - .and_then(move |stream| { - ClusterCore::accept_connection(data.clone(), stream); - Ok(()) - }) - .for_each(|_| Ok(())) - .then(|_| future::ok(())))) - } - - /// Accept connection. - fn accept_connection(data: Arc, stream: TcpStream) { - data.clone().spawn(ClusterCore::accept_connection_future(data, stream)) - } - - /// Accept connection future. - fn accept_connection_future(data: Arc, stream: TcpStream) -> BoxedEmptyFuture { - Box::new(net_accept_connection(stream, data.self_key_pair.clone()) - .then(move |result| ClusterCore::process_connection_result(data, None, result)) - .then(|_| future::ok(()))) - } - - /// Schedule mainatain procedures. - fn schedule_maintain(data: Arc) { - let d = data.clone(); - - let interval = Interval::new_interval(Duration::new(MAINTAIN_INTERVAL, 0)) - .and_then(move |_| Ok(ClusterCore::maintain(data.clone()))) - .for_each(|_| Ok(())) - .then(|_| future::ok(())); - - d.spawn(interval); - } - - /// Execute maintain procedures. - fn maintain(data: Arc) { - trace!(target: "secretstore_net", "{}: executing maintain procedures", data.self_key_pair.public()); - - ClusterCore::keep_alive(data.clone()); - ClusterCore::connect_disconnected_nodes(data.clone()); - data.sessions.stop_stalled_sessions(); - } - - /// Called for every incomming mesage. - fn process_connection_messages(data: Arc, connection: Arc) -> IoFuture> { - Box::new(connection - .read_message() - .then(move |result| - match result { - Ok((_, Ok(message))) => { - ClusterCore::process_connection_message(data.clone(), connection.clone(), message); - // continue serving connection - data.spawn(ClusterCore::process_connection_messages(data.clone(), connection).then(|_| Ok(()))); - Box::new(future::ok(Ok(()))) - }, - Ok((_, Err(err))) => { - warn!(target: "secretstore_net", "{}: protocol error '{}' when reading message from node {}", data.self_key_pair.public(), err, connection.node_id()); - // continue serving connection - data.spawn(ClusterCore::process_connection_messages(data.clone(), connection).then(|_| Ok(()))); - Box::new(future::ok(Err(err))) - }, - Err(err) => { - warn!(target: "secretstore_net", "{}: network error '{}' when reading message from node {}", data.self_key_pair.public(), err, connection.node_id()); - // close connection - data.connections.remove(data.clone(), connection.node_id(), connection.is_inbound()); - Box::new(future::err(err)) - }, - } - )) - } - - /// Send keepalive messages to every othe node. - fn keep_alive(data: Arc) { - data.sessions.sessions_keep_alive(); - for connection in data.connections.active_connections() { - let last_message_diff = Instant::now() - connection.last_message_time(); - if last_message_diff > KEEP_ALIVE_DISCONNECT_INTERVAL { - warn!(target: "secretstore_net", "{}: keep alive timeout for node {}", - data.self_key_pair.public(), connection.node_id()); - - data.connections.remove(data.clone(), connection.node_id(), connection.is_inbound()); - data.sessions.on_connection_timeout(connection.node_id()); - } - else if last_message_diff > KEEP_ALIVE_SEND_INTERVAL { - data.spawn(connection.send_message(Message::Cluster(ClusterMessage::KeepAlive(message::KeepAlive {}))).then(|_| Ok(()))); - } - } - } - - /// Try to connect to every disconnected node. - fn connect_disconnected_nodes(data: Arc) { - let r = data.connections.update_nodes_set(data.clone()); - if let Some(r) = r { - data.spawn(r); - } - - // connect to disconnected nodes - for (node_id, node_address) in data.connections.disconnected_nodes() { - if data.config.allow_connecting_to_higher_nodes || data.self_key_pair.public() < &node_id { - ClusterCore::connect(data.clone(), node_address); - } - } - } - - /// Process connection future result. - fn process_connection_result(data: Arc, outbound_addr: Option, - result: Result>, TimeoutError>) -> IoFuture> - { - match result { - Ok(DeadlineStatus::Meet(Ok(connection))) => { - let connection = Connection::new(outbound_addr.is_none(), connection); - if data.connections.insert(data.clone(), connection.clone()) { - ClusterCore::process_connection_messages(data.clone(), connection) - } else { - Box::new(future::ok(Ok(()))) - } - }, - Ok(DeadlineStatus::Meet(Err(err))) => { - warn!(target: "secretstore_net", "{}: protocol error '{}' when establishing {} connection{}", - data.self_key_pair.public(), err, if outbound_addr.is_some() { "outbound" } else { "inbound" }, - outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); - Box::new(future::ok(Ok(()))) - }, - Ok(DeadlineStatus::Timeout) => { - warn!(target: "secretstore_net", "{}: timeout when establishing {} connection{}", - data.self_key_pair.public(), if outbound_addr.is_some() { "outbound" } else { "inbound" }, - outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); - Box::new(future::ok(Ok(()))) - }, - Err(err) => { - warn!(target: "secretstore_net", "{}: network error '{}' when establishing {} connection{}", - data.self_key_pair.public(), err, if outbound_addr.is_some() { "outbound" } else { "inbound" }, - outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); - Box::new(future::ok(Ok(()))) - }, - } - } - - /// Process single message from the connection. - fn process_connection_message(data: Arc, connection: Arc, message: Message) { - connection.set_last_message_time(Instant::now()); - trace!(target: "secretstore_net", "{}: received message {} from {}", data.self_key_pair.public(), message, connection.node_id()); - // error is ignored as we only process errors on session level - match message { - Message::Generation(message) => Self::process_message(&data, &data.sessions.generation_sessions, connection, Message::Generation(message)) - .map(|_| ()).unwrap_or_default(), - Message::Encryption(message) => Self::process_message(&data, &data.sessions.encryption_sessions, connection, Message::Encryption(message)) - .map(|_| ()).unwrap_or_default(), - Message::Decryption(message) => Self::process_message(&data, &data.sessions.decryption_sessions, connection, Message::Decryption(message)) - .map(|_| ()).unwrap_or_default(), - Message::SchnorrSigning(message) => Self::process_message(&data, &data.sessions.schnorr_signing_sessions, connection, Message::SchnorrSigning(message)) - .map(|_| ()).unwrap_or_default(), - Message::EcdsaSigning(message) => Self::process_message(&data, &data.sessions.ecdsa_signing_sessions, connection, Message::EcdsaSigning(message)) - .map(|_| ()).unwrap_or_default(), - Message::ServersSetChange(message) => { - let message = Message::ServersSetChange(message); - let is_initialization_message = message.is_initialization_message(); - let session = Self::process_message(&data, &data.sessions.admin_sessions, connection, message); - if is_initialization_message { - if let Some(session) = session { - data.connections.servers_set_change_creator_connector().set_key_servers_set_change_session(session.clone()); - } - } - } - Message::KeyVersionNegotiation(message) => { - let session = Self::process_message(&data, &data.sessions.negotiation_sessions, connection, Message::KeyVersionNegotiation(message)); - Self::try_continue_session(&data, session); - }, - Message::ShareAdd(message) => Self::process_message(&data, &data.sessions.admin_sessions, connection, Message::ShareAdd(message)) - .map(|_| ()).unwrap_or_default(), - Message::Cluster(message) => ClusterCore::process_cluster_message(data, connection, message), - } - } - - /// Try to contnue session. - fn try_continue_session(data: &Arc, session: Option>>) { - if let Some(session) = session { - let meta = session.meta(); - let is_master_node = meta.self_node_id == meta.master_node_id; - if is_master_node && session.is_finished() { - data.sessions.negotiation_sessions.remove(&session.id()); - match session.wait() { - Ok(Some((version, master))) => match session.take_continue_action() { - Some(ContinueAction::Decrypt(session, origin, is_shadow_decryption, is_broadcast_decryption)) => { - let initialization_error = if data.self_key_pair.public() == &master { - session.initialize(origin, version, is_shadow_decryption, is_broadcast_decryption) - } else { - session.delegate(master, origin, version, is_shadow_decryption, is_broadcast_decryption) - }; - - if let Err(error) = initialization_error { - session.on_session_error(&meta.self_node_id, error); - data.sessions.decryption_sessions.remove(&session.id()); - } - }, - Some(ContinueAction::SchnorrSign(session, message_hash)) => { - let initialization_error = if data.self_key_pair.public() == &master { - session.initialize(version, message_hash) - } else { - session.delegate(master, version, message_hash) - }; - - if let Err(error) = initialization_error { - session.on_session_error(&meta.self_node_id, error); - data.sessions.schnorr_signing_sessions.remove(&session.id()); - } - }, - Some(ContinueAction::EcdsaSign(session, message_hash)) => { - let initialization_error = if data.self_key_pair.public() == &master { - session.initialize(version, message_hash) - } else { - session.delegate(master, version, message_hash) - }; - - if let Err(error) = initialization_error { - session.on_session_error(&meta.self_node_id, error); - data.sessions.ecdsa_signing_sessions.remove(&session.id()); - } - }, - None => (), - }, - Ok(None) => unreachable!("is_master_node; session is finished; negotiation version always finished with result on master; qed"), - Err(error) => match session.take_continue_action() { - Some(ContinueAction::Decrypt(session, _, _, _)) => { - session.on_session_error(&meta.self_node_id, error); - data.sessions.decryption_sessions.remove(&session.id()); - }, - Some(ContinueAction::SchnorrSign(session, _)) => { - session.on_session_error(&meta.self_node_id, error); - data.sessions.schnorr_signing_sessions.remove(&session.id()); - }, - Some(ContinueAction::EcdsaSign(session, _)) => { - session.on_session_error(&meta.self_node_id, error); - data.sessions.ecdsa_signing_sessions.remove(&session.id()); - }, - None => (), - }, - } - } - } - } - - /// Get or insert new session. - fn prepare_session, D>(data: &Arc, sessions: &ClusterSessionsContainer, sender: &NodeId, message: &Message) -> Result, Error> - where Message: IntoSessionId { - fn requires_all_connections(message: &Message) -> bool { - match *message { - Message::Generation(_) => true, - Message::ShareAdd(_) => true, - Message::ServersSetChange(_) => true, - _ => false, - } - } - - // get or create new session, if required - let session_id = message.into_session_id().expect("into_session_id fails for cluster messages only; only session messages are passed to prepare_session; qed"); - let is_initialization_message = message.is_initialization_message(); - let is_delegation_message = message.is_delegation_message(); - match is_initialization_message || is_delegation_message { - false => sessions.get(&session_id, true).ok_or(Error::NoActiveSessionWithId), - true => { - let creation_data = SC::creation_data_from_message(&message)?; - let master = if is_initialization_message { sender.clone() } else { data.self_key_pair.public().clone() }; - let cluster = create_cluster_view(data, requires_all_connections(&message))?; - - sessions.insert(cluster, master, session_id, Some(message.session_nonce().ok_or(Error::InvalidMessage)?), message.is_exclusive_session_message(), creation_data) - }, - } - } - - /// Process single session message from connection. - fn process_message, D>(data: &Arc, sessions: &ClusterSessionsContainer, connection: Arc, mut message: Message) -> Option> - where Message: IntoSessionId { - - // get or create new session, if required - let mut sender = connection.node_id().clone(); - let session = Self::prepare_session(data, sessions, &sender, &message); - // send error if session is not found, or failed to create - let session = match session { - Ok(session) => session, - Err(error) => { - // this is new session => it is not yet in container - warn!(target: "secretstore_net", "{}: {} session read error '{}' when requested for session from node {}", - data.self_key_pair.public(), S::type_name(), error, sender); - if !message.is_error_message() { - let session_id = message.into_session_id().expect("session_id only fails for cluster messages; only session messages are passed to process_message; qed"); - let session_nonce = message.session_nonce().expect("session_nonce only fails for cluster messages; only session messages are passed to process_message; qed"); - data.spawn(connection.send_message(SC::make_error_message(session_id, session_nonce, error)).then(|_| Ok(()))); - } - return None; - }, - }; - - let session_id = session.id(); - let mut is_queued_message = false; - loop { - let message_result = session.on_message(&sender, &message); - match message_result { - Ok(_) => { - // if session is completed => stop - if session.is_finished() { - info!(target: "secretstore_net", "{}: {} session completed", data.self_key_pair.public(), S::type_name()); - sessions.remove(&session_id); - return Some(session); - } - - // try to dequeue message - match sessions.dequeue_message(&session_id) { - Some((msg_sender, msg)) => { - is_queued_message = true; - sender = msg_sender; - message = msg; - }, - None => return Some(session), - } - }, - Err(Error::TooEarlyForRequest) => { - sessions.enqueue_message(&session_id, sender, message, is_queued_message); - return Some(session); - }, - Err(err) => { - warn!(target: "secretstore_net", "{}: {} session error '{}' when processing message {} from node {}", - data.self_key_pair.public(), - S::type_name(), - err, - message, - sender); - session.on_session_error(data.self_key_pair.public(), err); - sessions.remove(&session_id); - return Some(session); - }, - } - } - } - - /// Process single cluster message from the connection. - fn process_cluster_message(data: Arc, connection: Arc, message: ClusterMessage) { - match message { - ClusterMessage::KeepAlive(_) => data.spawn(connection.send_message(Message::Cluster(ClusterMessage::KeepAliveResponse(message::KeepAliveResponse { - session_id: None, - }))).then(|_| Ok(()))), - ClusterMessage::KeepAliveResponse(msg) => if let Some(session_id) = msg.session_id { - data.sessions.on_session_keep_alive(connection.node_id(), session_id.into()); - }, - _ => warn!(target: "secretstore_net", "{}: received unexpected message {} from node {} at {}", data.self_key_pair.public(), message, connection.node_id(), connection.node_address()), - } - } - - /// Prevents new tasks from being spawned. #[cfg(test)] - pub fn shutdown(&self) { - self.data.shutdown() - } -} - -impl ClusterConnections { - pub fn new(config: &ClusterConfiguration) -> Result { - let mut nodes = config.key_server_set.snapshot().current_set; - let is_isolated = nodes.remove(config.self_key_pair.public()).is_none(); - - let trigger: Box = match config.auto_migrate_enabled { - false => Box::new(SimpleConnectionTrigger::new(config.key_server_set.clone(), config.self_key_pair.clone(), config.admin_public.clone())), - true if config.admin_public.is_none() => Box::new(ConnectionTriggerWithMigration::new(config.key_server_set.clone(), config.self_key_pair.clone())), - true => return Err(Error::Internal("secret store admininstrator public key is specified with auto-migration enabled".into())), - }; - let connector = trigger.servers_set_change_creator_connector(); - - Ok(ClusterConnections { - self_node_id: config.self_key_pair.public().clone(), - key_server_set: config.key_server_set.clone(), - trigger: Mutex::new(trigger), - connector: connector, - data: RwLock::new(ClusterConnectionsData { - is_isolated: is_isolated, - nodes: nodes, - connections: BTreeMap::new(), - }), - }) - } - - pub fn cluster_state(&self) -> ClusterState { - ClusterState { - connected: self.data.read().connections.keys().cloned().collect(), - } - } - - pub fn get(&self, node: &NodeId) -> Option> { - self.data.read().connections.get(node).cloned() - } - - pub fn insert(&self, data: Arc, connection: Arc) -> bool { - { - let mut data = self.data.write(); - if !data.nodes.contains_key(connection.node_id()) { - // incoming connections are checked here - trace!(target: "secretstore_net", "{}: ignoring unknown connection from {} at {}", self.self_node_id, connection.node_id(), connection.node_address()); - debug_assert!(connection.is_inbound()); - return false; - } - - if data.connections.contains_key(connection.node_id()) { - // we have already connected to the same node - // the agreement is that node with lower id must establish connection to node with higher id - if (&self.self_node_id < connection.node_id() && connection.is_inbound()) - || (&self.self_node_id > connection.node_id() && !connection.is_inbound()) { - return false; - } - } - - let node = connection.node_id().clone(); - trace!(target: "secretstore_net", "{}: inserting connection to {} at {}. Connected to {} of {} nodes", - self.self_node_id, node, connection.node_address(), data.connections.len() + 1, data.nodes.len()); - data.connections.insert(node.clone(), connection.clone()); - } - - let maintain_action = self.trigger.lock().on_connection_established(connection.node_id()); - self.maintain_connection_trigger(maintain_action, data); - - true - } - - pub fn remove(&self, data: Arc, node: &NodeId, is_inbound: bool) { - { - let mut data = self.data.write(); - if let Entry::Occupied(entry) = data.connections.entry(node.clone()) { - if entry.get().is_inbound() != is_inbound { - return; - } - - trace!(target: "secretstore_net", "{}: removing connection to {} at {}", self.self_node_id, entry.get().node_id(), entry.get().node_address()); - entry.remove_entry(); - } else { - return; - } - } - - let maintain_action = self.trigger.lock().on_connection_closed(node); - self.maintain_connection_trigger(maintain_action, data); - } - - pub fn connected_nodes(&self) -> Result, Error> { - let data = self.data.read(); - if data.is_isolated { - return Err(Error::NodeDisconnected); - } - - Ok(data.connections.keys().cloned().collect()) - } - - pub fn active_connections(&self)-> Vec> { - self.data.read().connections.values().cloned().collect() - } - - pub fn disconnected_nodes(&self) -> BTreeMap { - let data = self.data.read(); - data.nodes.iter() - .filter(|&(node_id, _)| !data.connections.contains_key(node_id)) - .map(|(node_id, node_address)| (node_id.clone(), node_address.clone())) - .collect() - } - - pub fn servers_set_change_creator_connector(&self) -> Arc { - self.connector.clone() - } - - pub fn update_nodes_set(&self, data: Arc) -> Option { - let maintain_action = self.trigger.lock().on_maintain(); - self.maintain_connection_trigger(maintain_action, data); - None - } - - fn maintain_connection_trigger(&self, maintain_action: Option, data: Arc) { - if maintain_action == Some(Maintain::SessionAndConnections) || maintain_action == Some(Maintain::Session) { - let client = ClusterClientImpl::new(data); - self.trigger.lock().maintain_session(&client); - } - if maintain_action == Some(Maintain::SessionAndConnections) || maintain_action == Some(Maintain::Connections) { - let mut trigger = self.trigger.lock(); - let mut data = self.data.write(); - trigger.maintain_connections(&mut *data); - } - } -} - -impl ClusterData { - pub fn new(executor: &Executor, config: ClusterConfiguration, connections: ClusterConnections, sessions: ClusterSessions) -> Arc { - Arc::new(ClusterData { - executor: executor.clone(), - self_key_pair: config.self_key_pair.clone(), - connections: connections, - sessions: sessions, - config: config, - is_shutdown: Arc::new(AtomicBool::new(false)), - }) - } - - /// Get connection to given node. - pub fn connection(&self, node: &NodeId) -> Option> { - self.connections.get(node) - } - - /// Spawns a future on the runtime. - pub fn spawn(&self, f: F) where F: Future + Send + 'static { - if self.is_shutdown.load(Ordering::Acquire) == false { - if let Err(err) = future::Executor::execute(&self.executor, Box::new(f)) { - error!("Secret store runtime unable to spawn task. Runtime is shutting down. ({:?})", err); - } - } else { - error!("Secret store runtime unable to spawn task. Shutdown has been started."); - } - } - - /// Sets the `is_shutdown` flag which prevents future tasks from being - /// spawned via `::spawn`. - #[cfg(test)] - pub fn shutdown(&self) { - self.is_shutdown.store(true, Ordering::Release); - } -} - -impl Connection { - pub fn new(is_inbound: bool, connection: NetConnection) -> Arc { - Arc::new(Connection { - node_id: connection.node_id, - node_address: connection.address, - is_inbound: is_inbound, - stream: connection.stream, - key: connection.key, - last_message_time: RwLock::new(Instant::now()), - }) - } - - pub fn is_inbound(&self) -> bool { - self.is_inbound - } - - pub fn node_id(&self) -> &NodeId { - &self.node_id - } - - pub fn last_message_time(&self) -> Instant { - *self.last_message_time.read() - } - - pub fn set_last_message_time(&self, last_message_time: Instant) { - *self.last_message_time.write() = last_message_time; - } - - pub fn node_address(&self) -> &SocketAddr { - &self.node_address - } - - pub fn send_message(&self, message: Message) -> WriteMessage { - write_encrypted_message(self.stream.clone(), &self.key, message) - } + pub fn view(&self) -> Result, Error> { + let connections = self.data.connections.provider(); + let mut connected_nodes = connections.connected_nodes()?; + let disconnected_nodes = connections.disconnected_nodes(); + connected_nodes.insert(self.data.self_key_pair.public().clone()); - pub fn read_message(&self) -> ReadMessage { - read_encrypted_message(self.stream.clone(), self.key.clone()) + let connected_nodes_count = connected_nodes.len(); + let disconnected_nodes_count = disconnected_nodes.len(); + Ok(Arc::new(ClusterView::new( + self.data.self_key_pair.clone(), + connections, + connected_nodes, + connected_nodes_count + disconnected_nodes_count))) } } impl ClusterView { - pub fn new(cluster: Arc, nodes: BTreeSet, configured_nodes_count: usize) -> Self { + pub fn new( + self_key_pair: Arc, + connections: Arc, + nodes: BTreeSet, + configured_nodes_count: usize + ) -> Self { ClusterView { configured_nodes_count: configured_nodes_count, - connected_nodes_count: nodes.len(), - core: Arc::new(RwLock::new(ClusterViewCore { - cluster: cluster, - nodes: nodes, - })), + connected_nodes: nodes, + connections, + self_key_pair, } } } impl Cluster for ClusterView { fn broadcast(&self, message: Message) -> Result<(), Error> { - let core = self.core.read(); - for node in core.nodes.iter().filter(|n| *n != core.cluster.self_key_pair.public()) { - trace!(target: "secretstore_net", "{}: sent message {} to {}", core.cluster.self_key_pair.public(), message, node); - let connection = core.cluster.connection(node).ok_or(Error::NodeDisconnected)?; - core.cluster.spawn(connection.send_message(message.clone()).then(|_| Ok(()))) + for node in self.connected_nodes.iter().filter(|n| *n != self.self_key_pair.public()) { + trace!(target: "secretstore_net", "{}: sent message {} to {}", self.self_key_pair.public(), message, node); + let connection = self.connections.connection(node).ok_or(Error::NodeDisconnected)?; + connection.send_message(message.clone()); } Ok(()) } fn send(&self, to: &NodeId, message: Message) -> Result<(), Error> { - let core = self.core.read(); - trace!(target: "secretstore_net", "{}: sent message {} to {}", core.cluster.self_key_pair.public(), message, to); - let connection = core.cluster.connection(to).ok_or(Error::NodeDisconnected)?; - core.cluster.spawn(connection.send_message(message).then(|_| Ok(()))); + trace!(target: "secretstore_net", "{}: sent message {} to {}", self.self_key_pair.public(), message, to); + let connection = self.connections.connection(to).ok_or(Error::NodeDisconnected)?; + connection.send_message(message); Ok(()) } fn is_connected(&self, node: &NodeId) -> bool { - self.core.read().nodes.contains(node) + self.connected_nodes.contains(node) } fn nodes(&self) -> BTreeSet { - self.core.read().nodes.clone() + self.connected_nodes.clone() } fn configured_nodes_count(&self) -> usize { @@ -909,24 +313,24 @@ impl Cluster for ClusterView { } fn connected_nodes_count(&self) -> usize { - self.connected_nodes_count + self.connected_nodes.len() } } -impl ClusterClientImpl { - pub fn new(data: Arc) -> Self { +impl ClusterClientImpl { + pub fn new(data: Arc>) -> Self { ClusterClientImpl { data: data, } } fn create_key_version_negotiation_session(&self, session_id: SessionId) -> Result>, Error> { - let mut connected_nodes = self.data.connections.connected_nodes()?; + let mut connected_nodes = self.data.connections.provider().connected_nodes()?; connected_nodes.insert(self.data.self_key_pair.public().clone()); let access_key = Random.generate()?.secret().clone(); let session_id = SessionIdWithSubSession::new(session_id, access_key); - let cluster = create_cluster_view(&self.data, false)?; + let cluster = create_cluster_view(self.data.self_key_pair.clone(), self.data.connections.provider(), false)?; let session = self.data.sessions.negotiation_sessions.insert(cluster, self.data.self_key_pair.public().clone(), session_id.clone(), None, false, None)?; match session.initialize(connected_nodes) { Ok(()) => Ok(session), @@ -936,56 +340,38 @@ impl ClusterClientImpl { } } } - - fn process_initialization_result, D>(result: Result<(), Error>, session: Arc, sessions: &ClusterSessionsContainer) -> Result, Error> { - match result { - Ok(()) if session.is_finished() => { - sessions.remove(&session.id()); - Ok(session) - }, - Ok(()) => Ok(session), - Err(error) => { - sessions.remove(&session.id()); - Err(error) - }, - } - } } -impl ClusterClient for ClusterClientImpl { - fn cluster_state(&self) -> ClusterState { - self.data.connections.cluster_state() - } - +impl ClusterClient for ClusterClientImpl { fn new_generation_session(&self, session_id: SessionId, origin: Option
, author: Address, threshold: usize) -> Result, Error> { - let mut connected_nodes = self.data.connections.connected_nodes()?; + let mut connected_nodes = self.data.connections.provider().connected_nodes()?; connected_nodes.insert(self.data.self_key_pair.public().clone()); - let cluster = create_cluster_view(&self.data, true)?; + let cluster = create_cluster_view(self.data.self_key_pair.clone(), self.data.connections.provider(), true)?; let session = self.data.sessions.generation_sessions.insert(cluster, self.data.self_key_pair.public().clone(), session_id, None, false, None)?; - Self::process_initialization_result( + process_initialization_result( session.initialize(origin, author, false, threshold, connected_nodes.into()), session, &self.data.sessions.generation_sessions) } fn new_encryption_session(&self, session_id: SessionId, requester: Requester, common_point: Public, encrypted_point: Public) -> Result, Error> { - let mut connected_nodes = self.data.connections.connected_nodes()?; + let mut connected_nodes = self.data.connections.provider().connected_nodes()?; connected_nodes.insert(self.data.self_key_pair.public().clone()); - let cluster = create_cluster_view(&self.data, true)?; + let cluster = create_cluster_view(self.data.self_key_pair.clone(), self.data.connections.provider(), true)?; let session = self.data.sessions.encryption_sessions.insert(cluster, self.data.self_key_pair.public().clone(), session_id, None, false, None)?; - Self::process_initialization_result( + process_initialization_result( session.initialize(requester, common_point, encrypted_point), session, &self.data.sessions.encryption_sessions) } fn new_decryption_session(&self, session_id: SessionId, origin: Option
, requester: Requester, version: Option, is_shadow_decryption: bool, is_broadcast_decryption: bool) -> Result, Error> { - let mut connected_nodes = self.data.connections.connected_nodes()?; + let mut connected_nodes = self.data.connections.provider().connected_nodes()?; connected_nodes.insert(self.data.self_key_pair.public().clone()); let access_key = Random.generate()?.secret().clone(); let session_id = SessionIdWithSubSession::new(session_id, access_key); - let cluster = create_cluster_view(&self.data, false)?; + let cluster = create_cluster_view(self.data.self_key_pair.clone(), self.data.connections.provider(), false)?; let session = self.data.sessions.decryption_sessions.insert(cluster, self.data.self_key_pair.public().clone(), session_id.clone(), None, false, Some(requester))?; @@ -995,23 +381,23 @@ impl ClusterClient for ClusterClientImpl { self.create_key_version_negotiation_session(session_id.id.clone()) .map(|version_session| { version_session.set_continue_action(ContinueAction::Decrypt(session.clone(), origin, is_shadow_decryption, is_broadcast_decryption)); - ClusterCore::try_continue_session(&self.data, Some(version_session)); + self.data.message_processor.try_continue_session(Some(version_session)); }) }, }; - Self::process_initialization_result( + process_initialization_result( initialization_result, session, &self.data.sessions.decryption_sessions) } fn new_schnorr_signing_session(&self, session_id: SessionId, requester: Requester, version: Option, message_hash: H256) -> Result, Error> { - let mut connected_nodes = self.data.connections.connected_nodes()?; + let mut connected_nodes = self.data.connections.provider().connected_nodes()?; connected_nodes.insert(self.data.self_key_pair.public().clone()); let access_key = Random.generate()?.secret().clone(); let session_id = SessionIdWithSubSession::new(session_id, access_key); - let cluster = create_cluster_view(&self.data, false)?; + let cluster = create_cluster_view(self.data.self_key_pair.clone(), self.data.connections.provider(), false)?; let session = self.data.sessions.schnorr_signing_sessions.insert(cluster, self.data.self_key_pair.public().clone(), session_id.clone(), None, false, Some(requester))?; let initialization_result = match version { @@ -1020,23 +406,23 @@ impl ClusterClient for ClusterClientImpl { self.create_key_version_negotiation_session(session_id.id.clone()) .map(|version_session| { version_session.set_continue_action(ContinueAction::SchnorrSign(session.clone(), message_hash)); - ClusterCore::try_continue_session(&self.data, Some(version_session)); + self.data.message_processor.try_continue_session(Some(version_session)); }) }, }; - Self::process_initialization_result( + process_initialization_result( initialization_result, session, &self.data.sessions.schnorr_signing_sessions) } fn new_ecdsa_signing_session(&self, session_id: SessionId, requester: Requester, version: Option, message_hash: H256) -> Result, Error> { - let mut connected_nodes = self.data.connections.connected_nodes()?; + let mut connected_nodes = self.data.connections.provider().connected_nodes()?; connected_nodes.insert(self.data.self_key_pair.public().clone()); let access_key = Random.generate()?.secret().clone(); let session_id = SessionIdWithSubSession::new(session_id, access_key); - let cluster = create_cluster_view(&self.data, false)?; + let cluster = create_cluster_view(self.data.self_key_pair.clone(), self.data.connections.provider(), false)?; let session = self.data.sessions.ecdsa_signing_sessions.insert(cluster, self.data.self_key_pair.public().clone(), session_id.clone(), None, false, Some(requester))?; let initialization_result = match version { @@ -1045,12 +431,12 @@ impl ClusterClient for ClusterClientImpl { self.create_key_version_negotiation_session(session_id.id.clone()) .map(|version_session| { version_session.set_continue_action(ContinueAction::EcdsaSign(session.clone(), message_hash)); - ClusterCore::try_continue_session(&self.data, Some(version_session)); + self.data.message_processor.try_continue_session(Some(version_session)); }) }, }; - Self::process_initialization_result( + process_initialization_result( initialization_result, session, &self.data.sessions.ecdsa_signing_sessions) } @@ -1061,28 +447,18 @@ impl ClusterClient for ClusterClientImpl { } fn new_servers_set_change_session(&self, session_id: Option, migration_id: Option, new_nodes_set: BTreeSet, old_set_signature: Signature, new_set_signature: Signature) -> Result, Error> { - let mut connected_nodes = self.data.connections.connected_nodes()?; - connected_nodes.insert(self.data.self_key_pair.public().clone()); - - let session_id = match session_id { - Some(session_id) if session_id == *SERVERS_SET_CHANGE_SESSION_ID => session_id, - Some(_) => return Err(Error::InvalidMessage), - None => *SERVERS_SET_CHANGE_SESSION_ID, - }; - - let cluster = create_cluster_view(&self.data, true)?; - let creation_data = Some(AdminSessionCreationData::ServersSetChange(migration_id, new_nodes_set.clone())); - let session = self.data.sessions.admin_sessions.insert(cluster, self.data.self_key_pair.public().clone(), session_id, None, true, creation_data)?; - let initialization_result = session.as_servers_set_change().expect("servers set change session is created; qed") - .initialize(new_nodes_set, old_set_signature, new_set_signature); - - if initialization_result.is_ok() { - self.data.connections.servers_set_change_creator_connector().set_key_servers_set_change_session(session.clone()); - } - - Self::process_initialization_result( - initialization_result, - session, &self.data.sessions.admin_sessions) + new_servers_set_change_session( + self.data.self_key_pair.clone(), + &self.data.sessions, + self.data.connections.provider(), + self.data.servers_set_change_creator_connector.clone(), + ServersSetChangeParams { + session_id, + migration_id, + new_nodes_set, + old_set_signature, + new_set_signature, + }) } fn add_generation_listener(&self, listener: Arc>) { @@ -1097,11 +473,6 @@ impl ClusterClient for ClusterClientImpl { self.data.sessions.negotiation_sessions.add_listener(listener); } - #[cfg(test)] - fn connect(&self) { - ClusterCore::connect_disconnected_nodes(self.data.clone()); - } - #[cfg(test)] fn make_faulty_generation_sessions(&self) { self.data.sessions.make_faulty_generation_sessions(); @@ -1113,38 +484,92 @@ impl ClusterClient for ClusterClientImpl { } #[cfg(test)] - fn key_storage(&self) -> Arc { - self.data.config.key_storage.clone() + fn is_fully_connected(&self) -> bool { + self.data.connections.provider().disconnected_nodes().is_empty() + } + + #[cfg(test)] + fn connect(&self) { + self.data.connections.connect() } } -fn make_socket_address(address: &str, port: u16) -> Result { - let ip_address: IpAddr = address.parse().map_err(|_| Error::InvalidNodeAddress)?; - Ok(SocketAddr::new(ip_address, port)) +pub struct ServersSetChangeParams { + pub session_id: Option, + pub migration_id: Option, + pub new_nodes_set: BTreeSet, + pub old_set_signature: Signature, + pub new_set_signature: Signature, +} + +pub fn new_servers_set_change_session( + self_key_pair: Arc, + sessions: &ClusterSessions, + connections: Arc, + servers_set_change_creator_connector: Arc, + params: ServersSetChangeParams, +) -> Result, Error> { + let session_id = match params.session_id { + Some(session_id) if session_id == *SERVERS_SET_CHANGE_SESSION_ID => session_id, + Some(_) => return Err(Error::InvalidMessage), + None => *SERVERS_SET_CHANGE_SESSION_ID, + }; + + let cluster = create_cluster_view(self_key_pair.clone(), connections, true)?; + let creation_data = AdminSessionCreationData::ServersSetChange(params.migration_id, params.new_nodes_set.clone()); + let session = sessions.admin_sessions + .insert(cluster, *self_key_pair.public(), session_id, None, true, Some(creation_data))?; + let initialization_result = session.as_servers_set_change().expect("servers set change session is created; qed") + .initialize(params.new_nodes_set, params.old_set_signature, params.new_set_signature); + + if initialization_result.is_ok() { + servers_set_change_creator_connector.set_key_servers_set_change_session(session.clone()); + } + + process_initialization_result( + initialization_result, + session, &sessions.admin_sessions) +} + +fn process_initialization_result( + result: Result<(), Error>, + session: Arc, + sessions: &ClusterSessionsContainer +) -> Result, Error> + where + S: ClusterSession, + SC: ClusterSessionCreator +{ + match result { + Ok(()) if session.is_finished() => { + sessions.remove(&session.id()); + Ok(session) + }, + Ok(()) => Ok(session), + Err(error) => { + sessions.remove(&session.id()); + Err(error) + }, + } } #[cfg(test)] pub mod tests { use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; - use std::time::{Duration, Instant}; - use std::collections::{BTreeSet, VecDeque}; - use parking_lot::RwLock; - use tokio::{ - prelude::{future, Future}, - }; - use parity_runtime::{ - futures::sync::oneshot, - Runtime, Executor, - }; + use std::collections::{BTreeMap, BTreeSet, VecDeque}; + use parking_lot::{Mutex, RwLock}; use ethereum_types::{Address, H256}; use ethkey::{Random, Generator, Public, Signature, sign}; use key_server_cluster::{NodeId, SessionId, Requester, Error, DummyAclStorage, DummyKeyStorage, - MapKeyServerSet, PlainNodeKeyPair, KeyStorage}; + MapKeyServerSet, PlainNodeKeyPair, NodeKeyPair}; use key_server_cluster::message::Message; - use key_server_cluster::cluster::{Cluster, ClusterCore, ClusterConfiguration, ClusterClient, ClusterState}; - use key_server_cluster::cluster_sessions::{ClusterSession, AdminSession, ClusterSessionsListener}; - use key_server_cluster::generation_session::{SessionImpl as GenerationSession, SessionState as GenerationSessionState}; + use key_server_cluster::cluster::{new_test_cluster, Cluster, ClusterCore, ClusterConfiguration, ClusterClient}; + use key_server_cluster::cluster_connections::ConnectionManager; + use key_server_cluster::cluster_connections::tests::{MessagesQueue, TestConnections}; + use key_server_cluster::cluster_sessions::{ClusterSession, ClusterSessions, AdminSession, ClusterSessionsListener}; + use key_server_cluster::generation_session::{SessionImpl as GenerationSession, + SessionState as GenerationSessionState}; use key_server_cluster::decryption_session::{SessionImpl as DecryptionSession}; use key_server_cluster::encryption_session::{SessionImpl as EncryptionSession}; use key_server_cluster::signing_session_ecdsa::{SessionImpl as EcdsaSigningSession}; @@ -1152,8 +577,6 @@ pub mod tests { use key_server_cluster::key_version_negotiation_session::{SessionImpl as KeyVersionNegotiationSession, IsolatedSessionTransport as KeyVersionNegotiationSessionTransport}; - const TIMEOUT: Duration = Duration::from_millis(1000); - #[derive(Default)] pub struct DummyClusterClient { pub generation_requests_count: AtomicUsize, @@ -1172,7 +595,6 @@ pub mod tests { } impl ClusterClient for DummyClusterClient { - fn cluster_state(&self) -> ClusterState { unimplemented!("test-only") } fn new_generation_session(&self, _session_id: SessionId, _origin: Option
, _author: Address, _threshold: usize) -> Result, Error> { self.generation_requests_count.fetch_add(1, Ordering::Relaxed); Err(Error::Internal("test-error".into())) @@ -1191,8 +613,8 @@ pub mod tests { fn make_faulty_generation_sessions(&self) { unimplemented!("test-only") } fn generation_session(&self, _session_id: &SessionId) -> Option> { unimplemented!("test-only") } - fn connect(&self) { unimplemented!("test-only") } - fn key_storage(&self) -> Arc { unimplemented!("test-only") } + fn is_fully_connected(&self) -> bool { true } + fn connect(&self) {} } impl DummyCluster { @@ -1258,366 +680,431 @@ pub mod tests { } } - /// Blocks the calling thread, looping until `predicate` returns `true` or - /// `timeout` has elapsed. - pub fn loop_until(executor: &Executor, timeout: Duration, predicate: F) - where F: Send + 'static + Fn() -> bool - { - use futures::Stream; - use tokio::timer::Interval; - - let start = Instant::now(); - let (complete_tx, complete_rx) = oneshot::channel(); - - executor.spawn(Interval::new_interval(Duration::from_millis(1)) - .and_then(move |_| { - if Instant::now() - start > timeout { - panic!("no result in {:?}", timeout); + /// Test message loop. + pub struct MessageLoop { + messages: MessagesQueue, + preserve_sessions: bool, + key_pairs_map: BTreeMap>, + acl_storages_map: BTreeMap>, + key_storages_map: BTreeMap>, + clusters_map: BTreeMap>>>, + } + + impl ::std::fmt::Debug for MessageLoop { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "MessageLoop({})", self.clusters_map.len()) + } + } + + impl MessageLoop { + /// Returns set of all nodes ids. + pub fn nodes(&self) -> BTreeSet { + self.clusters_map.keys().cloned().collect() + } + + /// Returns nodes id by its index. + pub fn node(&self, idx: usize) -> NodeId { + *self.clusters_map.keys().nth(idx).unwrap() + } + + /// Returns key pair of the node by its idx. + pub fn node_key_pair(&self, idx: usize) -> &Arc { + self.key_pairs_map.values().nth(idx).unwrap() + } + + /// Get cluster reference by its index. + pub fn cluster(&self, idx: usize) -> &Arc>> { + self.clusters_map.values().nth(idx).unwrap() + } + + /// Get keys storage reference by its index. + pub fn key_storage(&self, idx: usize) -> &Arc { + self.key_storages_map.values().nth(idx).unwrap() + } + + /// Get keys storage reference by node id. + pub fn key_storage_of(&self, node: &NodeId) -> &Arc { + &self.key_storages_map[node] + } + + /// Replace key storage of the node by its id. + pub fn replace_key_storage_of(&mut self, node: &NodeId, key_storage: Arc) { + *self.key_storages_map.get_mut(node).unwrap() = key_storage; + } + + /// Get ACL storage reference by its index. + pub fn acl_storage(&self, idx: usize) -> &Arc { + self.acl_storages_map.values().nth(idx).unwrap() + } + + /// Get sessions container reference by its index. + pub fn sessions(&self, idx: usize) -> &Arc { + &self.cluster(idx).data.sessions + } + + /// Get sessions container reference by node id. + pub fn sessions_of(&self, node: &NodeId) -> &Arc { + &self.clusters_map[node].data.sessions + } + + /// Isolate node from others. + pub fn isolate(&self, idx: usize) { + let node = self.node(idx); + for (i, cluster) in self.clusters_map.values().enumerate() { + if i == idx { + cluster.data.connections.isolate(); + } else { + cluster.data.connections.disconnect(node); } + } + } - Ok(()) - }) - .take_while(move |_| future::ok(!predicate())) - .for_each(|_| Ok(())) - .then(|_| { - complete_tx.send(()).expect("receiver dropped"); - future::ok::<(), ()>(()) - }) - ); + /// Exclude node from cluster. + pub fn exclude(&mut self, idx: usize) { + let node = self.node(idx); + for (i, cluster) in self.clusters_map.values().enumerate() { + if i != idx { + cluster.data.connections.exclude(node); + } + } + self.key_storages_map.remove(&node); + self.acl_storages_map.remove(&node); + self.key_pairs_map.remove(&node); + self.clusters_map.remove(&node); + } - complete_rx.wait().unwrap(); - } + /// Include new node to the cluster. + pub fn include(&mut self, node_key_pair: Arc) -> usize { + let key_storage = Arc::new(DummyKeyStorage::default()); + let acl_storage = Arc::new(DummyAclStorage::default()); + let cluster_params = ClusterConfiguration { + self_key_pair: node_key_pair.clone(), + key_server_set: Arc::new(MapKeyServerSet::new(false, self.nodes().iter() + .chain(::std::iter::once(node_key_pair.public())) + .map(|n| (*n, format!("127.0.0.1:{}", 13).parse().unwrap())) + .collect())), + key_storage: key_storage.clone(), + acl_storage: acl_storage.clone(), + admin_public: None, + preserve_sessions: self.preserve_sessions, + }; + let cluster = new_test_cluster(self.messages.clone(), cluster_params).unwrap(); + + for cluster in self.clusters_map.values(){ + cluster.data.connections.include(node_key_pair.public().clone()); + } + self.acl_storages_map.insert(*node_key_pair.public(), acl_storage); + self.key_storages_map.insert(*node_key_pair.public(), key_storage); + self.clusters_map.insert(*node_key_pair.public(), cluster); + self.key_pairs_map.insert(*node_key_pair.public(), node_key_pair.clone()); + self.clusters_map.keys().position(|k| k == node_key_pair.public()).unwrap() + } - pub fn all_connections_established(cluster: &Arc) -> bool { - cluster.config().key_server_set.snapshot().new_set.keys() - .filter(|p| *p != cluster.config().self_key_pair.public()) - .all(|p| cluster.connection(p).is_some()) - } + /// Is empty message queue? + pub fn is_empty(&self) -> bool { + self.messages.lock().is_empty() + } - pub fn make_clusters(runtime: &Runtime, ports_begin: u16, num_nodes: usize) -> Vec> { - let key_pairs: Vec<_> = (0..num_nodes).map(|_| Random.generate().unwrap()).collect(); - let cluster_params: Vec<_> = (0..num_nodes).map(|i| ClusterConfiguration { - self_key_pair: Arc::new(PlainNodeKeyPair::new(key_pairs[i].clone())), - listen_address: ("127.0.0.1".to_owned(), ports_begin + i as u16), - key_server_set: Arc::new(MapKeyServerSet::new(false, key_pairs.iter().enumerate() - .map(|(j, kp)| (kp.public().clone(), format!("127.0.0.1:{}", ports_begin + j as u16).parse().unwrap())) - .collect())), - allow_connecting_to_higher_nodes: false, - key_storage: Arc::new(DummyKeyStorage::default()), - acl_storage: Arc::new(DummyAclStorage::default()), - admin_public: None, - auto_migrate_enabled: false, - }).collect(); - let clusters: Vec<_> = cluster_params.into_iter().enumerate() - .map(|(_, params)| ClusterCore::new(runtime.executor(), params).unwrap()) - .collect(); + /// Takes next message from the queue. + pub fn take_message(&self) -> Option<(NodeId, NodeId, Message)> { + self.messages.lock().pop_front() + } - clusters - } + /// Process single message. + pub fn process_message(&self, from: NodeId, to: NodeId, message: Message) { + let cluster_data = &self.clusters_map[&to].data; + let connection = cluster_data.connections.provider().connection(&from).unwrap(); + cluster_data.message_processor.process_connection_message(connection, message); + } + + /// Take next message and process it. + pub fn take_and_process_message(&self) -> bool { + let (from, to, message) = match self.take_message() { + Some((from, to, message)) => (from, to, message), + None => return false, + }; - pub fn run_clusters(clusters: &[Arc]) { - for cluster in clusters { - cluster.run_listener().unwrap(); + self.process_message(from, to, message); + true } - for cluster in clusters { - cluster.run_connections().unwrap(); + + /// Loops until `predicate` returns `true` or there are no messages in the queue. + pub fn loop_until(&self, predicate: F) where F: Fn() -> bool { + while !predicate() { + if !self.take_and_process_message() { + panic!("message queue is empty but goal is not achieved"); + } + } } } - pub fn shutdown_clusters(clusters: &[Arc]) { - for cluster in clusters { - cluster.shutdown() - } + pub fn make_clusters(num_nodes: usize) -> MessageLoop { + do_make_clusters(num_nodes, false) } - /// Returns a new runtime with a static number of threads. - pub fn new_runtime() -> Runtime { - Runtime::with_thread_count(4) + pub fn make_clusters_and_preserve_sessions(num_nodes: usize) -> MessageLoop { + do_make_clusters(num_nodes, true) } - #[test] - fn cluster_connects_to_other_nodes() { - let runtime = new_runtime(); - let clusters = make_clusters(&runtime, 6010, 3); - run_clusters(&clusters); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || clusters_clone.iter().all(all_connections_established)); - shutdown_clusters(&clusters); + fn do_make_clusters(num_nodes: usize, preserve_sessions: bool) -> MessageLoop { + let ports_begin = 0; + let messages = Arc::new(Mutex::new(VecDeque::new())); + let key_pairs: Vec<_> = (0..num_nodes) + .map(|_| Arc::new(PlainNodeKeyPair::new(Random.generate().unwrap()))).collect(); + let key_storages: Vec<_> = (0..num_nodes).map(|_| Arc::new(DummyKeyStorage::default())).collect(); + let acl_storages: Vec<_> = (0..num_nodes).map(|_| Arc::new(DummyAclStorage::default())).collect(); + let cluster_params: Vec<_> = (0..num_nodes).map(|i| ClusterConfiguration { + self_key_pair: key_pairs[i].clone(), + key_server_set: Arc::new(MapKeyServerSet::new(false, key_pairs.iter().enumerate() + .map(|(j, kp)| (*kp.public(), format!("127.0.0.1:{}", ports_begin + j as u16).parse().unwrap())) + .collect())), + key_storage: key_storages[i].clone(), + acl_storage: acl_storages[i].clone(), + admin_public: None, + preserve_sessions, + }).collect(); + let clusters: Vec<_> = cluster_params.into_iter() + .map(|params| new_test_cluster(messages.clone(), params).unwrap()) + .collect(); + + let clusters_map = clusters.iter().map(|c| (*c.data.config.self_key_pair.public(), c.clone())).collect(); + let key_pairs_map = key_pairs.into_iter().map(|kp| (*kp.public(), kp)).collect(); + let key_storages_map = clusters.iter().zip(key_storages.into_iter()) + .map(|(c, ks)| (*c.data.config.self_key_pair.public(), ks)).collect(); + let acl_storages_map = clusters.iter().zip(acl_storages.into_iter()) + .map(|(c, acls)| (*c.data.config.self_key_pair.public(), acls)).collect(); + MessageLoop { preserve_sessions, messages, key_pairs_map, acl_storages_map, key_storages_map, clusters_map } } #[test] fn cluster_wont_start_generation_session_if_not_fully_connected() { - let runtime = new_runtime(); - let clusters = make_clusters(&runtime, 6013, 3); - clusters[0].run().unwrap(); - match clusters[0].client().new_generation_session(SessionId::default(), Default::default(), Default::default(), 1) { + let ml = make_clusters(3); + ml.cluster(0).data.connections.disconnect(*ml.cluster(0).data.self_key_pair.public()); + match ml.cluster(0).client().new_generation_session(SessionId::default(), Default::default(), Default::default(), 1) { Err(Error::NodeDisconnected) => (), Err(e) => panic!("unexpected error {:?}", e), _ => panic!("unexpected success"), } - shutdown_clusters(&clusters); } #[test] fn error_in_generation_session_broadcasted_to_all_other_nodes() { let _ = ::env_logger::try_init(); - let runtime = new_runtime(); - let clusters = make_clusters(&runtime, 6016, 3); - run_clusters(&clusters); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || clusters_clone.iter().all(all_connections_established)); + let ml = make_clusters(3); // ask one of nodes to produce faulty generation sessions - clusters[1].client().make_faulty_generation_sessions(); + ml.cluster(1).client().make_faulty_generation_sessions(); // start && wait for generation session to fail - let session = clusters[0].client().new_generation_session(SessionId::default(), Default::default(), Default::default(), 1).unwrap(); - let session_clone = session.clone(); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || session_clone.joint_public_and_secret().is_some() - && clusters_clone[0].client().generation_session(&SessionId::default()).is_none()); + let session = ml.cluster(0).client() + .new_generation_session(SessionId::default(), Default::default(), Default::default(), 1).unwrap(); + ml.loop_until(|| session.joint_public_and_secret().is_some() + && ml.cluster(0).client().generation_session(&SessionId::default()).is_none()); assert!(session.joint_public_and_secret().unwrap().is_err()); // check that faulty session is either removed from all nodes, or nonexistent (already removed) for i in 1..3 { - if let Some(session) = clusters[i].client().generation_session(&SessionId::default()) { - let session_clone = session.clone(); - let clusters_clone = clusters.clone(); + if let Some(session) = ml.cluster(i).client().generation_session(&SessionId::default()) { // wait for both session completion && session removal (session completion event is fired // before session is removed from its own container by cluster) - loop_until(&runtime.executor(), TIMEOUT, move || session_clone.joint_public_and_secret().is_some() - && clusters_clone[i].client().generation_session(&SessionId::default()).is_none()); + ml.loop_until(|| session.joint_public_and_secret().is_some() + && ml.cluster(i).client().generation_session(&SessionId::default()).is_none()); assert!(session.joint_public_and_secret().unwrap().is_err()); } } - shutdown_clusters(&clusters); } #[test] fn generation_session_completion_signalled_if_failed_on_master() { let _ = ::env_logger::try_init(); - let runtime = new_runtime(); - let clusters = make_clusters(&runtime, 6025, 3); - run_clusters(&clusters); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || clusters_clone.iter().all(all_connections_established)); + let ml = make_clusters(3); // ask one of nodes to produce faulty generation sessions - clusters[0].client().make_faulty_generation_sessions(); + ml.cluster(0).client().make_faulty_generation_sessions(); // start && wait for generation session to fail - let session = clusters[0].client().new_generation_session(SessionId::default(), Default::default(), Default::default(), 1).unwrap(); - let session_clone = session.clone(); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || session_clone.joint_public_and_secret().is_some() - && clusters_clone[0].client().generation_session(&SessionId::default()).is_none()); + let session = ml.cluster(0).client() + .new_generation_session(SessionId::default(), Default::default(), Default::default(), 1).unwrap(); + ml.loop_until(|| session.joint_public_and_secret().is_some() + && ml.cluster(0).client().generation_session(&SessionId::default()).is_none()); assert!(session.joint_public_and_secret().unwrap().is_err()); // check that faulty session is either removed from all nodes, or nonexistent (already removed) for i in 1..3 { - if let Some(session) = clusters[i].client().generation_session(&SessionId::default()) { - let session_clone = session.clone(); - let clusters_clone = clusters.clone(); + if let Some(session) = ml.cluster(i).client().generation_session(&SessionId::default()) { + let session = session.clone(); // wait for both session completion && session removal (session completion event is fired // before session is removed from its own container by cluster) - loop_until(&runtime.executor(), TIMEOUT, move || session_clone.joint_public_and_secret().is_some() - && clusters_clone[i].client().generation_session(&SessionId::default()).is_none()); + ml.loop_until(|| session.joint_public_and_secret().is_some() + && ml.cluster(i).client().generation_session(&SessionId::default()).is_none()); assert!(session.joint_public_and_secret().unwrap().is_err()); } } - shutdown_clusters(&clusters); } #[test] fn generation_session_is_removed_when_succeeded() { let _ = ::env_logger::try_init(); - let runtime = new_runtime(); - let clusters = make_clusters(&runtime, 6019, 3); - run_clusters(&clusters); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || clusters_clone.iter().all(all_connections_established)); + let ml = make_clusters(3); // start && wait for generation session to complete - let session = clusters[0].client().new_generation_session(SessionId::default(), Default::default(), Default::default(), 1).unwrap(); - let session_clone = session.clone(); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || (session_clone.state() == GenerationSessionState::Finished - || session_clone.state() == GenerationSessionState::Failed) - && clusters_clone[0].client().generation_session(&SessionId::default()).is_none()); + let session = ml.cluster(0).client() + .new_generation_session(SessionId::default(), Default::default(), Default::default(), 1).unwrap(); + ml.loop_until(|| (session.state() == GenerationSessionState::Finished + || session.state() == GenerationSessionState::Failed) + && ml.cluster(0).client().generation_session(&SessionId::default()).is_none()); assert!(session.joint_public_and_secret().unwrap().is_ok()); // check that on non-master nodes session is either: // already removed // or it is removed right after completion for i in 1..3 { - if let Some(session) = clusters[i].client().generation_session(&SessionId::default()) { + if let Some(session) = ml.cluster(i).client().generation_session(&SessionId::default()) { // run to completion if completion message is still on the way // AND check that it is actually removed from cluster sessions - let session_clone = session.clone(); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || (session_clone.state() == GenerationSessionState::Finished - || session_clone.state() == GenerationSessionState::Failed) - && clusters_clone[i].client().generation_session(&SessionId::default()).is_none()); + ml.loop_until(|| (session.state() == GenerationSessionState::Finished + || session.state() == GenerationSessionState::Failed) + && ml.cluster(i).client().generation_session(&SessionId::default()).is_none()); } } - shutdown_clusters(&clusters); } #[test] fn sessions_are_removed_when_initialization_fails() { - let runtime = new_runtime(); - let clusters = make_clusters(&runtime, 6022, 3); - run_clusters(&clusters); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || clusters_clone.iter().all(all_connections_established)); + let ml = make_clusters(3); + let client = ml.cluster(0).client(); // generation session { // try to start generation session => fail in initialization - assert_eq!(clusters[0].client().new_generation_session(SessionId::default(), Default::default(), Default::default(), 100).map(|_| ()), + assert_eq!( + client.new_generation_session(SessionId::default(), None, Default::default(), 100).map(|_| ()), Err(Error::NotEnoughNodesForThreshold)); // try to start generation session => fails in initialization - assert_eq!(clusters[0].client().new_generation_session(SessionId::default(), Default::default(), Default::default(), 100).map(|_| ()), + assert_eq!( + client.new_generation_session(SessionId::default(), None, Default::default(), 100).map(|_| ()), Err(Error::NotEnoughNodesForThreshold)); - assert!(clusters[0].data.sessions.generation_sessions.is_empty()); + assert!(ml.cluster(0).data.sessions.generation_sessions.is_empty()); } // decryption session { // try to start decryption session => fails in initialization - assert_eq!(clusters[0].client().new_decryption_session(Default::default(), Default::default(), Default::default(), Some(Default::default()), false, false).map(|_| ()), + assert_eq!( + client.new_decryption_session( + Default::default(), Default::default(), Default::default(), Some(Default::default()), false, false + ).map(|_| ()), Err(Error::InvalidMessage)); // try to start generation session => fails in initialization - assert_eq!(clusters[0].client().new_decryption_session(Default::default(), Default::default(), Default::default(), Some(Default::default()), false, false).map(|_| ()), + assert_eq!( + client.new_decryption_session( + Default::default(), Default::default(), Default::default(), Some(Default::default()), false, false + ).map(|_| ()), Err(Error::InvalidMessage)); - assert!(clusters[0].data.sessions.decryption_sessions.is_empty()); - assert!(clusters[0].data.sessions.negotiation_sessions.is_empty()); + assert!(ml.cluster(0).data.sessions.decryption_sessions.is_empty()); + assert!(ml.cluster(0).data.sessions.negotiation_sessions.is_empty()); } - shutdown_clusters(&clusters); } - // test ignored because of - // - // https://github.com/paritytech/parity-ethereum/issues/9635 #[test] - #[ignore] fn schnorr_signing_session_completes_if_node_does_not_have_a_share() { let _ = ::env_logger::try_init(); - let runtime = new_runtime(); - let clusters = make_clusters(&runtime, 6028, 3); - run_clusters(&clusters); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || clusters_clone.iter().all(all_connections_established)); + let ml = make_clusters(3); // start && wait for generation session to complete - let session = clusters[0].client().new_generation_session(SessionId::default(), Default::default(), Default::default(), 1).unwrap(); - let session_clone = session.clone(); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || (session_clone.state() == GenerationSessionState::Finished - || session_clone.state() == GenerationSessionState::Failed) - && clusters_clone[0].client().generation_session(&SessionId::default()).is_none()); + let session = ml.cluster(0).client(). + new_generation_session(SessionId::default(), Default::default(), Default::default(), 1).unwrap(); + ml.loop_until(|| (session.state() == GenerationSessionState::Finished + || session.state() == GenerationSessionState::Failed) + && ml.cluster(0).client().generation_session(&SessionId::default()).is_none()); assert!(session.joint_public_and_secret().unwrap().is_ok()); // now remove share from node2 - assert!((0..3).all(|i| clusters[i].data.sessions.generation_sessions.is_empty())); - clusters[2].data.config.key_storage.remove(&Default::default()).unwrap(); + assert!((0..3).all(|i| ml.cluster(i).data.sessions.generation_sessions.is_empty())); + ml.cluster(2).data.config.key_storage.remove(&Default::default()).unwrap(); // and try to sign message with generated key let signature = sign(Random.generate().unwrap().secret(), &Default::default()).unwrap(); - let session0 = clusters[0].client().new_schnorr_signing_session(Default::default(), signature.into(), None, Default::default()).unwrap(); - let session = clusters[0].data.sessions.schnorr_signing_sessions.first().unwrap(); + let session0 = ml.cluster(0).client() + .new_schnorr_signing_session(Default::default(), signature.into(), None, Default::default()).unwrap(); + let session = ml.cluster(0).data.sessions.schnorr_signing_sessions.first().unwrap(); - let session_clone = session.clone(); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || session_clone.is_finished() && (0..3).all(|i| - clusters_clone[i].data.sessions.schnorr_signing_sessions.is_empty())); + ml.loop_until(|| session.is_finished() && (0..3).all(|i| + ml.cluster(i).data.sessions.schnorr_signing_sessions.is_empty())); session0.wait().unwrap(); // and try to sign message with generated key using node that has no key share let signature = sign(Random.generate().unwrap().secret(), &Default::default()).unwrap(); - let session2 = clusters[2].client().new_schnorr_signing_session(Default::default(), signature.into(), None, Default::default()).unwrap(); - let session = clusters[2].data.sessions.schnorr_signing_sessions.first().unwrap(); + let session2 = ml.cluster(2).client() + .new_schnorr_signing_session(Default::default(), signature.into(), None, Default::default()).unwrap(); + let session = ml.cluster(2).data.sessions.schnorr_signing_sessions.first().unwrap(); - let session_clone = session.clone(); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || session_clone.is_finished() && (0..3).all(|i| - clusters_clone[i].data.sessions.schnorr_signing_sessions.is_empty())); + ml.loop_until(|| session.is_finished() && (0..3).all(|i| + ml.cluster(i).data.sessions.schnorr_signing_sessions.is_empty())); session2.wait().unwrap(); // now remove share from node1 - clusters[1].data.config.key_storage.remove(&Default::default()).unwrap(); + ml.cluster(1).data.config.key_storage.remove(&Default::default()).unwrap(); // and try to sign message with generated key let signature = sign(Random.generate().unwrap().secret(), &Default::default()).unwrap(); - let session1 = clusters[0].client().new_schnorr_signing_session(Default::default(), signature.into(), None, Default::default()).unwrap(); - let session = clusters[0].data.sessions.schnorr_signing_sessions.first().unwrap(); + let session1 = ml.cluster(0).client() + .new_schnorr_signing_session(Default::default(), signature.into(), None, Default::default()).unwrap(); + let session = ml.cluster(0).data.sessions.schnorr_signing_sessions.first().unwrap(); - let session = session.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || session.is_finished()); + ml.loop_until(|| session.is_finished()); session1.wait().unwrap_err(); - shutdown_clusters(&clusters); } - // test ignored because of - // - // https://github.com/paritytech/parity-ethereum/issues/9635 #[test] - #[ignore] fn ecdsa_signing_session_completes_if_node_does_not_have_a_share() { let _ = ::env_logger::try_init(); - let runtime = new_runtime(); - let clusters = make_clusters(&runtime, 6041, 4); - run_clusters(&clusters); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || clusters_clone.iter().all(all_connections_established)); + let ml = make_clusters(4); // start && wait for generation session to complete - let session = clusters[0].client().new_generation_session(SessionId::default(), Default::default(), Default::default(), 1).unwrap(); - let session_clone = session.clone(); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), TIMEOUT, move || (session_clone.state() == GenerationSessionState::Finished - || session_clone.state() == GenerationSessionState::Failed) - && clusters_clone[0].client().generation_session(&SessionId::default()).is_none()); + let session = ml.cluster(0).client() + .new_generation_session(SessionId::default(), Default::default(), Default::default(), 1).unwrap(); + ml.loop_until(|| (session.state() == GenerationSessionState::Finished + || session.state() == GenerationSessionState::Failed) + && ml.cluster(0).client().generation_session(&SessionId::default()).is_none()); assert!(session.joint_public_and_secret().unwrap().is_ok()); // now remove share from node2 - assert!((0..3).all(|i| clusters[i].data.sessions.generation_sessions.is_empty())); - clusters[2].data.config.key_storage.remove(&Default::default()).unwrap(); + assert!((0..3).all(|i| ml.cluster(i).data.sessions.generation_sessions.is_empty())); + ml.cluster(2).data.config.key_storage.remove(&Default::default()).unwrap(); // and try to sign message with generated key let signature = sign(Random.generate().unwrap().secret(), &Default::default()).unwrap(); - let session0 = clusters[0].client().new_ecdsa_signing_session(Default::default(), signature.into(), None, H256::random()).unwrap(); - let session = clusters[0].data.sessions.ecdsa_signing_sessions.first().unwrap(); + let session0 = ml.cluster(0).client() + .new_ecdsa_signing_session(Default::default(), signature.into(), None, H256::random()).unwrap(); + let session = ml.cluster(0).data.sessions.ecdsa_signing_sessions.first().unwrap(); - let session_clone = session.clone(); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), Duration::from_millis(1000), move || session_clone.is_finished() && (0..3).all(|i| - clusters_clone[i].data.sessions.ecdsa_signing_sessions.is_empty())); + ml.loop_until(|| session.is_finished() && (0..3).all(|i| + ml.cluster(i).data.sessions.ecdsa_signing_sessions.is_empty())); session0.wait().unwrap(); // and try to sign message with generated key using node that has no key share let signature = sign(Random.generate().unwrap().secret(), &Default::default()).unwrap(); - let session2 = clusters[2].client().new_ecdsa_signing_session(Default::default(), signature.into(), None, H256::random()).unwrap(); - let session = clusters[2].data.sessions.ecdsa_signing_sessions.first().unwrap(); - let session_clone = session.clone(); - let clusters_clone = clusters.clone(); - loop_until(&runtime.executor(), Duration::from_millis(1000), move || session_clone.is_finished() && (0..3).all(|i| - clusters_clone[i].data.sessions.ecdsa_signing_sessions.is_empty())); + let session2 = ml.cluster(2).client() + .new_ecdsa_signing_session(Default::default(), signature.into(), None, H256::random()).unwrap(); + let session = ml.cluster(2).data.sessions.ecdsa_signing_sessions.first().unwrap(); + ml.loop_until(|| session.is_finished() && (0..3).all(|i| + ml.cluster(i).data.sessions.ecdsa_signing_sessions.is_empty())); session2.wait().unwrap(); // now remove share from node1 - clusters[1].data.config.key_storage.remove(&Default::default()).unwrap(); + ml.cluster(1).data.config.key_storage.remove(&Default::default()).unwrap(); // and try to sign message with generated key let signature = sign(Random.generate().unwrap().secret(), &Default::default()).unwrap(); - let session1 = clusters[0].client().new_ecdsa_signing_session(Default::default(), signature.into(), None, H256::random()).unwrap(); - let session = clusters[0].data.sessions.ecdsa_signing_sessions.first().unwrap(); - loop_until(&runtime.executor(), Duration::from_millis(1000), move || session.is_finished()); + let session1 = ml.cluster(0).client() + .new_ecdsa_signing_session(Default::default(), signature.into(), None, H256::random()).unwrap(); + let session = ml.cluster(0).data.sessions.ecdsa_signing_sessions.first().unwrap(); + ml.loop_until(|| session.is_finished()); session1.wait().unwrap_err(); - shutdown_clusters(&clusters); } } diff --git a/secret-store/src/key_server_cluster/cluster_connections.rs b/secret-store/src/key_server_cluster/cluster_connections.rs new file mode 100644 index 0000000000..b484e6d8e0 --- /dev/null +++ b/secret-store/src/key_server_cluster/cluster_connections.rs @@ -0,0 +1,176 @@ +// 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::collections::BTreeSet; +use std::sync::Arc; +use key_server_cluster::{Error, NodeId}; +use key_server_cluster::message::Message; + +/// Connection to the single node. Provides basic information about connected node and +/// allows sending messages to this node. +pub trait Connection: Send + Sync { + /// Is this inbound connection? This only matters when both nodes are simultaneously establishing + /// two connections to each other. The agreement is that the inbound connection from the node with + /// lower NodeId is used and the other connection is closed. + fn is_inbound(&self) -> bool; + /// Returns id of the connected node. + fn node_id(&self) -> &NodeId; + /// Returns 'address' of the node to use in traces. + fn node_address(&self) -> String; + /// Send message to the connected node. + fn send_message(&self, message: Message); +} + +/// Connections manager. Responsible for keeping us connected to all required nodes. +pub trait ConnectionManager: 'static + Send + Sync { + /// Returns shared reference to connections provider. + fn provider(&self) -> Arc; + /// Try to reach all disconnected nodes immediately. This method is exposed mostly for + /// tests, where all 'nodes' are starting listening for incoming connections first and + /// only after this, they're actually start connecting to each other. + fn connect(&self); +} + +/// Connections provider. Holds all active connections and the set of nodes that we need to +/// connect to. At any moment connection could be lost and the set of connected/disconnected +/// nodes could change (at behalf of the connection manager). +/// Clone operation should be cheap (Arc). +pub trait ConnectionProvider: Send + Sync { + /// Returns the set of currently connected nodes. Error is returned when our node is + /// not a part of the cluster ('isolated' node). + fn connected_nodes(&self) -> Result, Error>; + /// Returns the set of currently disconnected nodes. + fn disconnected_nodes(&self) -> BTreeSet; + /// Returns the reference to the active node connection or None if the node is not connected. + fn connection(&self, node: &NodeId) -> Option>; +} + +#[cfg(test)] +pub mod tests { + use std::collections::{BTreeSet, VecDeque}; + use std::sync::Arc; + use std::sync::atomic::{AtomicBool, Ordering}; + use parking_lot::Mutex; + use key_server_cluster::{Error, NodeId}; + use key_server_cluster::message::Message; + use super::{ConnectionManager, Connection, ConnectionProvider}; + + /// Shared messages queue. + pub type MessagesQueue = Arc>>; + + /// Single node connections. + pub struct TestConnections { + node: NodeId, + is_isolated: AtomicBool, + connected_nodes: Mutex>, + disconnected_nodes: Mutex>, + messages: MessagesQueue, + } + + /// Single connection. + pub struct TestConnection { + from: NodeId, + to: NodeId, + messages: MessagesQueue, + } + + impl TestConnections { + pub fn isolate(&self) { + let connected_nodes = ::std::mem::replace(&mut *self.connected_nodes.lock(), Default::default()); + self.is_isolated.store(true, Ordering::Relaxed); + self.disconnected_nodes.lock().extend(connected_nodes) + } + + pub fn disconnect(&self, node: NodeId) { + self.connected_nodes.lock().remove(&node); + self.disconnected_nodes.lock().insert(node); + } + + pub fn exclude(&self, node: NodeId) { + self.connected_nodes.lock().remove(&node); + self.disconnected_nodes.lock().remove(&node); + } + + pub fn include(&self, node: NodeId) { + self.connected_nodes.lock().insert(node); + } + } + + impl ConnectionManager for Arc { + fn provider(&self) -> Arc { + self.clone() + } + + fn connect(&self) {} + } + + impl ConnectionProvider for TestConnections { + fn connected_nodes(&self) -> Result, Error> { + match self.is_isolated.load(Ordering::Relaxed) { + false => Ok(self.connected_nodes.lock().clone()), + true => Err(Error::NodeDisconnected), + } + } + + fn disconnected_nodes(&self) -> BTreeSet { + self.disconnected_nodes.lock().clone() + } + + fn connection(&self, node: &NodeId) -> Option> { + match self.connected_nodes.lock().contains(node) { + true => Some(Arc::new(TestConnection { + from: self.node, + to: *node, + messages: self.messages.clone(), + })), + false => None, + } + } + } + + impl Connection for TestConnection { + fn is_inbound(&self) -> bool { + false + } + + fn node_id(&self) -> &NodeId { + &self.to + } + + fn node_address(&self) -> String { + format!("{}", self.to) + } + + fn send_message(&self, message: Message) { + self.messages.lock().push_back((self.from, self.to, message)) + } + } + + pub fn new_test_connections( + messages: MessagesQueue, + node: NodeId, + mut nodes: BTreeSet + ) -> Arc { + let is_isolated = !nodes.remove(&node); + Arc::new(TestConnections { + node, + is_isolated: AtomicBool::new(is_isolated), + connected_nodes: Mutex::new(nodes), + disconnected_nodes: Default::default(), + messages, + }) + } +} diff --git a/secret-store/src/key_server_cluster/cluster_connections_net.rs b/secret-store/src/key_server_cluster/cluster_connections_net.rs new file mode 100644 index 0000000000..bda7f7dd28 --- /dev/null +++ b/secret-store/src/key_server_cluster/cluster_connections_net.rs @@ -0,0 +1,539 @@ +// 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::collections::{BTreeMap, BTreeSet}; +use std::collections::btree_map::Entry; +use std::io; +use std::net::{SocketAddr, IpAddr}; +use std::sync::Arc; +use std::time::{Duration, Instant}; +use futures::{future, Future, Stream}; +use parking_lot::{Mutex, RwLock}; +use tokio::net::{TcpListener, TcpStream}; +use tokio::timer::{Interval, timeout::Error as TimeoutError}; +use tokio_io::IoFuture; +use ethkey::KeyPair; +use parity_runtime::Executor; +use key_server_cluster::{Error, NodeId, ClusterConfiguration, NodeKeyPair}; +use key_server_cluster::cluster_connections::{ConnectionProvider, Connection, ConnectionManager}; +use key_server_cluster::connection_trigger::{Maintain, ConnectionTrigger}; +use key_server_cluster::cluster_message_processor::MessageProcessor; +use key_server_cluster::io::{DeadlineStatus, ReadMessage, SharedTcpStream, + read_encrypted_message, WriteMessage, write_encrypted_message}; +use key_server_cluster::message::{self, ClusterMessage, Message}; +use key_server_cluster::net::{accept_connection as io_accept_connection, + connect as io_connect, Connection as IoConnection}; + +/// Empty future. +pub type BoxedEmptyFuture = Box + Send>; + +/// Maintain interval (seconds). Every MAINTAIN_INTERVAL seconds node: +/// 1) checks if connected nodes are responding to KeepAlive messages +/// 2) tries to connect to disconnected nodes +/// 3) checks if enc/dec sessions are time-outed +const MAINTAIN_INTERVAL: u64 = 10; + +/// When no messages have been received from node within KEEP_ALIVE_SEND_INTERVAL seconds, +/// we must send KeepAlive message to the node to check if it still responds to messages. +const KEEP_ALIVE_SEND_INTERVAL: Duration = Duration::from_secs(30); +/// When no messages have been received from node within KEEP_ALIVE_DISCONNECT_INTERVAL seconds, +/// we must treat this node as non-responding && disconnect from it. +const KEEP_ALIVE_DISCONNECT_INTERVAL: Duration = Duration::from_secs(60); + +/// Network connection manager configuration. +pub struct NetConnectionsManagerConfig { + /// Allow connecting to 'higher' nodes. + pub allow_connecting_to_higher_nodes: bool, + /// Interface to listen to. + pub listen_address: (String, u16), + /// True if we should autostart key servers set change session when servers set changes? + /// This will only work when servers set is configured using KeyServerSet contract. + pub auto_migrate_enabled: bool, +} + +/// Network connections manager. +pub struct NetConnectionsManager { + /// Address we're listening for incoming connections. + listen_address: SocketAddr, + /// Shared cluster connections data reference. + data: Arc, +} + +/// Network connections data. Shared among NetConnectionsManager and spawned futures. +struct NetConnectionsData { + /// Allow connecting to 'higher' nodes. + allow_connecting_to_higher_nodes: bool, + /// Reference to tokio task executor. + executor: Executor, + /// Key pair of this node. + self_key_pair: Arc, + /// Network messages processor. + message_processor: Arc, + /// Connections trigger. + trigger: Mutex>, + /// Mutable connection data. + container: Arc>, +} + +/// Network connections container. This is the only mutable data of NetConnectionsManager. +/// The set of nodes is mutated by the connection trigger and the connections set is also +/// mutated by spawned futures. +pub struct NetConnectionsContainer { + /// Is this node isolated from cluster? + pub is_isolated: bool, + /// Current key servers set. + pub nodes: BTreeMap, + /// Active connections to key servers. + pub connections: BTreeMap>, +} + +/// Network connection to single key server node. +pub struct NetConnection { + executor: Executor, + /// Id of the peer node. + node_id: NodeId, + /// Address of the peer node. + node_address: SocketAddr, + /// Is this inbound (true) or outbound (false) connection? + is_inbound: bool, + /// Key pair that is used to encrypt connection' messages. + key: KeyPair, + /// Last message time. + last_message_time: RwLock, + /// Underlying TCP stream. + stream: SharedTcpStream, +} + +impl NetConnectionsManager { + /// Create new network connections manager. + pub fn new( + executor: Executor, + message_processor: Arc, + trigger: Box, + container: Arc>, + config: &ClusterConfiguration, + net_config: NetConnectionsManagerConfig, + ) -> Result { + let listen_address = make_socket_address( + &net_config.listen_address.0, + net_config.listen_address.1)?; + + Ok(NetConnectionsManager { + listen_address, + data: Arc::new(NetConnectionsData { + allow_connecting_to_higher_nodes: net_config.allow_connecting_to_higher_nodes, + executor, + message_processor, + self_key_pair: config.self_key_pair.clone(), + trigger: Mutex::new(trigger), + container, + }), + }) + } + + /// Start listening for connections and schedule connections maintenance. + pub fn start(&self) -> Result<(), Error> { + net_listen(&self.listen_address, self.data.clone())?; + net_schedule_maintain(self.data.clone()); + Ok(()) + } +} + +impl ConnectionManager for NetConnectionsManager { + fn provider(&self) -> Arc { + self.data.container.clone() + } + + fn connect(&self) { + net_connect_disconnected(self.data.clone()); + } +} + +impl ConnectionProvider for RwLock { + fn connected_nodes(&self) -> Result, Error> { + let connections = self.read(); + if connections.is_isolated { + return Err(Error::NodeDisconnected); + } + + Ok(connections.connections.keys().cloned().collect()) + } + + fn disconnected_nodes(&self) -> BTreeSet { + let connections = self.read(); + connections.nodes.keys() + .filter(|node_id| !connections.connections.contains_key(node_id)) + .cloned() + .collect() + } + + fn connection(&self, node: &NodeId) -> Option> { + match self.read().connections.get(node).cloned() { + Some(connection) => Some(connection), + None => None, + } + } +} + +impl NetConnection { + /// Create new connection. + pub fn new(executor: Executor, is_inbound: bool, connection: IoConnection) -> NetConnection { + NetConnection { + executor, + node_id: connection.node_id, + node_address: connection.address, + is_inbound: is_inbound, + stream: connection.stream, + key: connection.key, + last_message_time: RwLock::new(Instant::now()), + } + } + + /// Get last message time. + pub fn last_message_time(&self) -> Instant { + *self.last_message_time.read() + } + + /// Update last message time + pub fn set_last_message_time(&self, last_message_time: Instant) { + *self.last_message_time.write() = last_message_time + } + + /// Returns future that sends encrypted message over this connection. + pub fn send_message_future(&self, message: Message) -> WriteMessage { + write_encrypted_message(self.stream.clone(), &self.key, message) + } + + /// Returns future that reads encrypted message from this connection. + pub fn read_message_future(&self) -> ReadMessage { + read_encrypted_message(self.stream.clone(), self.key.clone()) + } +} + +impl Connection for NetConnection { + fn is_inbound(&self) -> bool { + self.is_inbound + } + + fn node_id(&self) -> &NodeId { + &self.node_id + } + + fn node_address(&self) -> String { + format!("{}", self.node_address) + } + + fn send_message(&self, message: Message) { + execute(&self.executor, self.send_message_future(message).then(|_| Ok(()))); + } +} + +impl NetConnectionsData { + /// Executes closure for each active connection. + pub fn active_connections(&self) -> Vec> { + self.container.read().connections.values().cloned().collect() + } + + /// Executes closure for each disconnected node. + pub fn disconnected_nodes(&self) -> Vec<(NodeId, SocketAddr)> { + let container = self.container.read(); + container.nodes.iter() + .filter(|(node_id, _)| !container.connections.contains_key(node_id)) + .map(|(node_id, addr)| (*node_id, *addr)) + .collect() + } + + /// Try to insert new connection. Returns true if connection has been inserted. + /// Returns false (and ignores connections) if: + /// - we do not expect connection from this node + /// - we are already connected to the node and existing connection 'supersede' + /// new connection by agreement + pub fn insert(&self, connection: Arc) -> bool { + let node = *connection.node_id(); + let mut container = self.container.write(); + if !container.nodes.contains_key(&node) { + trace!(target: "secretstore_net", "{}: ignoring unknown connection from {} at {}", + self.self_key_pair.public(), node, connection.node_address()); + return false; + } + + if container.connections.contains_key(&node) { + // we have already connected to the same node + // the agreement is that node with lower id must establish connection to node with higher id + if (*self.self_key_pair.public() < node && connection.is_inbound()) + || (*self.self_key_pair.public() > node && !connection.is_inbound()) { + return false; + } + } + + trace!(target: "secretstore_net", + "{}: inserting connection to {} at {}. Connected to {} of {} nodes", + self.self_key_pair.public(), node, connection.node_address(), + container.connections.len() + 1, container.nodes.len()); + container.connections.insert(node, connection); + + true + } + + /// Tries to remove connection. Returns true if connection has been removed. + /// Returns false if we do not know this connection. + pub fn remove(&self, connection: &NetConnection) -> bool { + let node_id = *connection.node_id(); + let is_inbound = connection.is_inbound(); + let mut container = self.container.write(); + if let Entry::Occupied(entry) = container.connections.entry(node_id) { + if entry.get().is_inbound() != is_inbound { + return false; + } + + trace!(target: "secretstore_net", "{}: removing connection to {} at {}", + self.self_key_pair.public(), node_id, entry.get().node_address()); + entry.remove_entry(); + + true + } else { + false + } + } +} + +/// Listen incoming connections. +fn net_listen( + listen_address: &SocketAddr, + data: Arc, +) -> Result<(), Error> { + execute(&data.executor, net_listen_future(listen_address, data.clone())?); + Ok(()) +} + +/// Listen incoming connections future. +fn net_listen_future( + listen_address: &SocketAddr, + data: Arc, +) -> Result { + Ok(Box::new(TcpListener::bind(listen_address)? + .incoming() + .and_then(move |stream| { + net_accept_connection(data.clone(), stream); + Ok(()) + }) + .for_each(|_| Ok(())) + .then(|_| future::ok(())))) +} + +/// Accept incoming connection. +fn net_accept_connection( + data: Arc, + stream: TcpStream, +) { + execute(&data.executor, net_accept_connection_future(data.clone(), stream)); +} + +/// Accept incoming connection future. +fn net_accept_connection_future(data: Arc, stream: TcpStream) -> BoxedEmptyFuture { + Box::new(io_accept_connection(stream, data.self_key_pair.clone()) + .then(move |result| net_process_connection_result(data, None, result)) + .then(|_| future::ok(()))) +} + +/// Connect to remote node. +fn net_connect( + data: Arc, + remote: SocketAddr, +) { + execute(&data.executor, net_connect_future(data.clone(), remote)); +} + +/// Connect to remote node future. +fn net_connect_future( + data: Arc, + remote: SocketAddr, +) -> BoxedEmptyFuture { + let disconnected_nodes = data.container.disconnected_nodes(); + Box::new(io_connect(&remote, data.self_key_pair.clone(), disconnected_nodes) + .then(move |result| net_process_connection_result(data, Some(remote), result)) + .then(|_| future::ok(()))) +} + +/// Process network connection result. +fn net_process_connection_result( + data: Arc, + outbound_addr: Option, + result: Result>, TimeoutError>, +) -> IoFuture> { + match result { + Ok(DeadlineStatus::Meet(Ok(connection))) => { + let connection = Arc::new(NetConnection::new(data.executor.clone(), outbound_addr.is_none(), connection)); + if data.insert(connection.clone()) { + let maintain_action = data.trigger.lock().on_connection_established(connection.node_id()); + maintain_connection_trigger(data.clone(), maintain_action); + + return net_process_connection_messages(data, connection); + } + }, + Ok(DeadlineStatus::Meet(Err(err))) => { + warn!(target: "secretstore_net", "{}: protocol error '{}' when establishing {} connection{}", + data.self_key_pair.public(), err, if outbound_addr.is_some() { "outbound" } else { "inbound" }, + outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); + }, + Ok(DeadlineStatus::Timeout) => { + warn!(target: "secretstore_net", "{}: timeout when establishing {} connection{}", + data.self_key_pair.public(), if outbound_addr.is_some() { "outbound" } else { "inbound" }, + outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); + }, + Err(err) => { + warn!(target: "secretstore_net", "{}: network error '{}' when establishing {} connection{}", + data.self_key_pair.public(), err, if outbound_addr.is_some() { "outbound" } else { "inbound" }, + outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); + }, + } + + Box::new(future::ok(Ok(()))) +} + +/// Process connection messages. +fn net_process_connection_messages( + data: Arc, + connection: Arc, +) -> IoFuture> { + Box::new(connection + .read_message_future() + .then(move |result| + match result { + Ok((_, Ok(message))) => { + connection.set_last_message_time(Instant::now()); + data.message_processor.process_connection_message(connection.clone(), message); + // continue serving connection + let process_messages_future = net_process_connection_messages( + data.clone(), connection).then(|_| Ok(())); + execute(&data.executor, process_messages_future); + Box::new(future::ok(Ok(()))) + }, + Ok((_, Err(err))) => { + warn!(target: "secretstore_net", "{}: protocol error '{}' when reading message from node {}", + data.self_key_pair.public(), err, connection.node_id()); + // continue serving connection + let process_messages_future = net_process_connection_messages( + data.clone(), connection).then(|_| Ok(())); + execute(&data.executor, process_messages_future); + Box::new(future::ok(Err(err))) + }, + Err(err) => { + let node_id = *connection.node_id(); + warn!(target: "secretstore_net", "{}: network error '{}' when reading message from node {}", + data.self_key_pair.public(), err, node_id); + // close connection + if data.remove(&*connection) { + let maintain_action = data.trigger.lock().on_connection_closed(&node_id); + maintain_connection_trigger(data, maintain_action); + } + Box::new(future::err(err)) + }, + } + )) +} + +/// Schedule connections. maintain. +fn net_schedule_maintain(data: Arc) { + let closure_data = data.clone(); + execute(&data.executor, Interval::new_interval(Duration::new(MAINTAIN_INTERVAL, 0)) + .and_then(move |_| Ok(net_maintain(closure_data.clone()))) + .for_each(|_| Ok(())) + .then(|_| future::ok(()))); +} + +/// Maintain network connections. +fn net_maintain(data: Arc) { + trace!(target: "secretstore_net", "{}: executing maintain procedures", data.self_key_pair.public()); + + update_nodes_set(data.clone()); + data.message_processor.maintain_sessions(); + net_keep_alive(data.clone()); + net_connect_disconnected(data); +} + +/// Send keep alive messages to remote nodes. +fn net_keep_alive(data: Arc) { + let now = Instant::now(); + let active_connections = data.active_connections(); + for connection in active_connections { + let last_message_diff = now - connection.last_message_time(); + if last_message_diff > KEEP_ALIVE_DISCONNECT_INTERVAL { + warn!(target: "secretstore_net", "{}: keep alive timeout for node {}", + data.self_key_pair.public(), connection.node_id()); + + let node_id = *connection.node_id(); + if data.remove(&*connection) { + let maintain_action = data.trigger.lock().on_connection_closed(&node_id); + maintain_connection_trigger(data.clone(), maintain_action); + } + data.message_processor.process_disconnect(&node_id); + } + else if last_message_diff > KEEP_ALIVE_SEND_INTERVAL { + connection.send_message(Message::Cluster(ClusterMessage::KeepAlive(message::KeepAlive {}))); + } + } +} + +/// Connect disconnected nodes. +fn net_connect_disconnected(data: Arc) { + let disconnected_nodes = data.disconnected_nodes(); + for (node_id, address) in disconnected_nodes { + if data.allow_connecting_to_higher_nodes || *data.self_key_pair.public() < node_id { + net_connect(data.clone(), address); + } + } +} + +/// Schedule future execution. +fn execute + Send + 'static>(executor: &Executor, f: F) { + if let Err(err) = future::Executor::execute(executor, Box::new(f)) { + error!("Secret store runtime unable to spawn task. Runtime is shutting down. ({:?})", err); + } +} + +/// Try to update active nodes set from connection trigger. +fn update_nodes_set(data: Arc) { + let maintain_action = data.trigger.lock().on_maintain(); + maintain_connection_trigger(data, maintain_action); +} + +/// Execute maintain procedures of connections trigger. +fn maintain_connection_trigger(data: Arc, maintain_action: Option) { + if maintain_action == Some(Maintain::SessionAndConnections) || maintain_action == Some(Maintain::Session) { + let session_params = data.trigger.lock().maintain_session(); + if let Some(session_params) = session_params { + let session = data.message_processor.start_servers_set_change_session(session_params); + match session { + Ok(_) => trace!(target: "secretstore_net", "{}: started auto-migrate session", + data.self_key_pair.public()), + Err(err) => trace!(target: "secretstore_net", "{}: failed to start auto-migrate session with: {}", + data.self_key_pair.public(), err), + } + } + } + if maintain_action == Some(Maintain::SessionAndConnections) || maintain_action == Some(Maintain::Connections) { + let mut trigger = data.trigger.lock(); + let mut data = data.container.write(); + trigger.maintain_connections(&mut *data); + } +} + +/// Compose SocketAddr from configuration' address and port. +fn make_socket_address(address: &str, port: u16) -> Result { + let ip_address: IpAddr = address.parse().map_err(|_| Error::InvalidNodeAddress)?; + Ok(SocketAddr::new(ip_address, port)) +} diff --git a/secret-store/src/key_server_cluster/cluster_message_processor.rs b/secret-store/src/key_server_cluster/cluster_message_processor.rs new file mode 100644 index 0000000000..b4ba5ef03b --- /dev/null +++ b/secret-store/src/key_server_cluster/cluster_message_processor.rs @@ -0,0 +1,357 @@ +// 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::sync::Arc; +use key_server_cluster::{Error, NodeId, NodeKeyPair}; +use key_server_cluster::cluster::{ServersSetChangeParams, new_servers_set_change_session}; +use key_server_cluster::cluster_sessions::{AdminSession}; +use key_server_cluster::cluster_connections::{ConnectionProvider, Connection}; +use key_server_cluster::cluster_sessions::{ClusterSession, ClusterSessions, ClusterSessionsContainer, + create_cluster_view}; +use key_server_cluster::cluster_sessions_creator::{ClusterSessionCreator, IntoSessionId}; +use key_server_cluster::message::{self, Message, ClusterMessage}; +use key_server_cluster::key_version_negotiation_session::{SessionImpl as KeyVersionNegotiationSession, + IsolatedSessionTransport as KeyVersionNegotiationSessionTransport, ContinueAction}; +use key_server_cluster::connection_trigger::ServersSetChangeSessionCreatorConnector; + +/// Something that is able to process signals/messages from other nodes. +pub trait MessageProcessor: Send + Sync { + /// Process disconnect from the remote node. + fn process_disconnect(&self, node: &NodeId); + /// Process single message from the connection. + fn process_connection_message(&self, connection: Arc, message: Message); + + /// Start servers set change session. This is typically used by ConnectionManager when + /// it detects that auto-migration session needs to be started. + fn start_servers_set_change_session(&self, params: ServersSetChangeParams) -> Result, Error>; + /// Try to continue session after key version negotiation session is completed. + fn try_continue_session( + &self, + session: Option>> + ); + /// Maintain active sessions. Typically called by the ConnectionManager at some intervals. + /// Should cancel stalled sessions and send keep-alive messages for sessions that support it. + fn maintain_sessions(&self); +} + +/// Bridge between ConnectionManager and ClusterSessions. +pub struct SessionsMessageProcessor { + self_key_pair: Arc, + servers_set_change_creator_connector: Arc, + sessions: Arc, + connections: Arc, +} + +impl SessionsMessageProcessor { + /// Create new instance of SessionsMessageProcessor. + pub fn new( + self_key_pair: Arc, + servers_set_change_creator_connector: Arc, + sessions: Arc, + connections: Arc, + ) -> Self { + SessionsMessageProcessor { + self_key_pair, + servers_set_change_creator_connector, + sessions, + connections, + } + } + + /// Process single session message from connection. + fn process_message, D>( + &self, + sessions: &ClusterSessionsContainer, + connection: Arc, + mut message: Message, + ) -> Option> + where + Message: IntoSessionId + { + // get or create new session, if required + let mut sender = *connection.node_id(); + let session = self.prepare_session(sessions, &sender, &message); + // send error if session is not found, or failed to create + let session = match session { + Ok(session) => session, + Err(error) => { + // this is new session => it is not yet in container + warn!(target: "secretstore_net", + "{}: {} session read error '{}' when requested for session from node {}", + self.self_key_pair.public(), S::type_name(), error, sender); + if !message.is_error_message() { + let qed = "session_id only fails for cluster messages; + only session messages are passed to process_message; + qed"; + let session_id = message.into_session_id().expect(qed); + let session_nonce = message.session_nonce().expect(qed); + + connection.send_message(SC::make_error_message(session_id, session_nonce, error)); + } + return None; + }, + }; + + let session_id = session.id(); + let mut is_queued_message = false; + loop { + let message_result = session.on_message(&sender, &message); + match message_result { + Ok(_) => { + // if session is completed => stop + if session.is_finished() { + info!(target: "secretstore_net", + "{}: {} session completed", self.self_key_pair.public(), S::type_name()); + sessions.remove(&session_id); + return Some(session); + } + + // try to dequeue message + match sessions.dequeue_message(&session_id) { + Some((msg_sender, msg)) => { + is_queued_message = true; + sender = msg_sender; + message = msg; + }, + None => return Some(session), + } + }, + Err(Error::TooEarlyForRequest) => { + sessions.enqueue_message(&session_id, sender, message, is_queued_message); + return Some(session); + }, + Err(err) => { + warn!( + target: "secretstore_net", + "{}: {} session error '{}' when processing message {} from node {}", + self.self_key_pair.public(), + S::type_name(), + err, + message, + sender); + session.on_session_error(self.self_key_pair.public(), err); + sessions.remove(&session_id); + return Some(session); + }, + } + } + } + + /// Get or insert new session. + fn prepare_session, D>( + &self, + sessions: &ClusterSessionsContainer, + sender: &NodeId, + message: &Message + ) -> Result, Error> + where + Message: IntoSessionId + { + fn requires_all_connections(message: &Message) -> bool { + match *message { + Message::Generation(_) => true, + Message::ShareAdd(_) => true, + Message::ServersSetChange(_) => true, + _ => false, + } + } + + // get or create new session, if required + let session_id = message.into_session_id() + .expect("into_session_id fails for cluster messages only; + only session messages are passed to prepare_session; + qed"); + let is_initialization_message = message.is_initialization_message(); + let is_delegation_message = message.is_delegation_message(); + match is_initialization_message || is_delegation_message { + false => sessions.get(&session_id, true).ok_or(Error::NoActiveSessionWithId), + true => { + let creation_data = SC::creation_data_from_message(&message)?; + let master = if is_initialization_message { + *sender + } else { + *self.self_key_pair.public() + }; + let cluster = create_cluster_view( + self.self_key_pair.clone(), + self.connections.clone(), + requires_all_connections(&message))?; + + let nonce = Some(message.session_nonce().ok_or(Error::InvalidMessage)?); + let exclusive = message.is_exclusive_session_message(); + sessions.insert(cluster, master, session_id, nonce, exclusive, creation_data) + }, + } + } + + /// Process single cluster message from the connection. + fn process_cluster_message(&self, connection: Arc, message: ClusterMessage) { + match message { + ClusterMessage::KeepAlive(_) => { + let msg = Message::Cluster(ClusterMessage::KeepAliveResponse(message::KeepAliveResponse { + session_id: None, + })); + connection.send_message(msg) + }, + ClusterMessage::KeepAliveResponse(msg) => if let Some(session_id) = msg.session_id { + self.sessions.on_session_keep_alive(connection.node_id(), session_id.into()); + }, + _ => warn!(target: "secretstore_net", "{}: received unexpected message {} from node {} at {}", + self.self_key_pair.public(), message, connection.node_id(), connection.node_address()), + } + } +} + +impl MessageProcessor for SessionsMessageProcessor { + fn process_disconnect(&self, node: &NodeId) { + self.sessions.on_connection_timeout(node); + } + + fn process_connection_message(&self, connection: Arc, message: Message) { + trace!(target: "secretstore_net", "{}: received message {} from {}", + self.self_key_pair.public(), message, connection.node_id()); + + // error is ignored as we only process errors on session level + match message { + Message::Generation(message) => self + .process_message(&self.sessions.generation_sessions, connection, Message::Generation(message)) + .map(|_| ()).unwrap_or_default(), + Message::Encryption(message) => self + .process_message(&self.sessions.encryption_sessions, connection, Message::Encryption(message)) + .map(|_| ()).unwrap_or_default(), + Message::Decryption(message) => self + .process_message(&self.sessions.decryption_sessions, connection, Message::Decryption(message)) + .map(|_| ()).unwrap_or_default(), + Message::SchnorrSigning(message) => self + .process_message(&self.sessions.schnorr_signing_sessions, connection, Message::SchnorrSigning(message)) + .map(|_| ()).unwrap_or_default(), + Message::EcdsaSigning(message) => self + .process_message(&self.sessions.ecdsa_signing_sessions, connection, Message::EcdsaSigning(message)) + .map(|_| ()).unwrap_or_default(), + Message::ServersSetChange(message) => { + let message = Message::ServersSetChange(message); + let is_initialization_message = message.is_initialization_message(); + let session = self.process_message(&self.sessions.admin_sessions, connection, message); + if is_initialization_message { + if let Some(session) = session { + self.servers_set_change_creator_connector + .set_key_servers_set_change_session(session.clone()); + } + } + }, + Message::KeyVersionNegotiation(message) => { + let session = self.process_message( + &self.sessions.negotiation_sessions, connection, Message::KeyVersionNegotiation(message)); + self.try_continue_session(session); + }, + Message::ShareAdd(message) => self.process_message( + &self.sessions.admin_sessions, connection, Message::ShareAdd(message)) + .map(|_| ()).unwrap_or_default(), + Message::Cluster(message) => self.process_cluster_message(connection, message), + } + } + + fn try_continue_session( + &self, + session: Option>> + ) { + if let Some(session) = session { + let meta = session.meta(); + let is_master_node = meta.self_node_id == meta.master_node_id; + if is_master_node && session.is_finished() { + self.sessions.negotiation_sessions.remove(&session.id()); + match session.wait() { + Ok(Some((version, master))) => match session.take_continue_action() { + Some(ContinueAction::Decrypt( + session, origin, is_shadow_decryption, is_broadcast_decryption + )) => { + let initialization_error = if self.self_key_pair.public() == &master { + session.initialize( + origin, version, is_shadow_decryption, is_broadcast_decryption) + } else { + session.delegate( + master, origin, version, is_shadow_decryption, is_broadcast_decryption) + }; + + if let Err(error) = initialization_error { + session.on_session_error(&meta.self_node_id, error); + self.sessions.decryption_sessions.remove(&session.id()); + } + }, + Some(ContinueAction::SchnorrSign(session, message_hash)) => { + let initialization_error = if self.self_key_pair.public() == &master { + session.initialize(version, message_hash) + } else { + session.delegate(master, version, message_hash) + }; + + if let Err(error) = initialization_error { + session.on_session_error(&meta.self_node_id, error); + self.sessions.schnorr_signing_sessions.remove(&session.id()); + } + }, + Some(ContinueAction::EcdsaSign(session, message_hash)) => { + let initialization_error = if self.self_key_pair.public() == &master { + session.initialize(version, message_hash) + } else { + session.delegate(master, version, message_hash) + }; + + if let Err(error) = initialization_error { + session.on_session_error(&meta.self_node_id, error); + self.sessions.ecdsa_signing_sessions.remove(&session.id()); + } + }, + None => (), + }, + Ok(None) => unreachable!("is_master_node; session is finished; + negotiation version always finished with result on master; + qed"), + Err(error) => match session.take_continue_action() { + Some(ContinueAction::Decrypt(session, _, _, _)) => { + session.on_session_error(&meta.self_node_id, error); + self.sessions.decryption_sessions.remove(&session.id()); + }, + Some(ContinueAction::SchnorrSign(session, _)) => { + session.on_session_error(&meta.self_node_id, error); + self.sessions.schnorr_signing_sessions.remove(&session.id()); + }, + Some(ContinueAction::EcdsaSign(session, _)) => { + session.on_session_error(&meta.self_node_id, error); + self.sessions.ecdsa_signing_sessions.remove(&session.id()); + }, + None => (), + }, + } + } + } + } + + fn maintain_sessions(&self) { + self.sessions.stop_stalled_sessions(); + self.sessions.sessions_keep_alive(); + } + + fn start_servers_set_change_session(&self, params: ServersSetChangeParams) -> Result, Error> { + new_servers_set_change_session( + self.self_key_pair.clone(), + &*self.sessions, + self.connections.clone(), + self.servers_set_change_creator_connector.clone(), + params, + ) + } +} diff --git a/secret-store/src/key_server_cluster/cluster_sessions.rs b/secret-store/src/key_server_cluster/cluster_sessions.rs index cce4b18c3b..53eec13346 100644 --- a/secret-store/src/key_server_cluster/cluster_sessions.rs +++ b/secret-store/src/key_server_cluster/cluster_sessions.rs @@ -21,8 +21,9 @@ use std::collections::{VecDeque, BTreeMap, BTreeSet}; use parking_lot::{Mutex, RwLock, Condvar}; use ethereum_types::H256; use ethkey::Secret; -use key_server_cluster::{Error, NodeId, SessionId, Requester}; -use key_server_cluster::cluster::{Cluster, ClusterData, ClusterConfiguration, ClusterView}; +use key_server_cluster::{Error, NodeId, SessionId, Requester, NodeKeyPair}; +use key_server_cluster::cluster::{Cluster, ClusterConfiguration, ClusterView}; +use key_server_cluster::cluster_connections::ConnectionProvider; use key_server_cluster::connection_trigger::ServersSetChangeSessionCreatorConnector; use key_server_cluster::message::{self, Message}; use key_server_cluster::generation_session::{SessionImpl as GenerationSessionImpl}; @@ -158,6 +159,8 @@ pub struct ClusterSessionsContainer>>>, /// Sessions container state. container_state: Arc>, + /// Do not actually remove sessions. + preserve_sessions: bool, /// Phantom data. _pd: ::std::marker::PhantomData, } @@ -229,6 +232,17 @@ impl ClusterSessions { self.generation_sessions.creator.make_faulty_generation_sessions(); } + #[cfg(test)] + pub fn preserve_sessions(&mut self) { + self.generation_sessions.preserve_sessions = true; + self.encryption_sessions.preserve_sessions = true; + self.decryption_sessions.preserve_sessions = true; + self.schnorr_signing_sessions.preserve_sessions = true; + self.ecdsa_signing_sessions.preserve_sessions = true; + self.negotiation_sessions.preserve_sessions = true; + self.admin_sessions.preserve_sessions = true; + } + /// Send session-level keep-alive messages. pub fn sessions_keep_alive(&self) { self.admin_sessions.send_keep_alive(&*SERVERS_SET_CHANGE_SESSION_ID, &self.self_node_id); @@ -272,6 +286,7 @@ impl ClusterSessionsContainer where S: ClusterSession, SC: C sessions: RwLock::new(BTreeMap::new()), listeners: Mutex::new(Vec::new()), container_state: container_state, + preserve_sessions: false, _pd: Default::default(), } } @@ -379,9 +394,11 @@ impl ClusterSessionsContainer where S: ClusterSession, SC: C } fn do_remove(&self, session_id: &S::Id, sessions: &mut BTreeMap>) { - if let Some(session) = sessions.remove(session_id) { - self.container_state.lock().on_session_completed(); - self.notify_listeners(|l| l.on_session_removed(session.session.clone())); + if !self.preserve_sessions { + if let Some(session) = sessions.remove(session_id) { + self.container_state.lock().on_session_completed(); + self.notify_listeners(|l| l.on_session_removed(session.session.clone())); + } } } @@ -551,19 +568,22 @@ impl ClusterSession for AdminSession { } } } -pub fn create_cluster_view(data: &Arc, requires_all_connections: bool) -> Result, Error> { - let disconnected_nodes_count = data.connections.disconnected_nodes().len(); + +pub fn create_cluster_view(self_key_pair: Arc, connections: Arc, requires_all_connections: bool) -> Result, Error> { + let mut connected_nodes = connections.connected_nodes()?; + let disconnected_nodes = connections.disconnected_nodes(); + + let disconnected_nodes_count = disconnected_nodes.len(); if requires_all_connections { if disconnected_nodes_count != 0 { return Err(Error::NodeDisconnected); } } - let mut connected_nodes = data.connections.connected_nodes()?; - connected_nodes.insert(data.self_key_pair.public().clone()); + connected_nodes.insert(self_key_pair.public().clone()); let connected_nodes_count = connected_nodes.len(); - Ok(Arc::new(ClusterView::new(data.clone(), connected_nodes, connected_nodes_count + disconnected_nodes_count))) + Ok(Arc::new(ClusterView::new(self_key_pair, connections, connected_nodes, connected_nodes_count + disconnected_nodes_count))) } #[cfg(test)] @@ -583,13 +603,11 @@ mod tests { let key_pair = Random.generate().unwrap(); let config = ClusterConfiguration { self_key_pair: Arc::new(PlainNodeKeyPair::new(key_pair.clone())), - listen_address: ("127.0.0.1".to_owned(), 100_u16), key_server_set: Arc::new(MapKeyServerSet::new(false, vec![(key_pair.public().clone(), format!("127.0.0.1:{}", 100).parse().unwrap())].into_iter().collect())), - allow_connecting_to_higher_nodes: false, key_storage: Arc::new(DummyKeyStorage::default()), acl_storage: Arc::new(DummyAclStorage::default()), admin_public: Some(Random.generate().unwrap().public().clone()), - auto_migrate_enabled: false, + preserve_sessions: false, }; ClusterSessions::new(&config, Arc::new(SimpleServersSetChangeSessionCreatorConnector { admin_public: Some(Random.generate().unwrap().public().clone()), diff --git a/secret-store/src/key_server_cluster/connection_trigger.rs b/secret-store/src/key_server_cluster/connection_trigger.rs index 3ea1a0a302..7b3649861f 100644 --- a/secret-store/src/key_server_cluster/connection_trigger.rs +++ b/secret-store/src/key_server_cluster/connection_trigger.rs @@ -21,10 +21,12 @@ use std::sync::Arc; use ethereum_types::H256; use ethkey::Public; use key_server_cluster::{KeyServerSet, KeyServerSetSnapshot}; -use key_server_cluster::cluster::{ClusterClient, ClusterConnectionsData}; +use key_server_cluster::cluster::{ClusterConfiguration, ServersSetChangeParams}; use key_server_cluster::cluster_sessions::AdminSession; +use key_server_cluster::cluster_connections::{Connection}; +use key_server_cluster::cluster_connections_net::{NetConnectionsContainer}; use types::{Error, NodeId}; -use {NodeKeyPair}; +use NodeKeyPair; #[derive(Debug, Clone, Copy, PartialEq)] /// Describes which maintain() call is required. @@ -45,10 +47,10 @@ pub trait ConnectionTrigger: Send + Sync { fn on_connection_established(&mut self, node: &NodeId) -> Option; /// When connection is closed. fn on_connection_closed(&mut self, node: &NodeId) -> Option; - /// Maintain active sessions. - fn maintain_session(&mut self, sessions: &ClusterClient); + /// Maintain active sessions. Returns Some if servers set session creation required. + fn maintain_session(&mut self) -> Option; /// Maintain active connections. - fn maintain_connections(&mut self, connections: &mut ClusterConnectionsData); + fn maintain_connections(&mut self, connections: &mut NetConnectionsContainer); /// Return connector for the servers set change session creator. fn servers_set_change_creator_connector(&self) -> Arc; } @@ -95,6 +97,11 @@ pub struct TriggerConnections { } impl SimpleConnectionTrigger { + /// Create new simple from cluster configuration. + pub fn with_config(config: &ClusterConfiguration) -> Self { + Self::new(config.key_server_set.clone(), config.self_key_pair.clone(), config.admin_public) + } + /// Create new simple connection trigger. pub fn new(key_server_set: Arc, self_key_pair: Arc, admin_public: Option) -> Self { SimpleConnectionTrigger { @@ -124,10 +131,11 @@ impl ConnectionTrigger for SimpleConnectionTrigger { None } - fn maintain_session(&mut self, _sessions: &ClusterClient) { + fn maintain_session(&mut self) -> Option { + None } - fn maintain_connections(&mut self, connections: &mut ClusterConnectionsData) { + fn maintain_connections(&mut self, connections: &mut NetConnectionsContainer) { self.connections.maintain(ConnectionsAction::ConnectToCurrentSet, connections, &self.key_server_set.snapshot()) } @@ -146,7 +154,7 @@ impl ServersSetChangeSessionCreatorConnector for SimpleServersSetChangeSessionCr } impl TriggerConnections { - pub fn maintain(&self, action: ConnectionsAction, data: &mut ClusterConnectionsData, server_set: &KeyServerSetSnapshot) { + pub fn maintain(&self, action: ConnectionsAction, data: &mut NetConnectionsContainer, server_set: &KeyServerSetSnapshot) { match action { ConnectionsAction::ConnectToCurrentSet => { adjust_connections(self.self_key_pair.public(), data, &server_set.current_set); @@ -159,7 +167,11 @@ impl TriggerConnections { } } -fn adjust_connections(self_node_id: &NodeId, data: &mut ClusterConnectionsData, required_set: &BTreeMap) { +fn adjust_connections( + self_node_id: &NodeId, + data: &mut NetConnectionsContainer, + required_set: &BTreeMap +) { if !required_set.contains_key(self_node_id) { if !data.is_isolated { trace!(target: "secretstore_net", "{}: isolated from cluser", self_node_id); @@ -204,13 +216,13 @@ mod tests { use std::collections::BTreeSet; use std::sync::Arc; use ethkey::{Random, Generator}; - use key_server_cluster::cluster::ClusterConnectionsData; use key_server_cluster::{MapKeyServerSet, PlainNodeKeyPair, KeyServerSetSnapshot, KeyServerSetMigration}; + use key_server_cluster::cluster_connections_net::NetConnectionsContainer; use super::{Maintain, TriggerConnections, ConnectionsAction, ConnectionTrigger, SimpleConnectionTrigger, select_nodes_to_disconnect, adjust_connections}; - fn default_connection_data() -> ClusterConnectionsData { - ClusterConnectionsData { + fn default_connection_data() -> NetConnectionsContainer { + NetConnectionsContainer { is_isolated: false, nodes: Default::default(), connections: Default::default(), diff --git a/secret-store/src/key_server_cluster/connection_trigger_with_migration.rs b/secret-store/src/key_server_cluster/connection_trigger_with_migration.rs index 9607949c5a..559bab18c1 100644 --- a/secret-store/src/key_server_cluster/connection_trigger_with_migration.rs +++ b/secret-store/src/key_server_cluster/connection_trigger_with_migration.rs @@ -21,7 +21,8 @@ use ethereum_types::H256; use ethkey::Public; use parking_lot::Mutex; use key_server_cluster::{KeyServerSet, KeyServerSetSnapshot, KeyServerSetMigration, is_migration_required}; -use key_server_cluster::cluster::{ClusterClient, ClusterConnectionsData}; +use key_server_cluster::cluster::{ClusterConfiguration, ServersSetChangeParams}; +use key_server_cluster::cluster_connections_net::NetConnectionsContainer; use key_server_cluster::cluster_sessions::{AdminSession, ClusterSession}; use key_server_cluster::jobs::servers_set_change_access_job::ordered_nodes_hash; use key_server_cluster::connection_trigger::{Maintain, ConnectionsAction, ConnectionTrigger, @@ -110,6 +111,11 @@ struct TriggerSession { } impl ConnectionTriggerWithMigration { + /// Create new simple from cluster configuration. + pub fn with_config(config: &ClusterConfiguration) -> Self { + Self::new(config.key_server_set.clone(), config.self_key_pair.clone()) + } + /// Create new trigge with migration. pub fn new(key_server_set: Arc, self_key_pair: Arc) -> Self { let snapshot = key_server_set.snapshot(); @@ -187,13 +193,11 @@ impl ConnectionTrigger for ConnectionTriggerWithMigration { self.do_maintain() } - fn maintain_session(&mut self, sessions: &ClusterClient) { - if let Some(action) = self.session_action { - self.session.maintain(action, sessions, &self.snapshot); - } + fn maintain_session(&mut self) -> Option { + self.session_action.and_then(|action| self.session.maintain(action, &self.snapshot)) } - fn maintain_connections(&mut self, connections: &mut ClusterConnectionsData) { + fn maintain_connections(&mut self, connections: &mut NetConnectionsContainer) { if let Some(action) = self.connections_action { self.connections.maintain(action, connections, &self.snapshot); } @@ -255,30 +259,42 @@ impl TriggerSession { } /// Maintain session. - pub fn maintain(&mut self, action: SessionAction, sessions: &ClusterClient, server_set: &KeyServerSetSnapshot) { - if action == SessionAction::Start { // all other actions are processed in maintain - let migration = server_set.migration.as_ref() - .expect("action is Start only when migration is started (see maintain_session); qed"); - - // we assume that authorities that are removed from the servers set are either offline, or malicious - // => they're not involved in ServersSetChangeSession - // => both sets are the same - let old_set: BTreeSet<_> = migration.set.keys().cloned().collect(); - let new_set = old_set.clone(); - - let signatures = self.self_key_pair.sign(&ordered_nodes_hash(&old_set)) - .and_then(|old_set_signature| self.self_key_pair.sign(&ordered_nodes_hash(&new_set)) - .map(|new_set_signature| (old_set_signature, new_set_signature))) - .map_err(Into::into); - let session = signatures.and_then(|(old_set_signature, new_set_signature)| - sessions.new_servers_set_change_session(None, Some(migration.id.clone()), new_set, old_set_signature, new_set_signature)); - - match session { - Ok(_) => trace!(target: "secretstore_net", "{}: started auto-migrate session", - self.self_key_pair.public()), - Err(err) => trace!(target: "secretstore_net", "{}: failed to start auto-migrate session with: {}", - self.self_key_pair.public(), err), - } + pub fn maintain( + &mut self, + action: SessionAction, + server_set: &KeyServerSetSnapshot + ) -> Option { + if action != SessionAction::Start { // all other actions are processed in maintain + return None; + } + let migration = server_set.migration.as_ref() + .expect("action is Start only when migration is started (see maintain_session); qed"); + + // we assume that authorities that are removed from the servers set are either offline, or malicious + // => they're not involved in ServersSetChangeSession + // => both sets are the same + let old_set: BTreeSet<_> = migration.set.keys().cloned().collect(); + let new_set = old_set.clone(); + + let signatures = self.self_key_pair.sign(&ordered_nodes_hash(&old_set)) + .and_then(|old_set_signature| self.self_key_pair.sign(&ordered_nodes_hash(&new_set)) + .map(|new_set_signature| (old_set_signature, new_set_signature))); + + match signatures { + Ok((old_set_signature, new_set_signature)) => Some(ServersSetChangeParams { + session_id: None, + migration_id: Some(migration.id), + new_nodes_set: new_set, + old_set_signature, + new_set_signature, + }), + Err(err) => { + trace!( + target: "secretstore_net", + "{}: failed to sign servers set for auto-migrate session with: {}", + self.self_key_pair.public(), err); + None + }, } } } diff --git a/secret-store/src/key_server_cluster/mod.rs b/secret-store/src/key_server_cluster/mod.rs index 3db29ba7ed..fc46e10318 100644 --- a/secret-store/src/key_server_cluster/mod.rs +++ b/secret-store/src/key_server_cluster/mod.rs @@ -23,7 +23,8 @@ pub use super::key_storage::{KeyStorage, DocumentKeyShare, DocumentKeyShareVersi pub use super::key_server_set::{is_migration_required, KeyServerSet, KeyServerSetSnapshot, KeyServerSetMigration}; pub use super::serialization::{SerializableSignature, SerializableH256, SerializableSecret, SerializablePublic, SerializableRequester, SerializableMessageHash, SerializableAddress}; -pub use self::cluster::{ClusterCore, ClusterConfiguration, ClusterClient}; +pub use self::cluster::{new_network_cluster, ClusterCore, ClusterConfiguration, ClusterClient}; +pub use self::cluster_connections_net::NetConnectionsManagerConfig; pub use self::cluster_sessions::{ClusterSession, ClusterSessionsListener}; #[cfg(test)] pub use self::cluster::tests::DummyClusterClient; @@ -70,6 +71,9 @@ pub use self::client_sessions::signing_session_ecdsa; pub use self::client_sessions::signing_session_schnorr; mod cluster; +mod cluster_connections; +mod cluster_connections_net; +mod cluster_message_processor; mod cluster_sessions; mod cluster_sessions_creator; mod connection_trigger; diff --git a/secret-store/src/lib.rs b/secret-store/src/lib.rs index 915cec5288..a3c82991b1 100644 --- a/secret-store/src/lib.rs +++ b/secret-store/src/lib.rs @@ -56,6 +56,9 @@ extern crate env_logger; #[cfg(test)] extern crate kvdb_rocksdb; +#[cfg(feature = "accounts")] +extern crate ethcore_accounts as accounts; + mod key_server_cluster; mod types; mod helpers; @@ -80,7 +83,9 @@ use parity_runtime::Executor; pub use types::{ServerKeyId, EncryptedDocumentKey, RequestSignature, Public, Error, NodeAddress, ContractAddress, ServiceConfiguration, ClusterConfiguration}; pub use traits::{NodeKeyPair, KeyServer}; -pub use self::node_key_pair::{PlainNodeKeyPair, KeyStoreNodeKeyPair}; +pub use self::node_key_pair::PlainNodeKeyPair; +#[cfg(feature = "accounts")] +pub use self::node_key_pair::KeyStoreNodeKeyPair; /// Start new key server instance pub fn start(client: Arc, sync: Arc, miner: Arc, self_key_pair: Arc, mut config: ServiceConfiguration, diff --git a/secret-store/src/listener/http_listener.rs b/secret-store/src/listener/http_listener.rs index cbe6c42d3a..aa67ec5c66 100644 --- a/secret-store/src/listener/http_listener.rs +++ b/secret-store/src/listener/http_listener.rs @@ -334,7 +334,7 @@ fn parse_request(method: &HttpMethod, uri_path: &str, body: &[u8]) -> Request { Err(_) => return Request::Invalid, }; - let path: Vec = uri_path.trim_left_matches('/').split('/').map(Into::into).collect(); + let path: Vec = uri_path.trim_start_matches('/').split('/').map(Into::into).collect(); if path.len() == 0 { return Request::Invalid; } diff --git a/secret-store/src/node_key_pair.rs b/secret-store/src/node_key_pair.rs index 6293858891..f50f75ad1b 100644 --- a/secret-store/src/node_key_pair.rs +++ b/secret-store/src/node_key_pair.rs @@ -14,31 +14,26 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use std::sync::Arc; use ethkey::crypto::ecdh::agree; use ethkey::{KeyPair, Public, Signature, Error as EthKeyError, sign, public_to_address}; -use ethcore::account_provider::AccountProvider; use ethereum_types::{H256, Address}; use traits::NodeKeyPair; -use ethkey::Password; pub struct PlainNodeKeyPair { key_pair: KeyPair, } -pub struct KeyStoreNodeKeyPair { - account_provider: Arc, - address: Address, - public: Public, - password: Password, -} - impl PlainNodeKeyPair { pub fn new(key_pair: KeyPair) -> Self { PlainNodeKeyPair { key_pair: key_pair, } } + + #[cfg(test)] + pub fn key_pair(&self) -> &KeyPair { + &self.key_pair + } } impl NodeKeyPair for PlainNodeKeyPair { @@ -61,34 +56,52 @@ impl NodeKeyPair for PlainNodeKeyPair { } } -impl KeyStoreNodeKeyPair { - pub fn new(account_provider: Arc, address: Address, password: Password) -> Result { - let public = account_provider.account_public(address.clone(), &password).map_err(|e| EthKeyError::Custom(format!("{}", e)))?; - Ok(KeyStoreNodeKeyPair { - account_provider: account_provider, - address: address, - public: public, - password: password, - }) +#[cfg(feature = "accounts")] +mod accounts { + use super::*; + use std::sync::Arc; + use ethkey::Password; + use accounts::AccountProvider; + + pub struct KeyStoreNodeKeyPair { + account_provider: Arc, + address: Address, + public: Public, + password: Password, } -} -impl NodeKeyPair for KeyStoreNodeKeyPair { - fn public(&self) -> &Public { - &self.public + impl KeyStoreNodeKeyPair { + pub fn new(account_provider: Arc, address: Address, password: Password) -> Result { + let public = account_provider.account_public(address.clone(), &password).map_err(|e| EthKeyError::Custom(format!("{}", e)))?; + Ok(KeyStoreNodeKeyPair { + account_provider: account_provider, + address: address, + public: public, + password: password, + }) + } } - fn address(&self) -> Address { - public_to_address(&self.public) - } + impl NodeKeyPair for KeyStoreNodeKeyPair { + fn public(&self) -> &Public { + &self.public + } - fn sign(&self, data: &H256) -> Result { - self.account_provider.sign(self.address.clone(), Some(self.password.clone()), data.clone()) - .map_err(|e| EthKeyError::Custom(format!("{}", e))) - } + fn address(&self) -> Address { + public_to_address(&self.public) + } - fn compute_shared_key(&self, peer_public: &Public) -> Result { - KeyPair::from_secret(self.account_provider.agree(self.address.clone(), Some(self.password.clone()), peer_public) - .map_err(|e| EthKeyError::Custom(format!("{}", e)))?) + fn sign(&self, data: &H256) -> Result { + self.account_provider.sign(self.address.clone(), Some(self.password.clone()), data.clone()) + .map_err(|e| EthKeyError::Custom(format!("{}", e))) + } + + fn compute_shared_key(&self, peer_public: &Public) -> Result { + KeyPair::from_secret(self.account_provider.agree(self.address.clone(), Some(self.password.clone()), peer_public) + .map_err(|e| EthKeyError::Custom(format!("{}", e)))?) + } } } + +#[cfg(feature = "accounts")] +pub use self::accounts::KeyStoreNodeKeyPair; diff --git a/secret_store/src/key_server_cluster/cluster_connections.rs b/secret_store/src/key_server_cluster/cluster_connections.rs new file mode 100644 index 0000000000..b484e6d8e0 --- /dev/null +++ b/secret_store/src/key_server_cluster/cluster_connections.rs @@ -0,0 +1,176 @@ +// 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::collections::BTreeSet; +use std::sync::Arc; +use key_server_cluster::{Error, NodeId}; +use key_server_cluster::message::Message; + +/// Connection to the single node. Provides basic information about connected node and +/// allows sending messages to this node. +pub trait Connection: Send + Sync { + /// Is this inbound connection? This only matters when both nodes are simultaneously establishing + /// two connections to each other. The agreement is that the inbound connection from the node with + /// lower NodeId is used and the other connection is closed. + fn is_inbound(&self) -> bool; + /// Returns id of the connected node. + fn node_id(&self) -> &NodeId; + /// Returns 'address' of the node to use in traces. + fn node_address(&self) -> String; + /// Send message to the connected node. + fn send_message(&self, message: Message); +} + +/// Connections manager. Responsible for keeping us connected to all required nodes. +pub trait ConnectionManager: 'static + Send + Sync { + /// Returns shared reference to connections provider. + fn provider(&self) -> Arc; + /// Try to reach all disconnected nodes immediately. This method is exposed mostly for + /// tests, where all 'nodes' are starting listening for incoming connections first and + /// only after this, they're actually start connecting to each other. + fn connect(&self); +} + +/// Connections provider. Holds all active connections and the set of nodes that we need to +/// connect to. At any moment connection could be lost and the set of connected/disconnected +/// nodes could change (at behalf of the connection manager). +/// Clone operation should be cheap (Arc). +pub trait ConnectionProvider: Send + Sync { + /// Returns the set of currently connected nodes. Error is returned when our node is + /// not a part of the cluster ('isolated' node). + fn connected_nodes(&self) -> Result, Error>; + /// Returns the set of currently disconnected nodes. + fn disconnected_nodes(&self) -> BTreeSet; + /// Returns the reference to the active node connection or None if the node is not connected. + fn connection(&self, node: &NodeId) -> Option>; +} + +#[cfg(test)] +pub mod tests { + use std::collections::{BTreeSet, VecDeque}; + use std::sync::Arc; + use std::sync::atomic::{AtomicBool, Ordering}; + use parking_lot::Mutex; + use key_server_cluster::{Error, NodeId}; + use key_server_cluster::message::Message; + use super::{ConnectionManager, Connection, ConnectionProvider}; + + /// Shared messages queue. + pub type MessagesQueue = Arc>>; + + /// Single node connections. + pub struct TestConnections { + node: NodeId, + is_isolated: AtomicBool, + connected_nodes: Mutex>, + disconnected_nodes: Mutex>, + messages: MessagesQueue, + } + + /// Single connection. + pub struct TestConnection { + from: NodeId, + to: NodeId, + messages: MessagesQueue, + } + + impl TestConnections { + pub fn isolate(&self) { + let connected_nodes = ::std::mem::replace(&mut *self.connected_nodes.lock(), Default::default()); + self.is_isolated.store(true, Ordering::Relaxed); + self.disconnected_nodes.lock().extend(connected_nodes) + } + + pub fn disconnect(&self, node: NodeId) { + self.connected_nodes.lock().remove(&node); + self.disconnected_nodes.lock().insert(node); + } + + pub fn exclude(&self, node: NodeId) { + self.connected_nodes.lock().remove(&node); + self.disconnected_nodes.lock().remove(&node); + } + + pub fn include(&self, node: NodeId) { + self.connected_nodes.lock().insert(node); + } + } + + impl ConnectionManager for Arc { + fn provider(&self) -> Arc { + self.clone() + } + + fn connect(&self) {} + } + + impl ConnectionProvider for TestConnections { + fn connected_nodes(&self) -> Result, Error> { + match self.is_isolated.load(Ordering::Relaxed) { + false => Ok(self.connected_nodes.lock().clone()), + true => Err(Error::NodeDisconnected), + } + } + + fn disconnected_nodes(&self) -> BTreeSet { + self.disconnected_nodes.lock().clone() + } + + fn connection(&self, node: &NodeId) -> Option> { + match self.connected_nodes.lock().contains(node) { + true => Some(Arc::new(TestConnection { + from: self.node, + to: *node, + messages: self.messages.clone(), + })), + false => None, + } + } + } + + impl Connection for TestConnection { + fn is_inbound(&self) -> bool { + false + } + + fn node_id(&self) -> &NodeId { + &self.to + } + + fn node_address(&self) -> String { + format!("{}", self.to) + } + + fn send_message(&self, message: Message) { + self.messages.lock().push_back((self.from, self.to, message)) + } + } + + pub fn new_test_connections( + messages: MessagesQueue, + node: NodeId, + mut nodes: BTreeSet + ) -> Arc { + let is_isolated = !nodes.remove(&node); + Arc::new(TestConnections { + node, + is_isolated: AtomicBool::new(is_isolated), + connected_nodes: Mutex::new(nodes), + disconnected_nodes: Default::default(), + messages, + }) + } +} diff --git a/secret_store/src/key_server_cluster/cluster_connections_net.rs b/secret_store/src/key_server_cluster/cluster_connections_net.rs new file mode 100644 index 0000000000..bda7f7dd28 --- /dev/null +++ b/secret_store/src/key_server_cluster/cluster_connections_net.rs @@ -0,0 +1,539 @@ +// 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::collections::{BTreeMap, BTreeSet}; +use std::collections::btree_map::Entry; +use std::io; +use std::net::{SocketAddr, IpAddr}; +use std::sync::Arc; +use std::time::{Duration, Instant}; +use futures::{future, Future, Stream}; +use parking_lot::{Mutex, RwLock}; +use tokio::net::{TcpListener, TcpStream}; +use tokio::timer::{Interval, timeout::Error as TimeoutError}; +use tokio_io::IoFuture; +use ethkey::KeyPair; +use parity_runtime::Executor; +use key_server_cluster::{Error, NodeId, ClusterConfiguration, NodeKeyPair}; +use key_server_cluster::cluster_connections::{ConnectionProvider, Connection, ConnectionManager}; +use key_server_cluster::connection_trigger::{Maintain, ConnectionTrigger}; +use key_server_cluster::cluster_message_processor::MessageProcessor; +use key_server_cluster::io::{DeadlineStatus, ReadMessage, SharedTcpStream, + read_encrypted_message, WriteMessage, write_encrypted_message}; +use key_server_cluster::message::{self, ClusterMessage, Message}; +use key_server_cluster::net::{accept_connection as io_accept_connection, + connect as io_connect, Connection as IoConnection}; + +/// Empty future. +pub type BoxedEmptyFuture = Box + Send>; + +/// Maintain interval (seconds). Every MAINTAIN_INTERVAL seconds node: +/// 1) checks if connected nodes are responding to KeepAlive messages +/// 2) tries to connect to disconnected nodes +/// 3) checks if enc/dec sessions are time-outed +const MAINTAIN_INTERVAL: u64 = 10; + +/// When no messages have been received from node within KEEP_ALIVE_SEND_INTERVAL seconds, +/// we must send KeepAlive message to the node to check if it still responds to messages. +const KEEP_ALIVE_SEND_INTERVAL: Duration = Duration::from_secs(30); +/// When no messages have been received from node within KEEP_ALIVE_DISCONNECT_INTERVAL seconds, +/// we must treat this node as non-responding && disconnect from it. +const KEEP_ALIVE_DISCONNECT_INTERVAL: Duration = Duration::from_secs(60); + +/// Network connection manager configuration. +pub struct NetConnectionsManagerConfig { + /// Allow connecting to 'higher' nodes. + pub allow_connecting_to_higher_nodes: bool, + /// Interface to listen to. + pub listen_address: (String, u16), + /// True if we should autostart key servers set change session when servers set changes? + /// This will only work when servers set is configured using KeyServerSet contract. + pub auto_migrate_enabled: bool, +} + +/// Network connections manager. +pub struct NetConnectionsManager { + /// Address we're listening for incoming connections. + listen_address: SocketAddr, + /// Shared cluster connections data reference. + data: Arc, +} + +/// Network connections data. Shared among NetConnectionsManager and spawned futures. +struct NetConnectionsData { + /// Allow connecting to 'higher' nodes. + allow_connecting_to_higher_nodes: bool, + /// Reference to tokio task executor. + executor: Executor, + /// Key pair of this node. + self_key_pair: Arc, + /// Network messages processor. + message_processor: Arc, + /// Connections trigger. + trigger: Mutex>, + /// Mutable connection data. + container: Arc>, +} + +/// Network connections container. This is the only mutable data of NetConnectionsManager. +/// The set of nodes is mutated by the connection trigger and the connections set is also +/// mutated by spawned futures. +pub struct NetConnectionsContainer { + /// Is this node isolated from cluster? + pub is_isolated: bool, + /// Current key servers set. + pub nodes: BTreeMap, + /// Active connections to key servers. + pub connections: BTreeMap>, +} + +/// Network connection to single key server node. +pub struct NetConnection { + executor: Executor, + /// Id of the peer node. + node_id: NodeId, + /// Address of the peer node. + node_address: SocketAddr, + /// Is this inbound (true) or outbound (false) connection? + is_inbound: bool, + /// Key pair that is used to encrypt connection' messages. + key: KeyPair, + /// Last message time. + last_message_time: RwLock, + /// Underlying TCP stream. + stream: SharedTcpStream, +} + +impl NetConnectionsManager { + /// Create new network connections manager. + pub fn new( + executor: Executor, + message_processor: Arc, + trigger: Box, + container: Arc>, + config: &ClusterConfiguration, + net_config: NetConnectionsManagerConfig, + ) -> Result { + let listen_address = make_socket_address( + &net_config.listen_address.0, + net_config.listen_address.1)?; + + Ok(NetConnectionsManager { + listen_address, + data: Arc::new(NetConnectionsData { + allow_connecting_to_higher_nodes: net_config.allow_connecting_to_higher_nodes, + executor, + message_processor, + self_key_pair: config.self_key_pair.clone(), + trigger: Mutex::new(trigger), + container, + }), + }) + } + + /// Start listening for connections and schedule connections maintenance. + pub fn start(&self) -> Result<(), Error> { + net_listen(&self.listen_address, self.data.clone())?; + net_schedule_maintain(self.data.clone()); + Ok(()) + } +} + +impl ConnectionManager for NetConnectionsManager { + fn provider(&self) -> Arc { + self.data.container.clone() + } + + fn connect(&self) { + net_connect_disconnected(self.data.clone()); + } +} + +impl ConnectionProvider for RwLock { + fn connected_nodes(&self) -> Result, Error> { + let connections = self.read(); + if connections.is_isolated { + return Err(Error::NodeDisconnected); + } + + Ok(connections.connections.keys().cloned().collect()) + } + + fn disconnected_nodes(&self) -> BTreeSet { + let connections = self.read(); + connections.nodes.keys() + .filter(|node_id| !connections.connections.contains_key(node_id)) + .cloned() + .collect() + } + + fn connection(&self, node: &NodeId) -> Option> { + match self.read().connections.get(node).cloned() { + Some(connection) => Some(connection), + None => None, + } + } +} + +impl NetConnection { + /// Create new connection. + pub fn new(executor: Executor, is_inbound: bool, connection: IoConnection) -> NetConnection { + NetConnection { + executor, + node_id: connection.node_id, + node_address: connection.address, + is_inbound: is_inbound, + stream: connection.stream, + key: connection.key, + last_message_time: RwLock::new(Instant::now()), + } + } + + /// Get last message time. + pub fn last_message_time(&self) -> Instant { + *self.last_message_time.read() + } + + /// Update last message time + pub fn set_last_message_time(&self, last_message_time: Instant) { + *self.last_message_time.write() = last_message_time + } + + /// Returns future that sends encrypted message over this connection. + pub fn send_message_future(&self, message: Message) -> WriteMessage { + write_encrypted_message(self.stream.clone(), &self.key, message) + } + + /// Returns future that reads encrypted message from this connection. + pub fn read_message_future(&self) -> ReadMessage { + read_encrypted_message(self.stream.clone(), self.key.clone()) + } +} + +impl Connection for NetConnection { + fn is_inbound(&self) -> bool { + self.is_inbound + } + + fn node_id(&self) -> &NodeId { + &self.node_id + } + + fn node_address(&self) -> String { + format!("{}", self.node_address) + } + + fn send_message(&self, message: Message) { + execute(&self.executor, self.send_message_future(message).then(|_| Ok(()))); + } +} + +impl NetConnectionsData { + /// Executes closure for each active connection. + pub fn active_connections(&self) -> Vec> { + self.container.read().connections.values().cloned().collect() + } + + /// Executes closure for each disconnected node. + pub fn disconnected_nodes(&self) -> Vec<(NodeId, SocketAddr)> { + let container = self.container.read(); + container.nodes.iter() + .filter(|(node_id, _)| !container.connections.contains_key(node_id)) + .map(|(node_id, addr)| (*node_id, *addr)) + .collect() + } + + /// Try to insert new connection. Returns true if connection has been inserted. + /// Returns false (and ignores connections) if: + /// - we do not expect connection from this node + /// - we are already connected to the node and existing connection 'supersede' + /// new connection by agreement + pub fn insert(&self, connection: Arc) -> bool { + let node = *connection.node_id(); + let mut container = self.container.write(); + if !container.nodes.contains_key(&node) { + trace!(target: "secretstore_net", "{}: ignoring unknown connection from {} at {}", + self.self_key_pair.public(), node, connection.node_address()); + return false; + } + + if container.connections.contains_key(&node) { + // we have already connected to the same node + // the agreement is that node with lower id must establish connection to node with higher id + if (*self.self_key_pair.public() < node && connection.is_inbound()) + || (*self.self_key_pair.public() > node && !connection.is_inbound()) { + return false; + } + } + + trace!(target: "secretstore_net", + "{}: inserting connection to {} at {}. Connected to {} of {} nodes", + self.self_key_pair.public(), node, connection.node_address(), + container.connections.len() + 1, container.nodes.len()); + container.connections.insert(node, connection); + + true + } + + /// Tries to remove connection. Returns true if connection has been removed. + /// Returns false if we do not know this connection. + pub fn remove(&self, connection: &NetConnection) -> bool { + let node_id = *connection.node_id(); + let is_inbound = connection.is_inbound(); + let mut container = self.container.write(); + if let Entry::Occupied(entry) = container.connections.entry(node_id) { + if entry.get().is_inbound() != is_inbound { + return false; + } + + trace!(target: "secretstore_net", "{}: removing connection to {} at {}", + self.self_key_pair.public(), node_id, entry.get().node_address()); + entry.remove_entry(); + + true + } else { + false + } + } +} + +/// Listen incoming connections. +fn net_listen( + listen_address: &SocketAddr, + data: Arc, +) -> Result<(), Error> { + execute(&data.executor, net_listen_future(listen_address, data.clone())?); + Ok(()) +} + +/// Listen incoming connections future. +fn net_listen_future( + listen_address: &SocketAddr, + data: Arc, +) -> Result { + Ok(Box::new(TcpListener::bind(listen_address)? + .incoming() + .and_then(move |stream| { + net_accept_connection(data.clone(), stream); + Ok(()) + }) + .for_each(|_| Ok(())) + .then(|_| future::ok(())))) +} + +/// Accept incoming connection. +fn net_accept_connection( + data: Arc, + stream: TcpStream, +) { + execute(&data.executor, net_accept_connection_future(data.clone(), stream)); +} + +/// Accept incoming connection future. +fn net_accept_connection_future(data: Arc, stream: TcpStream) -> BoxedEmptyFuture { + Box::new(io_accept_connection(stream, data.self_key_pair.clone()) + .then(move |result| net_process_connection_result(data, None, result)) + .then(|_| future::ok(()))) +} + +/// Connect to remote node. +fn net_connect( + data: Arc, + remote: SocketAddr, +) { + execute(&data.executor, net_connect_future(data.clone(), remote)); +} + +/// Connect to remote node future. +fn net_connect_future( + data: Arc, + remote: SocketAddr, +) -> BoxedEmptyFuture { + let disconnected_nodes = data.container.disconnected_nodes(); + Box::new(io_connect(&remote, data.self_key_pair.clone(), disconnected_nodes) + .then(move |result| net_process_connection_result(data, Some(remote), result)) + .then(|_| future::ok(()))) +} + +/// Process network connection result. +fn net_process_connection_result( + data: Arc, + outbound_addr: Option, + result: Result>, TimeoutError>, +) -> IoFuture> { + match result { + Ok(DeadlineStatus::Meet(Ok(connection))) => { + let connection = Arc::new(NetConnection::new(data.executor.clone(), outbound_addr.is_none(), connection)); + if data.insert(connection.clone()) { + let maintain_action = data.trigger.lock().on_connection_established(connection.node_id()); + maintain_connection_trigger(data.clone(), maintain_action); + + return net_process_connection_messages(data, connection); + } + }, + Ok(DeadlineStatus::Meet(Err(err))) => { + warn!(target: "secretstore_net", "{}: protocol error '{}' when establishing {} connection{}", + data.self_key_pair.public(), err, if outbound_addr.is_some() { "outbound" } else { "inbound" }, + outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); + }, + Ok(DeadlineStatus::Timeout) => { + warn!(target: "secretstore_net", "{}: timeout when establishing {} connection{}", + data.self_key_pair.public(), if outbound_addr.is_some() { "outbound" } else { "inbound" }, + outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); + }, + Err(err) => { + warn!(target: "secretstore_net", "{}: network error '{}' when establishing {} connection{}", + data.self_key_pair.public(), err, if outbound_addr.is_some() { "outbound" } else { "inbound" }, + outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); + }, + } + + Box::new(future::ok(Ok(()))) +} + +/// Process connection messages. +fn net_process_connection_messages( + data: Arc, + connection: Arc, +) -> IoFuture> { + Box::new(connection + .read_message_future() + .then(move |result| + match result { + Ok((_, Ok(message))) => { + connection.set_last_message_time(Instant::now()); + data.message_processor.process_connection_message(connection.clone(), message); + // continue serving connection + let process_messages_future = net_process_connection_messages( + data.clone(), connection).then(|_| Ok(())); + execute(&data.executor, process_messages_future); + Box::new(future::ok(Ok(()))) + }, + Ok((_, Err(err))) => { + warn!(target: "secretstore_net", "{}: protocol error '{}' when reading message from node {}", + data.self_key_pair.public(), err, connection.node_id()); + // continue serving connection + let process_messages_future = net_process_connection_messages( + data.clone(), connection).then(|_| Ok(())); + execute(&data.executor, process_messages_future); + Box::new(future::ok(Err(err))) + }, + Err(err) => { + let node_id = *connection.node_id(); + warn!(target: "secretstore_net", "{}: network error '{}' when reading message from node {}", + data.self_key_pair.public(), err, node_id); + // close connection + if data.remove(&*connection) { + let maintain_action = data.trigger.lock().on_connection_closed(&node_id); + maintain_connection_trigger(data, maintain_action); + } + Box::new(future::err(err)) + }, + } + )) +} + +/// Schedule connections. maintain. +fn net_schedule_maintain(data: Arc) { + let closure_data = data.clone(); + execute(&data.executor, Interval::new_interval(Duration::new(MAINTAIN_INTERVAL, 0)) + .and_then(move |_| Ok(net_maintain(closure_data.clone()))) + .for_each(|_| Ok(())) + .then(|_| future::ok(()))); +} + +/// Maintain network connections. +fn net_maintain(data: Arc) { + trace!(target: "secretstore_net", "{}: executing maintain procedures", data.self_key_pair.public()); + + update_nodes_set(data.clone()); + data.message_processor.maintain_sessions(); + net_keep_alive(data.clone()); + net_connect_disconnected(data); +} + +/// Send keep alive messages to remote nodes. +fn net_keep_alive(data: Arc) { + let now = Instant::now(); + let active_connections = data.active_connections(); + for connection in active_connections { + let last_message_diff = now - connection.last_message_time(); + if last_message_diff > KEEP_ALIVE_DISCONNECT_INTERVAL { + warn!(target: "secretstore_net", "{}: keep alive timeout for node {}", + data.self_key_pair.public(), connection.node_id()); + + let node_id = *connection.node_id(); + if data.remove(&*connection) { + let maintain_action = data.trigger.lock().on_connection_closed(&node_id); + maintain_connection_trigger(data.clone(), maintain_action); + } + data.message_processor.process_disconnect(&node_id); + } + else if last_message_diff > KEEP_ALIVE_SEND_INTERVAL { + connection.send_message(Message::Cluster(ClusterMessage::KeepAlive(message::KeepAlive {}))); + } + } +} + +/// Connect disconnected nodes. +fn net_connect_disconnected(data: Arc) { + let disconnected_nodes = data.disconnected_nodes(); + for (node_id, address) in disconnected_nodes { + if data.allow_connecting_to_higher_nodes || *data.self_key_pair.public() < node_id { + net_connect(data.clone(), address); + } + } +} + +/// Schedule future execution. +fn execute + Send + 'static>(executor: &Executor, f: F) { + if let Err(err) = future::Executor::execute(executor, Box::new(f)) { + error!("Secret store runtime unable to spawn task. Runtime is shutting down. ({:?})", err); + } +} + +/// Try to update active nodes set from connection trigger. +fn update_nodes_set(data: Arc) { + let maintain_action = data.trigger.lock().on_maintain(); + maintain_connection_trigger(data, maintain_action); +} + +/// Execute maintain procedures of connections trigger. +fn maintain_connection_trigger(data: Arc, maintain_action: Option) { + if maintain_action == Some(Maintain::SessionAndConnections) || maintain_action == Some(Maintain::Session) { + let session_params = data.trigger.lock().maintain_session(); + if let Some(session_params) = session_params { + let session = data.message_processor.start_servers_set_change_session(session_params); + match session { + Ok(_) => trace!(target: "secretstore_net", "{}: started auto-migrate session", + data.self_key_pair.public()), + Err(err) => trace!(target: "secretstore_net", "{}: failed to start auto-migrate session with: {}", + data.self_key_pair.public(), err), + } + } + } + if maintain_action == Some(Maintain::SessionAndConnections) || maintain_action == Some(Maintain::Connections) { + let mut trigger = data.trigger.lock(); + let mut data = data.container.write(); + trigger.maintain_connections(&mut *data); + } +} + +/// Compose SocketAddr from configuration' address and port. +fn make_socket_address(address: &str, port: u16) -> Result { + let ip_address: IpAddr = address.parse().map_err(|_| Error::InvalidNodeAddress)?; + Ok(SocketAddr::new(ip_address, port)) +} diff --git a/secret_store/src/key_server_cluster/cluster_message_processor.rs b/secret_store/src/key_server_cluster/cluster_message_processor.rs new file mode 100644 index 0000000000..b4ba5ef03b --- /dev/null +++ b/secret_store/src/key_server_cluster/cluster_message_processor.rs @@ -0,0 +1,357 @@ +// 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::sync::Arc; +use key_server_cluster::{Error, NodeId, NodeKeyPair}; +use key_server_cluster::cluster::{ServersSetChangeParams, new_servers_set_change_session}; +use key_server_cluster::cluster_sessions::{AdminSession}; +use key_server_cluster::cluster_connections::{ConnectionProvider, Connection}; +use key_server_cluster::cluster_sessions::{ClusterSession, ClusterSessions, ClusterSessionsContainer, + create_cluster_view}; +use key_server_cluster::cluster_sessions_creator::{ClusterSessionCreator, IntoSessionId}; +use key_server_cluster::message::{self, Message, ClusterMessage}; +use key_server_cluster::key_version_negotiation_session::{SessionImpl as KeyVersionNegotiationSession, + IsolatedSessionTransport as KeyVersionNegotiationSessionTransport, ContinueAction}; +use key_server_cluster::connection_trigger::ServersSetChangeSessionCreatorConnector; + +/// Something that is able to process signals/messages from other nodes. +pub trait MessageProcessor: Send + Sync { + /// Process disconnect from the remote node. + fn process_disconnect(&self, node: &NodeId); + /// Process single message from the connection. + fn process_connection_message(&self, connection: Arc, message: Message); + + /// Start servers set change session. This is typically used by ConnectionManager when + /// it detects that auto-migration session needs to be started. + fn start_servers_set_change_session(&self, params: ServersSetChangeParams) -> Result, Error>; + /// Try to continue session after key version negotiation session is completed. + fn try_continue_session( + &self, + session: Option>> + ); + /// Maintain active sessions. Typically called by the ConnectionManager at some intervals. + /// Should cancel stalled sessions and send keep-alive messages for sessions that support it. + fn maintain_sessions(&self); +} + +/// Bridge between ConnectionManager and ClusterSessions. +pub struct SessionsMessageProcessor { + self_key_pair: Arc, + servers_set_change_creator_connector: Arc, + sessions: Arc, + connections: Arc, +} + +impl SessionsMessageProcessor { + /// Create new instance of SessionsMessageProcessor. + pub fn new( + self_key_pair: Arc, + servers_set_change_creator_connector: Arc, + sessions: Arc, + connections: Arc, + ) -> Self { + SessionsMessageProcessor { + self_key_pair, + servers_set_change_creator_connector, + sessions, + connections, + } + } + + /// Process single session message from connection. + fn process_message, D>( + &self, + sessions: &ClusterSessionsContainer, + connection: Arc, + mut message: Message, + ) -> Option> + where + Message: IntoSessionId + { + // get or create new session, if required + let mut sender = *connection.node_id(); + let session = self.prepare_session(sessions, &sender, &message); + // send error if session is not found, or failed to create + let session = match session { + Ok(session) => session, + Err(error) => { + // this is new session => it is not yet in container + warn!(target: "secretstore_net", + "{}: {} session read error '{}' when requested for session from node {}", + self.self_key_pair.public(), S::type_name(), error, sender); + if !message.is_error_message() { + let qed = "session_id only fails for cluster messages; + only session messages are passed to process_message; + qed"; + let session_id = message.into_session_id().expect(qed); + let session_nonce = message.session_nonce().expect(qed); + + connection.send_message(SC::make_error_message(session_id, session_nonce, error)); + } + return None; + }, + }; + + let session_id = session.id(); + let mut is_queued_message = false; + loop { + let message_result = session.on_message(&sender, &message); + match message_result { + Ok(_) => { + // if session is completed => stop + if session.is_finished() { + info!(target: "secretstore_net", + "{}: {} session completed", self.self_key_pair.public(), S::type_name()); + sessions.remove(&session_id); + return Some(session); + } + + // try to dequeue message + match sessions.dequeue_message(&session_id) { + Some((msg_sender, msg)) => { + is_queued_message = true; + sender = msg_sender; + message = msg; + }, + None => return Some(session), + } + }, + Err(Error::TooEarlyForRequest) => { + sessions.enqueue_message(&session_id, sender, message, is_queued_message); + return Some(session); + }, + Err(err) => { + warn!( + target: "secretstore_net", + "{}: {} session error '{}' when processing message {} from node {}", + self.self_key_pair.public(), + S::type_name(), + err, + message, + sender); + session.on_session_error(self.self_key_pair.public(), err); + sessions.remove(&session_id); + return Some(session); + }, + } + } + } + + /// Get or insert new session. + fn prepare_session, D>( + &self, + sessions: &ClusterSessionsContainer, + sender: &NodeId, + message: &Message + ) -> Result, Error> + where + Message: IntoSessionId + { + fn requires_all_connections(message: &Message) -> bool { + match *message { + Message::Generation(_) => true, + Message::ShareAdd(_) => true, + Message::ServersSetChange(_) => true, + _ => false, + } + } + + // get or create new session, if required + let session_id = message.into_session_id() + .expect("into_session_id fails for cluster messages only; + only session messages are passed to prepare_session; + qed"); + let is_initialization_message = message.is_initialization_message(); + let is_delegation_message = message.is_delegation_message(); + match is_initialization_message || is_delegation_message { + false => sessions.get(&session_id, true).ok_or(Error::NoActiveSessionWithId), + true => { + let creation_data = SC::creation_data_from_message(&message)?; + let master = if is_initialization_message { + *sender + } else { + *self.self_key_pair.public() + }; + let cluster = create_cluster_view( + self.self_key_pair.clone(), + self.connections.clone(), + requires_all_connections(&message))?; + + let nonce = Some(message.session_nonce().ok_or(Error::InvalidMessage)?); + let exclusive = message.is_exclusive_session_message(); + sessions.insert(cluster, master, session_id, nonce, exclusive, creation_data) + }, + } + } + + /// Process single cluster message from the connection. + fn process_cluster_message(&self, connection: Arc, message: ClusterMessage) { + match message { + ClusterMessage::KeepAlive(_) => { + let msg = Message::Cluster(ClusterMessage::KeepAliveResponse(message::KeepAliveResponse { + session_id: None, + })); + connection.send_message(msg) + }, + ClusterMessage::KeepAliveResponse(msg) => if let Some(session_id) = msg.session_id { + self.sessions.on_session_keep_alive(connection.node_id(), session_id.into()); + }, + _ => warn!(target: "secretstore_net", "{}: received unexpected message {} from node {} at {}", + self.self_key_pair.public(), message, connection.node_id(), connection.node_address()), + } + } +} + +impl MessageProcessor for SessionsMessageProcessor { + fn process_disconnect(&self, node: &NodeId) { + self.sessions.on_connection_timeout(node); + } + + fn process_connection_message(&self, connection: Arc, message: Message) { + trace!(target: "secretstore_net", "{}: received message {} from {}", + self.self_key_pair.public(), message, connection.node_id()); + + // error is ignored as we only process errors on session level + match message { + Message::Generation(message) => self + .process_message(&self.sessions.generation_sessions, connection, Message::Generation(message)) + .map(|_| ()).unwrap_or_default(), + Message::Encryption(message) => self + .process_message(&self.sessions.encryption_sessions, connection, Message::Encryption(message)) + .map(|_| ()).unwrap_or_default(), + Message::Decryption(message) => self + .process_message(&self.sessions.decryption_sessions, connection, Message::Decryption(message)) + .map(|_| ()).unwrap_or_default(), + Message::SchnorrSigning(message) => self + .process_message(&self.sessions.schnorr_signing_sessions, connection, Message::SchnorrSigning(message)) + .map(|_| ()).unwrap_or_default(), + Message::EcdsaSigning(message) => self + .process_message(&self.sessions.ecdsa_signing_sessions, connection, Message::EcdsaSigning(message)) + .map(|_| ()).unwrap_or_default(), + Message::ServersSetChange(message) => { + let message = Message::ServersSetChange(message); + let is_initialization_message = message.is_initialization_message(); + let session = self.process_message(&self.sessions.admin_sessions, connection, message); + if is_initialization_message { + if let Some(session) = session { + self.servers_set_change_creator_connector + .set_key_servers_set_change_session(session.clone()); + } + } + }, + Message::KeyVersionNegotiation(message) => { + let session = self.process_message( + &self.sessions.negotiation_sessions, connection, Message::KeyVersionNegotiation(message)); + self.try_continue_session(session); + }, + Message::ShareAdd(message) => self.process_message( + &self.sessions.admin_sessions, connection, Message::ShareAdd(message)) + .map(|_| ()).unwrap_or_default(), + Message::Cluster(message) => self.process_cluster_message(connection, message), + } + } + + fn try_continue_session( + &self, + session: Option>> + ) { + if let Some(session) = session { + let meta = session.meta(); + let is_master_node = meta.self_node_id == meta.master_node_id; + if is_master_node && session.is_finished() { + self.sessions.negotiation_sessions.remove(&session.id()); + match session.wait() { + Ok(Some((version, master))) => match session.take_continue_action() { + Some(ContinueAction::Decrypt( + session, origin, is_shadow_decryption, is_broadcast_decryption + )) => { + let initialization_error = if self.self_key_pair.public() == &master { + session.initialize( + origin, version, is_shadow_decryption, is_broadcast_decryption) + } else { + session.delegate( + master, origin, version, is_shadow_decryption, is_broadcast_decryption) + }; + + if let Err(error) = initialization_error { + session.on_session_error(&meta.self_node_id, error); + self.sessions.decryption_sessions.remove(&session.id()); + } + }, + Some(ContinueAction::SchnorrSign(session, message_hash)) => { + let initialization_error = if self.self_key_pair.public() == &master { + session.initialize(version, message_hash) + } else { + session.delegate(master, version, message_hash) + }; + + if let Err(error) = initialization_error { + session.on_session_error(&meta.self_node_id, error); + self.sessions.schnorr_signing_sessions.remove(&session.id()); + } + }, + Some(ContinueAction::EcdsaSign(session, message_hash)) => { + let initialization_error = if self.self_key_pair.public() == &master { + session.initialize(version, message_hash) + } else { + session.delegate(master, version, message_hash) + }; + + if let Err(error) = initialization_error { + session.on_session_error(&meta.self_node_id, error); + self.sessions.ecdsa_signing_sessions.remove(&session.id()); + } + }, + None => (), + }, + Ok(None) => unreachable!("is_master_node; session is finished; + negotiation version always finished with result on master; + qed"), + Err(error) => match session.take_continue_action() { + Some(ContinueAction::Decrypt(session, _, _, _)) => { + session.on_session_error(&meta.self_node_id, error); + self.sessions.decryption_sessions.remove(&session.id()); + }, + Some(ContinueAction::SchnorrSign(session, _)) => { + session.on_session_error(&meta.self_node_id, error); + self.sessions.schnorr_signing_sessions.remove(&session.id()); + }, + Some(ContinueAction::EcdsaSign(session, _)) => { + session.on_session_error(&meta.self_node_id, error); + self.sessions.ecdsa_signing_sessions.remove(&session.id()); + }, + None => (), + }, + } + } + } + } + + fn maintain_sessions(&self) { + self.sessions.stop_stalled_sessions(); + self.sessions.sessions_keep_alive(); + } + + fn start_servers_set_change_session(&self, params: ServersSetChangeParams) -> Result, Error> { + new_servers_set_change_session( + self.self_key_pair.clone(), + &*self.sessions, + self.connections.clone(), + self.servers_set_change_creator_connector.clone(), + params, + ) + } +} diff --git a/util/EIP-152/Cargo.toml b/util/EIP-152/Cargo.toml new file mode 100644 index 0000000000..fe65d01109 --- /dev/null +++ b/util/EIP-152/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "eip-152" +version = "0.1.0" +authors = ["Parity Technologies "] +repository = "https://github.com/paritytech/parity-ethereum" +documentation = "https://docs.rs/eip-152" +readme = "README.md" +description = "eip-512 blake2 F compression function" +keywords = ["eip-152", "eip152", "eip"] +license = "GPL-3.0" +edition = "2018" + +[dependencies] +rustc-hex = "2.0.1" diff --git a/util/EIP-152/src/lib.rs b/util/EIP-152/src/lib.rs new file mode 100644 index 0000000000..fd68b9072d --- /dev/null +++ b/util/EIP-152/src/lib.rs @@ -0,0 +1,192 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +/// The precomputed values for BLAKE2b [from the spec](https://tools.ietf.org/html/rfc7693#section-2.7) +/// There are 10 16-byte arrays - one for each round +/// the entries are calculated from the sigma constants. +const SIGMA: [[usize; 16]; 10] = [ + [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], + [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], + [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4], + [ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8], + [ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13], + [ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9], + [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11], + [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10], + [ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], + [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0], +]; + + +/// IV is the initialization vector for BLAKE2b. See https://tools.ietf.org/html/rfc7693#section-2.6 +/// for details. +const IV: [u64; 8] = [ + 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, +]; + + +#[inline(always)] +/// The G mixing function. See https://tools.ietf.org/html/rfc7693#section-3.1 +fn g(v: &mut [u64], a: usize, b: usize, c: usize, d: usize, x: u64, y: u64) { + v[a] = v[a].wrapping_add(v[b]).wrapping_add(x); + v[d] = (v[d] ^ v[a]).rotate_right(32); + v[c] = v[c].wrapping_add(v[d]); + v[b] = (v[b] ^ v[c]).rotate_right(24); + v[a] = v[a].wrapping_add(v[b]).wrapping_add(y); + v[d] = (v[d] ^ v[a]).rotate_right(16); + v[c] = v[c].wrapping_add(v[d]); + v[b] = (v[b] ^ v[c]).rotate_right(63); +} + +/// The Blake2 compression function F. See https://tools.ietf.org/html/rfc7693#section-3.2 +/// Takes as an argument the state vector `h`, message block vector `m`, offset counter `t`, final +/// block indicator flag `f`, and number of rounds `rounds`. The state vector provided as the first +/// parameter is modified by the function. +pub fn compress(h: &mut [u64; 8], m: [u64; 16], t: [u64; 2], f: bool, rounds: usize) { + let mut v = [0u64; 16]; + v[..h.len()].copy_from_slice(h); // First half from state. + v[h.len()..].copy_from_slice(&IV); // Second half from IV. + + v[12] ^= t[0]; + v[13] ^= t[1]; + + if f { + v[14] = !v[14] // Invert all bits if the last-block-flag is set. + } + for i in 0..rounds { + // Message word selection permutation for this round. + let s = &SIGMA[i % 10]; + g(&mut v, 0, 4, 8, 12, m[s[0]], m[s[1]]); + g(&mut v, 1, 5, 9, 13, m[s[2]], m[s[3]]); + g(&mut v, 2, 6, 10, 14, m[s[4]], m[s[5]]); + g(&mut v, 3, 7, 11, 15, m[s[6]], m[s[7]]); + + g(&mut v, 0, 5, 10, 15, m[s[8]], m[s[9]]); + g(&mut v, 1, 6, 11, 12, m[s[10]], m[s[11]]); + g(&mut v, 2, 7, 8, 13, m[s[12]], m[s[13]]); + g(&mut v, 3, 4, 9, 14, m[s[14]], m[s[15]]); + } + + for i in 0..8 { + h[i] ^= v[i] ^ v[i + 8]; + } +} + + +#[cfg(test)] +mod tests { + use crate::compress; + use rustc_hex::FromHex; + + #[test] + fn test_blake2_f() { + // test from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-152.md#example-usage-in-solidity + let mut h_in = [ + 0x6a09e667f2bdc948_u64, 0xbb67ae8584caa73b_u64, + 0x3c6ef372fe94f82b_u64, 0xa54ff53a5f1d36f1_u64, + 0x510e527fade682d1_u64, 0x9b05688c2b3e6c1f_u64, + 0x1f83d9abfb41bd6b_u64, 0x5be0cd19137e2179_u64, + ]; + + let m = [ + 0x0000000000636261_u64, 0x0000000000000000_u64, 0x0000000000000000_u64, + 0x0000000000000000_u64, 0x0000000000000000_u64, 0x0000000000000000_u64, + 0x0000000000000000_u64, 0x0000000000000000_u64, 0x0000000000000000_u64, + 0x0000000000000000_u64, 0x0000000000000000_u64, 0x0000000000000000_u64, + 0x0000000000000000_u64, 0x0000000000000000_u64, 0x0000000000000000_u64, + 0x0000000000000000_u64, + ]; + let c = [3, 0]; + let f = true; + let rounds = 12; + let h_out: [u64; 8] = [ + 0x0D4D1C983FA580BA_u64, 0xE9F6129FB697276A_u64, 0xB7C45A68142F214C_u64, + 0xD1A2FFDB6FBB124B_u64, 0x2D79AB2A39C5877D_u64, 0x95CC3345DED552C2_u64, + 0x5A92F1DBA88AD318_u64, 0x239900D4ED8623B9_u64, + ]; + + compress(&mut h_in, m, c, f, rounds); + + assert_eq!(h_in, h_out); + } + + fn to_u64_slice(vec: &[u8], slice: &mut [u64]) { + vec.chunks(8).enumerate().for_each(|(index, val)| { + slice[index] = u64::from_le_bytes([val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7]]) + }) + } + + #[test] + fn test_vectors_from_eip() { + let vec = vec![ + ( + // Test vector 4 + "0000000048c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", + "08c9bcf367e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d282e6ad7f520e511f6c3e2b8c68059b9442be0454267ce079217e1319cde05b", + ), + ( // test vector 5 + "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", + "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923", + ), + ( + // Test vector 6 + "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000", + "75ab69d3190a562c51aef8d88f1c2775876944407270c42c9844252c26d2875298743e7f6d5ea2f2d3e8d226039cd31b4e426ac4f2d3d666a610c2116fde4735", + ), + ( + // Test vector 7 + "0000000148c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", + "b63a380cb2897d521994a85234ee2c181b5f844d2c624c002677e9703449d2fba551b3a8333bcdf5f2f7e08993d53923de3d64fcc68c034e717b9293fed7a421", + ), + // Test vector 8 – u32::MAX rounds – too slow to run +// ( +// "ffffffff48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", +// "fc59093aafa9ab43daae0e914c57635c5402d8e3d2130eb9b3cc181de7f0ecf9b22bf99a7815ce16419e200e01846e6b5df8cc7703041bbceb571de6631d2615", +// ), + ]; + for (hex, output) in vec { + let hex = hex; + let bytes: Vec = hex.from_hex().unwrap(); + + assert_eq!(bytes.len(), 213); + + let mut h = [0u64; 8]; + let mut m = [0u64; 16]; + let mut t = [0u64; 2]; + + let rounds = u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]); + let f = match bytes[212] { + 1 => true, + 0 => false, + _ => unreachable!() + }; + + to_u64_slice(&bytes[4..68], &mut h); + to_u64_slice(&bytes[68..196], &mut m); + to_u64_slice(&bytes[196..212], &mut t); + + compress(&mut h, m, t, f, rounds as usize); + + let output: Vec = output.from_hex().unwrap(); + + let mut out = [0u64; 8]; + to_u64_slice(&output[..], &mut out); + + assert_eq!(out, h); + } + } +} diff --git a/util/blooms-db/benches/blooms.rs b/util/blooms-db/benches/blooms.rs index 1cb3bad543..4a0c54fbdb 100644 --- a/util/blooms-db/benches/blooms.rs +++ b/util/blooms-db/benches/blooms.rs @@ -31,8 +31,8 @@ use ethbloom::Bloom; 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(999_999, iter::once(&Bloom::zero())).unwrap(); + let bloom = Bloom::from_low_u64_be(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(); @@ -48,9 +48,9 @@ fn blooms_filter_1_million_ok(b: &mut Bencher) { 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(999_999, iter::once(&Bloom::zero())).unwrap(); + let bloom = Bloom::from_low_u64_be(0x001); + let bad_bloom = Bloom::from_low_u64_be(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(); @@ -66,9 +66,9 @@ fn blooms_filter_1_million_miss(b: &mut Bencher) { 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(999_999, iter::once(&Bloom::zero())).unwrap(); + let bloom = Bloom::from_low_u64_be(0x001); + let bad_bloom = Bloom::from_low_u64_be(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(); diff --git a/util/blooms-db/src/db.rs b/util/blooms-db/src/db.rs index 7d003f7e27..2a05ec8123 100644 --- a/util/blooms-db/src/db.rs +++ b/util/blooms-db/src/db.rs @@ -21,7 +21,7 @@ use ethbloom; use file::{File, FileIterator}; -fn other_io_err(e: E) -> io::Error where E: Into> { +fn other_io_err(e: E) -> io::Error where E: Into> { io::Error::new(io::ErrorKind::Other, e) } diff --git a/util/fetch/Cargo.toml b/util/fetch/Cargo.toml index d5df1034bc..c45c2ca4f4 100644 --- a/util/fetch/Cargo.toml +++ b/util/fetch/Cargo.toml @@ -9,7 +9,7 @@ authors = ["Parity Technologies "] [dependencies] futures = "0.1" hyper = "~0.12.9" -hyper-rustls = "0.14" +hyper-rustls = "0.16.0" http = "0.1" log = "0.4" tokio = "~0.1.8" diff --git a/util/journaldb/Cargo.toml b/util/journaldb/Cargo.toml index 20657f2ca4..045b42d662 100644 --- a/util/journaldb/Cargo.toml +++ b/util/journaldb/Cargo.toml @@ -8,12 +8,12 @@ license = "GPL3" [dependencies] parity-bytes = "0.1" ethereum-types = "0.4" -hashdb = "0.3.0" +hash-db = "0.11.0" heapsize = "0.4" keccak-hasher = { path = "../keccak-hasher" } kvdb = "0.1" log = "0.4" -memorydb = "0.3.0" +memory-db = "0.11.0" parking_lot = "0.7" fastmap = { path = "../../util/fastmap" } rlp = { version = "0.3.0", features = ["ethereum"] } diff --git a/util/journaldb/src/archivedb.rs b/util/journaldb/src/archivedb.rs index a6dcd29377..a068919a78 100644 --- a/util/journaldb/src/archivedb.rs +++ b/util/journaldb/src/archivedb.rs @@ -23,12 +23,12 @@ use std::sync::Arc; use bytes::Bytes; use ethereum_types::H256; -use hashdb::*; +use hash_db::{HashDB}; use keccak_hasher::KeccakHasher; use kvdb::{KeyValueDB, DBTransaction, DBValue}; use rlp::{encode, decode}; use super::{DB_PREFIX_LEN, LATEST_ERA_KEY, error_key_already_exists, error_negatively_reference_hash}; -use super::memorydb::*; +use super::memory_db::*; use traits::JournalDB; /// Implementation of the `HashDB` trait for a disk-backed database with a memory overlay @@ -52,7 +52,7 @@ impl ArchiveDB { .expect("Low-level database error.") .map(|val| decode::(&val).expect("decoding db value failed")); ArchiveDB { - overlay: MemoryDB::new(), + overlay: ::new_memory_db(), backing, latest_era, column, @@ -62,31 +62,14 @@ impl ArchiveDB { fn payload(&self, key: &H256) -> Option { self.backing.get(self.column, key).expect("Low-level database error. Some issue with your hard disk?") } + } impl HashDB for ArchiveDB { - fn keys(&self) -> HashMap { - let mut ret: HashMap = self.backing.iter(self.column) - .map(|(key, _)| (H256::from_slice(&*key), 1)) - .collect(); - - for (key, refs) in self.overlay.keys() { - match ret.entry(key) { - Entry::Occupied(mut entry) => { - *entry.get_mut() += refs; - }, - Entry::Vacant(entry) => { - entry.insert(refs); - } - } - } - ret - } - fn get(&self, key: &H256) -> Option { if let Some((d, rc)) = self.overlay.raw(key) { if rc > 0 { - return Some(d); + return Some(d.clone()); } } self.payload(key) @@ -109,7 +92,28 @@ impl HashDB for ArchiveDB { } } +impl ::traits::KeyedHashDB for ArchiveDB { + fn keys(&self) -> HashMap { + let mut ret: HashMap = self.backing.iter(self.column) + .map(|(key, _)| (H256::from_slice(&*key), 1)) + .collect(); + + for (key, refs) in self.overlay.keys() { + match ret.entry(key) { + Entry::Occupied(mut entry) => { + *entry.get_mut() += refs; + }, + Entry::Vacant(entry) => { + entry.insert(refs); + } + } + } + ret + } +} + impl JournalDB for ArchiveDB { + fn boxed_clone(&self) -> Box { Box::new(ArchiveDB { overlay: self.overlay.clone(), @@ -202,7 +206,7 @@ impl JournalDB for ArchiveDB { mod tests { use keccak::keccak; - use hashdb::HashDB; + use hash_db::HashDB; use super::*; use {kvdb_memorydb, JournalDB}; diff --git a/util/journaldb/src/as_hash_db_impls.rs b/util/journaldb/src/as_hash_db_impls.rs index 203a5be676..8a380ea56a 100644 --- a/util/journaldb/src/as_hash_db_impls.rs +++ b/util/journaldb/src/as_hash_db_impls.rs @@ -15,7 +15,7 @@ // along with Parity Ethereum. If not, see . //! Impls of the `AsHashDB` upcast trait for all different variants of DB -use hashdb::{HashDB, AsHashDB}; +use hash_db::{HashDB, AsHashDB}; use keccak_hasher::KeccakHasher; use archivedb::ArchiveDB; use earlymergedb::EarlyMergeDB; @@ -23,28 +23,49 @@ use overlayrecentdb::OverlayRecentDB; use refcounteddb::RefCountedDB; use overlaydb::OverlayDB; use kvdb::DBValue; +use crate::{KeyedHashDB, AsKeyedHashDB}; impl AsHashDB for ArchiveDB { - fn as_hashdb(&self) -> &HashDB { self } - fn as_hashdb_mut(&mut self) -> &mut HashDB { self } + fn as_hash_db(&self) -> &HashDB { self } + fn as_hash_db_mut(&mut self) -> &mut HashDB { self } } impl AsHashDB for EarlyMergeDB { - fn as_hashdb(&self) -> &HashDB { self } - fn as_hashdb_mut(&mut self) -> &mut HashDB { self } + fn as_hash_db(&self) -> &HashDB { self } + fn as_hash_db_mut(&mut self) -> &mut HashDB { self } } impl AsHashDB for OverlayRecentDB { - fn as_hashdb(&self) -> &HashDB { self } - fn as_hashdb_mut(&mut self) -> &mut HashDB { self } + fn as_hash_db(&self) -> &HashDB { self } + fn as_hash_db_mut(&mut self) -> &mut HashDB { self } } impl AsHashDB for RefCountedDB { - fn as_hashdb(&self) -> &HashDB { self } - fn as_hashdb_mut(&mut self) -> &mut HashDB { self } + fn as_hash_db(&self) -> &HashDB { self } + fn as_hash_db_mut(&mut self) -> &mut HashDB { self } } impl AsHashDB for OverlayDB { - fn as_hashdb(&self) -> &HashDB { self } - fn as_hashdb_mut(&mut self) -> &mut HashDB { self } + fn as_hash_db(&self) -> &HashDB { self } + fn as_hash_db_mut(&mut self) -> &mut HashDB { self } +} + +impl AsKeyedHashDB for ArchiveDB { + fn as_keyed_hash_db(&self) -> &KeyedHashDB { self } +} + +impl AsKeyedHashDB for EarlyMergeDB { + fn as_keyed_hash_db(&self) -> &KeyedHashDB { self } +} + +impl AsKeyedHashDB for OverlayRecentDB { + fn as_keyed_hash_db(&self) -> &KeyedHashDB { self } +} + +impl AsKeyedHashDB for RefCountedDB { + fn as_keyed_hash_db(&self) -> &KeyedHashDB { self } +} + +impl AsKeyedHashDB for OverlayDB { + fn as_keyed_hash_db(&self) -> &KeyedHashDB { self } } diff --git a/util/journaldb/src/earlymergedb.rs b/util/journaldb/src/earlymergedb.rs index aac1af0169..2a55200c49 100644 --- a/util/journaldb/src/earlymergedb.rs +++ b/util/journaldb/src/earlymergedb.rs @@ -23,11 +23,11 @@ use std::sync::Arc; use bytes::Bytes; use ethereum_types::H256; -use hashdb::*; +use hash_db::{HashDB}; use heapsize::HeapSizeOf; use keccak_hasher::KeccakHasher; use kvdb::{KeyValueDB, DBTransaction, DBValue}; -use memorydb::*; +use memory_db::*; use parking_lot::RwLock; use rlp::{encode, decode}; use super::{DB_PREFIX_LEN, LATEST_ERA_KEY, error_negatively_reference_hash, error_key_already_exists}; @@ -120,7 +120,7 @@ impl EarlyMergeDB { let (latest_era, refs) = EarlyMergeDB::read_refs(&*backing, col); let refs = Some(Arc::new(RwLock::new(refs))); EarlyMergeDB { - overlay: MemoryDB::new(), + overlay: ::new_memory_db(), backing: backing, refs: refs, latest_era: latest_era, @@ -285,31 +285,14 @@ impl EarlyMergeDB { } (latest_era, refs) } + } impl HashDB for EarlyMergeDB { - fn keys(&self) -> HashMap { - let mut ret: HashMap = self.backing.iter(self.column) - .map(|(key, _)| (H256::from_slice(&*key), 1)) - .collect(); - - for (key, refs) in self.overlay.keys() { - match ret.entry(key) { - Entry::Occupied(mut entry) => { - *entry.get_mut() += refs; - }, - Entry::Vacant(entry) => { - entry.insert(refs); - } - } - } - ret - } - fn get(&self, key: &H256) -> Option { if let Some((d, rc)) = self.overlay.raw(key) { if rc > 0 { - return Some(d) + return Some(d.clone()) } } self.payload(key) @@ -330,6 +313,26 @@ impl HashDB for EarlyMergeDB { } } +impl ::traits::KeyedHashDB for EarlyMergeDB { + fn keys(&self) -> HashMap { + let mut ret: HashMap = self.backing.iter(self.column) + .map(|(key, _)| (H256::from_slice(&*key), 1)) + .collect(); + + for (key, refs) in self.overlay.keys() { + match ret.entry(key) { + Entry::Occupied(mut entry) => { + *entry.get_mut() += refs; + }, + Entry::Vacant(entry) => { + entry.insert(refs); + } + } + } + ret + } +} + impl JournalDB for EarlyMergeDB { fn boxed_clone(&self) -> Box { Box::new(EarlyMergeDB { @@ -523,7 +526,7 @@ impl JournalDB for EarlyMergeDB { mod tests { use keccak::keccak; - use hashdb::HashDB; + use hash_db::HashDB; use super::*; use super::super::traits::JournalDB; use kvdb_memorydb; diff --git a/util/journaldb/src/lib.rs b/util/journaldb/src/lib.rs index 67ceeb848a..3eb6ee38c8 100644 --- a/util/journaldb/src/lib.rs +++ b/util/journaldb/src/lib.rs @@ -22,10 +22,10 @@ extern crate log; extern crate ethereum_types; extern crate parity_bytes as bytes; -extern crate hashdb; +extern crate hash_db; extern crate keccak_hasher; extern crate kvdb; -extern crate memorydb; +extern crate memory_db; extern crate parking_lot; extern crate fastmap; extern crate rlp; @@ -54,6 +54,11 @@ pub mod overlaydb; /// Export the `JournalDB` trait. pub use self::traits::JournalDB; +/// Export keyed hash trait +pub use self::traits::KeyedHashDB; +/// Export as keyed hash trait +pub use self::traits::AsKeyedHashDB; + /// Journal database operating strategy. #[derive(Debug, PartialEq, Clone, Copy)] pub enum Algorithm { @@ -158,6 +163,10 @@ fn error_negatively_reference_hash(hash: ðereum_types::H256) -> io::Error { io::Error::new(io::ErrorKind::Other, format!("Entry {} removed from database more times than it was added.", hash)) } +pub fn new_memory_db() -> memory_db::MemoryDB { + memory_db::MemoryDB::from_null_node(&rlp::NULL_RLP, rlp::NULL_RLP.as_ref().into()) +} + #[cfg(test)] mod tests { use super::Algorithm; diff --git a/util/journaldb/src/overlaydb.rs b/util/journaldb/src/overlaydb.rs index d7018d1edb..757a92e621 100644 --- a/util/journaldb/src/overlaydb.rs +++ b/util/journaldb/src/overlaydb.rs @@ -23,9 +23,9 @@ use std::sync::Arc; use ethereum_types::H256; use rlp::{Rlp, RlpStream, Encodable, DecoderError, Decodable, encode, decode}; -use hashdb::*; +use hash_db::{HashDB}; use keccak_hasher::KeccakHasher; -use memorydb::*; +use memory_db::*; use kvdb::{KeyValueDB, DBTransaction, DBValue}; use super::{error_negatively_reference_hash}; @@ -80,7 +80,7 @@ impl Decodable for Payload { impl OverlayDB { /// Create a new instance of OverlayDB given a `backing` database. pub fn new(backing: Arc, col: Option) -> OverlayDB { - OverlayDB{ overlay: MemoryDB::new(), backing: backing, column: col } + OverlayDB{ overlay: ::new_memory_db(), backing: backing, column: col } } /// Create a new instance of OverlayDB with an anonymous temporary database. @@ -153,9 +153,10 @@ impl OverlayDB { true } } + } -impl HashDB for OverlayDB { +impl crate::KeyedHashDB for OverlayDB { fn keys(&self) -> HashMap { let mut ret: HashMap = self.backing.iter(self.column) .map(|(key, _)| { @@ -178,13 +179,16 @@ impl HashDB for OverlayDB { ret } +} + +impl HashDB for OverlayDB { fn get(&self, key: &H256) -> Option { // return ok if positive; if negative, check backing - might be enough references there to make // it positive again. let k = self.overlay.raw(key); let memrc = { if let Some((d, rc)) = k { - if rc > 0 { return Some(d); } + if rc > 0 { return Some(d.clone()); } rc } else { 0 diff --git a/util/journaldb/src/overlayrecentdb.rs b/util/journaldb/src/overlayrecentdb.rs index 67f5ab8890..a48e59d91f 100644 --- a/util/journaldb/src/overlayrecentdb.rs +++ b/util/journaldb/src/overlayrecentdb.rs @@ -23,11 +23,11 @@ use std::sync::Arc; use bytes::Bytes; use ethereum_types::H256; -use hashdb::*; +use hash_db::{HashDB}; use heapsize::HeapSizeOf; use keccak_hasher::KeccakHasher; use kvdb::{KeyValueDB, DBTransaction, DBValue}; -use memorydb::*; +use memory_db::*; use parking_lot::RwLock; use fastmap::H256FastMap; use rlp::{Rlp, RlpStream, encode, decode, DecoderError, Decodable, Encodable}; @@ -157,7 +157,7 @@ impl OverlayRecentDB { pub fn new(backing: Arc, col: Option) -> OverlayRecentDB { let journal_overlay = Arc::new(RwLock::new(OverlayRecentDB::read_overlay(&*backing, col))); OverlayRecentDB { - transaction_overlay: MemoryDB::new(), + transaction_overlay: ::new_memory_db(), backing: backing, journal_overlay: journal_overlay, column: col, @@ -181,7 +181,7 @@ impl OverlayRecentDB { fn read_overlay(db: &KeyValueDB, col: Option) -> JournalOverlay { let mut journal = HashMap::new(); - let mut overlay = MemoryDB::new(); + let mut overlay = ::new_memory_db(); let mut count = 0; let mut latest_era = None; let mut earliest_era = None; @@ -233,6 +233,7 @@ impl OverlayRecentDB { cumulative_size: cumulative_size, } } + } #[inline] @@ -242,7 +243,28 @@ fn to_short_key(key: &H256) -> H256 { k } +impl ::traits::KeyedHashDB for OverlayRecentDB { + fn keys(&self) -> HashMap { + let mut ret: HashMap = self.backing.iter(self.column) + .map(|(key, _)| (H256::from_slice(&*key), 1)) + .collect(); + + for (key, refs) in self.transaction_overlay.keys() { + match ret.entry(key) { + Entry::Occupied(mut entry) => { + *entry.get_mut() += refs; + }, + Entry::Vacant(entry) => { + entry.insert(refs); + } + } + } + ret + } +} + impl JournalDB for OverlayRecentDB { + fn boxed_clone(&self) -> Box { Box::new(self.clone()) } @@ -365,7 +387,7 @@ impl JournalDB for OverlayRecentDB { for h in &journal.insertions { if let Some((d, rc)) = journal_overlay.backing_overlay.raw(&to_short_key(h)) { if rc > 0 { - canon_insertions.push((h.clone(), d)); //TODO: optimize this to avoid data copy + canon_insertions.push((h.clone(), d.clone())); //TODO: optimize this to avoid data copy } } } @@ -440,28 +462,10 @@ impl JournalDB for OverlayRecentDB { } impl HashDB for OverlayRecentDB { - fn keys(&self) -> HashMap { - let mut ret: HashMap = self.backing.iter(self.column) - .map(|(key, _)| (H256::from_slice(&*key), 1)) - .collect(); - - for (key, refs) in self.transaction_overlay.keys() { - match ret.entry(key) { - Entry::Occupied(mut entry) => { - *entry.get_mut() += refs; - }, - Entry::Vacant(entry) => { - entry.insert(refs); - } - } - } - ret - } - fn get(&self, key: &H256) -> Option { if let Some((d, rc)) = self.transaction_overlay.raw(key) { if rc > 0 { - return Some(d) + return Some(d.clone()) } } let v = { @@ -493,7 +497,7 @@ mod tests { use keccak::keccak; use super::*; - use hashdb::HashDB; + use hash_db::HashDB; use {kvdb_memorydb, JournalDB}; fn new_db() -> OverlayRecentDB { diff --git a/util/journaldb/src/refcounteddb.rs b/util/journaldb/src/refcounteddb.rs index 36cac3201a..bdd396a481 100644 --- a/util/journaldb/src/refcounteddb.rs +++ b/util/journaldb/src/refcounteddb.rs @@ -22,11 +22,11 @@ use std::sync::Arc; use bytes::Bytes; use ethereum_types::H256; -use hashdb::*; +use hash_db::{HashDB}; use heapsize::HeapSizeOf; use keccak_hasher::KeccakHasher; use kvdb::{KeyValueDB, DBTransaction, DBValue}; -use memorydb::MemoryDB; +use memory_db::MemoryDB; use overlaydb::OverlayDB; use rlp::{encode, decode}; use super::{DB_PREFIX_LEN, LATEST_ERA_KEY}; @@ -81,7 +81,6 @@ impl RefCountedDB { } impl HashDB for RefCountedDB { - fn keys(&self) -> HashMap { self.forward.keys() } fn get(&self, key: &H256) -> Option { self.forward.get(key) } fn contains(&self, key: &H256) -> bool { self.forward.contains(key) } fn insert(&mut self, value: &[u8]) -> H256 { let r = self.forward.insert(value); self.inserts.push(r.clone()); r } @@ -89,6 +88,10 @@ impl HashDB for RefCountedDB { fn remove(&mut self, key: &H256) { self.removes.push(key.clone()); } } +impl ::traits::KeyedHashDB for RefCountedDB { + fn keys(&self) -> HashMap { self.forward.keys() } +} + impl JournalDB for RefCountedDB { fn boxed_clone(&self) -> Box { Box::new(RefCountedDB { @@ -216,7 +219,7 @@ impl JournalDB for RefCountedDB { mod tests { use keccak::keccak; - use hashdb::HashDB; + use hash_db::HashDB; use super::*; use {JournalDB, kvdb_memorydb}; diff --git a/util/journaldb/src/traits.rs b/util/journaldb/src/traits.rs index 68ca57b96a..e6ce8acb04 100644 --- a/util/journaldb/src/traits.rs +++ b/util/journaldb/src/traits.rs @@ -21,13 +21,28 @@ use std::sync::Arc; use bytes::Bytes; use ethereum_types::H256; -use hashdb::HashDB; +use hash_db::{HashDB, AsHashDB}; use keccak_hasher::KeccakHasher; use kvdb::{self, DBTransaction, DBValue}; +use std::collections::HashMap; + + +/// expose keys of a hashDB for debugging or tests (slow). +pub trait KeyedHashDB: HashDB { + /// Primarily use for tests, highly inefficient. + fn keys(&self) -> HashMap; +} + +/// Upcast to `KeyedHashDB` +pub trait AsKeyedHashDB: AsHashDB { + /// Perform upcast to KeyedHashDB. + fn as_keyed_hash_db(&self) -> &KeyedHashDB; +} /// A `HashDB` which can manage a short-term journal potentially containing many forks of mutually /// exclusive actions. -pub trait JournalDB: HashDB { +pub trait JournalDB: KeyedHashDB { + /// Return a copy of ourself, in a box. fn boxed_clone(&self) -> Box; @@ -78,7 +93,7 @@ pub trait JournalDB: HashDB { fn flush(&self) {} /// Consolidate all the insertions and deletions in the given memory overlay. - fn consolidate(&mut self, overlay: ::memorydb::MemoryDB); + fn consolidate(&mut self, overlay: ::memory_db::MemoryDB); /// Commit all changes in a single batch #[cfg(test)] diff --git a/util/keccak-hasher/Cargo.toml b/util/keccak-hasher/Cargo.toml index f61e461e29..edeecda833 100644 --- a/util/keccak-hasher/Cargo.toml +++ b/util/keccak-hasher/Cargo.toml @@ -8,5 +8,5 @@ license = "GPL-3.0" [dependencies] ethereum-types = "0.4" tiny-keccak = "1.4.2" -hashdb = "0.3.0" +hash-db = "0.11.0" plain_hasher = "0.2" diff --git a/util/keccak-hasher/src/lib.rs b/util/keccak-hasher/src/lib.rs index e37b03ee7d..d9c9be5454 100644 --- a/util/keccak-hasher/src/lib.rs +++ b/util/keccak-hasher/src/lib.rs @@ -15,12 +15,12 @@ // along with Parity Ethereum. If not, see . //! Hasher implementation for the Keccak-256 hash -extern crate hashdb; +extern crate hash_db; extern crate ethereum_types; extern crate tiny_keccak; extern crate plain_hasher; -use hashdb::Hasher; +use hash_db::Hasher; use ethereum_types::H256; use tiny_keccak::Keccak; use plain_hasher::PlainHasher; diff --git a/util/memzero/Cargo.toml b/util/memzero/Cargo.toml index 4b62e7adc1..67d17d26d0 100644 --- a/util/memzero/Cargo.toml +++ b/util/memzero/Cargo.toml @@ -1,4 +1,10 @@ [package] name = "memzero" version = "0.1.0" +description = "A wrapper for zero-ing out memory when dropped" +license = "GPL-3.0" +homepage = "https://parity.io" +repository = "https://github.com/paritytech/parity-ethereum" +documentation = "https://docs.rs/crate/memzero" authors = ["Parity Technologies "] +edition = "2018" diff --git a/util/network-devp2p/Cargo.toml b/util/network-devp2p/Cargo.toml index bea3f6e31c..8bf402e206 100644 --- a/util/network-devp2p/Cargo.toml +++ b/util/network-devp2p/Cargo.toml @@ -21,7 +21,7 @@ ansi_term = "0.10" rustc-hex = "1.0" ethcore-io = { path = "../io", features = ["mio"] } parity-bytes = "0.1" -parity-crypto = "0.2" +parity-crypto = "0.3.0" ethcore-network = { path = "../network" } ethereum-types = "0.4" ethkey = { path = "../../accounts/ethkey" } diff --git a/util/network-devp2p/src/discovery.rs b/util/network-devp2p/src/discovery.rs index 7bf8dc62e5..f18469e164 100644 --- a/util/network-devp2p/src/discovery.rs +++ b/util/network-devp2p/src/discovery.rs @@ -168,7 +168,6 @@ pub struct Discovery<'a> { discovery_id: NodeId, discovery_nodes: HashSet, node_buckets: Vec, - // Sometimes we don't want to add nodes to the NodeTable, but still want to // keep track of them to avoid excessive pinging (happens when an unknown node sends // a discovery request to us -- the node might be on a different net). @@ -257,7 +256,7 @@ impl<'a> Discovery<'a> { Ok(()) => None, Err(BucketError::Ourselves) => None, Err(BucketError::NotInTheBucket{node_entry, bucket_distance}) => Some((node_entry, bucket_distance)) - }.map(|(node_entry, bucket_distance)| { + }.and_then(|(node_entry, bucket_distance)| { trace!(target: "discovery", "Adding a new node {:?} into our bucket {}", &node_entry, bucket_distance); let mut added = HashMap::with_capacity(1); @@ -265,7 +264,7 @@ impl<'a> Discovery<'a> { let node_to_ping = { let bucket = &mut self.node_buckets[bucket_distance]; - bucket.nodes.push_front(BucketEntry::new(node_entry)); + bucket.nodes.push_front(BucketEntry::new(node_entry.clone())); if bucket.nodes.len() > BUCKET_SIZE { select_bucket_ping(bucket.nodes.iter()) } else { @@ -275,7 +274,12 @@ impl<'a> Discovery<'a> { if let Some(node) = node_to_ping { self.try_ping(node, PingReason::Default); }; - TableUpdates{added, removed: HashSet::new()} + + if node_entry.endpoint.is_valid_sync_node() { + Some(TableUpdates { added, removed: HashSet::new() }) + } else { + None + } }) } @@ -518,7 +522,18 @@ impl<'a> Discovery<'a> { fn on_ping(&mut self, rlp: &Rlp, node_id: &NodeId, from: &SocketAddr, echo_hash: &[u8]) -> Result, Error> { trace!(target: "discovery", "Got Ping from {:?}", &from); - let ping_from = NodeEndpoint::from_rlp(&rlp.at(1)?)?; + let ping_from = if let Ok(node_endpoint) = NodeEndpoint::from_rlp(&rlp.at(1)?) { + node_endpoint + } else { + let mut address = from.clone(); + // address here is the node's tcp port. If we are unable to get the `NodeEndpoint` from the `ping_from` + // rlp field then this is most likely a BootNode, set the tcp port to 0 because it can not be used for syncing. + address.set_port(0); + NodeEndpoint { + address, + udp_port: from.port() + } + }; let ping_to = NodeEndpoint::from_rlp(&rlp.at(2)?)?; let timestamp: u64 = rlp.val_at(3)?; self.check_timestamp(timestamp)?; @@ -540,7 +555,7 @@ impl<'a> Discovery<'a> { self.send_packet(PACKET_PONG, from, &response.drain())?; let entry = NodeEntry { id: *node_id, endpoint: pong_to.clone() }; - if !entry.endpoint.is_valid() { + if !entry.endpoint.is_valid_discovery_node() { debug!(target: "discovery", "Got bad address: {:?}", entry); } else if !self.is_allowed(&entry) { debug!(target: "discovery", "Address not allowed: {:?}", entry); @@ -728,7 +743,7 @@ impl<'a> Discovery<'a> { trace!(target: "discovery", "Got {} Neighbours from {:?}", results_count, &from); for r in rlp.at(0)?.iter() { let endpoint = NodeEndpoint::from_rlp(&r)?; - if !endpoint.is_valid() { + if !endpoint.is_valid_discovery_node() { debug!(target: "discovery", "Bad address: {:?}", endpoint); continue; } diff --git a/util/network-devp2p/src/host.rs b/util/network-devp2p/src/host.rs index 672fd30fbf..572f073a0d 100644 --- a/util/network-devp2p/src/host.rs +++ b/util/network-devp2p/src/host.rs @@ -42,6 +42,7 @@ use network::{NetworkConfiguration, NetworkIoMessage, ProtocolId, PeerId, Packet use network::{NonReservedPeerMode, NetworkContext as NetworkContextTrait}; use network::{SessionInfo, Error, ErrorKind, DisconnectReason, NetworkProtocolHandler}; use discovery::{Discovery, TableUpdates, NodeEntry, MAX_DATAGRAM_SIZE}; +use network::client_version::ClientVersion; use ip_utils::{map_external_address, select_public_address}; use parity_path::restrict_permissions_owner; use parking_lot::{Mutex, RwLock}; @@ -180,8 +181,8 @@ impl<'s> NetworkContextTrait for NetworkContext<'s> { Ok(()) } - fn peer_client_version(&self, peer: PeerId) -> String { - self.resolve_session(peer).map_or("unknown".to_owned(), |s| s.lock().info.client_version.clone()) + fn peer_client_version(&self, peer: PeerId) -> ClientVersion { + self.resolve_session(peer).map_or(ClientVersion::from("unknown").to_owned(), |s| s.lock().info.client_version.clone()) } fn session_info(&self, peer: PeerId) -> Option { @@ -253,6 +254,8 @@ struct ProtocolTimer { } /// Root IO handler. Manages protocol handlers, IO timers and network connections. +/// +/// NOTE: must keep the lock in order of: reserved_nodes (rwlock) -> session (mutex, from sessions) pub struct Host { pub info: RwLock, udp_socket: Mutex>, @@ -714,12 +717,13 @@ impl Host { let session_result = session.lock().readable(io, &self.info.read()); match session_result { Err(e) => { + let reserved_nodes = self.reserved_nodes.read(); let s = session.lock(); trace!(target: "network", "Session read error: {}:{:?} ({:?}) {:?}", token, s.id(), s.remote_addr(), e); match *e.kind() { ErrorKind::Disconnect(DisconnectReason::IncompatibleProtocol) | ErrorKind::Disconnect(DisconnectReason::UselessPeer) => { if let Some(id) = s.id() { - if !self.reserved_nodes.read().contains(id) { + if !reserved_nodes.contains(id) { let mut nodes = self.nodes.write(); nodes.note_failure(&id); nodes.mark_as_useless(id); @@ -733,6 +737,7 @@ impl Host { }, Ok(SessionData::Ready) => { let (_, egress_count, ingress_count) = self.session_count(); + let reserved_nodes = self.reserved_nodes.read(); let mut s = session.lock(); let (min_peers, mut max_peers, reserved_only, self_id) = { let info = self.info.read(); @@ -757,7 +762,7 @@ impl Host { if reserved_only || (s.info.originated && egress_count > min_peers) || (!s.info.originated && ingress_count > max_ingress) { - if !self.reserved_nodes.read().contains(&id) { + if !reserved_nodes.contains(&id) { // only proceed if the connecting peer is reserved. trace!(target: "network", "Disconnecting non-reserved peer {:?}", id); s.disconnect(io, DisconnectReason::TooManyPeers); @@ -972,7 +977,8 @@ impl Host { for i in to_remove { trace!(target: "network", "Removed from node table: {}", i); } - self.nodes.write().update(node_changes, &*self.reserved_nodes.read()); + let reserved_nodes = self.reserved_nodes.read(); + self.nodes.write().update(node_changes, &*reserved_nodes); } pub fn with_context(&self, protocol: ProtocolId, io: &IoContext, action: F) where F: FnOnce(&NetworkContextTrait) { @@ -1058,8 +1064,9 @@ impl IoHandler for Host { }, NODE_TABLE => { trace!(target: "network", "Refreshing node table"); - self.nodes.write().clear_useless(); - self.nodes.write().save(); + let mut nodes = self.nodes.write(); + nodes.clear_useless(); + nodes.save(); }, _ => match self.timers.read().get(&token).cloned() { Some(timer) => match self.handlers.read().get(&timer.protocol).cloned() { diff --git a/util/network-devp2p/src/node_table.rs b/util/network-devp2p/src/node_table.rs index 3cee93fd9a..db001bfe76 100644 --- a/util/network-devp2p/src/node_table.rs +++ b/util/network-devp2p/src/node_table.rs @@ -103,10 +103,16 @@ impl NodeEndpoint { self.to_rlp(rlp); } - /// Validates that the port is not 0 and address IP is specified - pub fn is_valid(&self) -> bool { - self.udp_port != 0 && self.address.port() != 0 && - match self.address { + /// Validates that the tcp port is not 0 and that the node is a valid discovery node (i.e. `is_valid_discovery_node()` is true). + /// Sync happens over tcp. + pub fn is_valid_sync_node(&self) -> bool { + self.is_valid_discovery_node() && self.address.port() != 0 + } + + /// Validates that the udp port is not 0 and address IP is specified. + /// Peer discovery happens over udp. + pub fn is_valid_discovery_node(&self) -> bool { + self.udp_port != 0 && match self.address { SocketAddr::V4(a) => !a.ip().is_unspecified(), SocketAddr::V6(a) => !a.ip().is_unspecified() } diff --git a/util/network-devp2p/src/service.rs b/util/network-devp2p/src/service.rs index e57f01066a..dfacec4be3 100644 --- a/util/network-devp2p/src/service.rs +++ b/util/network-devp2p/src/service.rs @@ -20,7 +20,7 @@ use host::Host; use io::*; use parking_lot::RwLock; use std::net::SocketAddr; -use std::ops::Range; +use std::ops::RangeInclusive; use std::sync::Arc; use ansi_term::Colour; use network::ConnectionFilter; @@ -95,12 +95,8 @@ impl NetworkService { } /// Returns the number of peers allowed. - /// - /// Keep in mind that `range.end` is *exclusive*. - pub fn num_peers_range(&self) -> Range { - let start = self.config.min_peers; - let end = self.config.max_peers + 1; - start .. end + pub fn num_peers_range(&self) -> RangeInclusive { + self.config.min_peers..=self.config.max_peers } /// Returns external url if available. diff --git a/util/network-devp2p/src/session.rs b/util/network-devp2p/src/session.rs index 6ba982bb11..6cecaf3610 100644 --- a/util/network-devp2p/src/session.rs +++ b/util/network-devp2p/src/session.rs @@ -29,6 +29,7 @@ use handshake::Handshake; use io::{IoContext, StreamToken}; use network::{Error, ErrorKind, DisconnectReason, SessionInfo, ProtocolId, PeerCapabilityInfo}; use network::SessionCapabilityInfo; +use network::client_version::ClientVersion; use host::*; use node_table::NodeId; use snappy; @@ -112,7 +113,7 @@ impl Session { had_hello: false, info: SessionInfo { id: id.cloned(), - client_version: String::new(), + client_version: ClientVersion::from(""), protocol_version: 0, capabilities: Vec::new(), peer_capabilities: Vec::new(), @@ -419,7 +420,8 @@ impl Session { fn read_hello(&mut self, io: &IoContext, rlp: &Rlp, host: &HostInfo) -> Result<(), Error> where Message: Send + Sync + Clone { let protocol = rlp.val_at::(0)?; - let client_version = rlp.val_at::(1)?; + let client_version_string = rlp.val_at::(1)?; + let client_version = ClientVersion::from(client_version_string); let peer_caps: Vec = rlp.list_at(2)?; let id = rlp.val_at::(4)?; diff --git a/util/network-devp2p/tests/tests.rs b/util/network-devp2p/tests/tests.rs index adc55b791d..00f811e463 100644 --- a/util/network-devp2p/tests/tests.rs +++ b/util/network-devp2p/tests/tests.rs @@ -80,7 +80,7 @@ impl NetworkProtocolHandler for TestProtocol { } fn connected(&self, io: &NetworkContext, peer: &PeerId) { - assert!(io.peer_client_version(*peer).contains("Parity")); + assert!(io.peer_client_version(*peer).to_string().contains("Parity")); if self.drop_session { io.disconnect_peer(*peer) } else { diff --git a/util/network/Cargo.toml b/util/network/Cargo.toml index b24249cd5d..b7077f7aea 100644 --- a/util/network/Cargo.toml +++ b/util/network/Cargo.toml @@ -8,14 +8,18 @@ authors = ["Parity Technologies "] [dependencies] error-chain = { version = "0.12", default-features = false } -parity-crypto = "0.2" +parity-crypto = "0.3.0" ethcore-io = { path = "../io" } ethereum-types = "0.4" ethkey = { path = "../../accounts/ethkey" } ipnetwork = "0.12.6" +lazy_static = "1.0" rlp = { version = "0.3.0", features = ["ethereum"] } libc = "0.2" parity-snappy = "0.1" +semver = {version="0.9.0", features=["serde"]} +serde = "1.0" +serde_derive = "1.0" [dev-dependencies] assert_matches = "1.2" diff --git a/util/network/src/client_version.rs b/util/network/src/client_version.rs new file mode 100644 index 0000000000..47d81fad86 --- /dev/null +++ b/util/network/src/client_version.rs @@ -0,0 +1,515 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +#![warn(missing_docs)] + +//! Parse ethereum client ID strings and provide querying functionality + +use semver::Version; +use std::fmt; + +/// Parity client string prefix +const LEGACY_CLIENT_ID_PREFIX: &str = "Parity"; +const PARITY_CLIENT_ID_PREFIX: &str = "Parity-Ethereum"; + +lazy_static! { +/// Parity versions starting from this will accept block bodies requests +/// of 256 bodies + static ref PARITY_CLIENT_LARGE_REQUESTS_VERSION: Version = Version::parse("2.4.0").unwrap(); +} + +/// Description of the software version running in a peer +/// according to https://github.com/ethereum/wiki/wiki/Client-Version-Strings +/// This structure as it is represents the format used by Parity clients. Other +/// vendors may provide additional fields. +#[derive(Clone,Debug,PartialEq,Eq,Serialize)] +pub struct ParityClientData { + name: String, + identity: Option, + semver: Version, + os: String, + compiler: String, + + // Capability flags, should be calculated in constructor + can_handle_large_requests: bool, +} + +/// Accessor methods for ParityClientData. This will probably +/// need to be abstracted away into a trait. +impl ParityClientData { + fn new( + name: String, + identity: Option, + semver: Version, + os: String, + compiler: String, + ) -> Self { + // Flags logic + let can_handle_large_requests = &semver >= &PARITY_CLIENT_LARGE_REQUESTS_VERSION; + + // Instantiate and return + ParityClientData { + name: name, + identity: identity, + semver: semver, + os: os, + compiler: compiler, + + can_handle_large_requests: can_handle_large_requests, + } + } + + fn name(&self) -> &str { + self.name.as_str() + } + + fn identity(&self) -> Option<&str> { + self.identity.as_ref().map(String::as_str) + } + + fn semver(&self) -> &Version { + &self.semver + } + + fn os(&self) -> &str { + self.os.as_str() + } + + fn compiler(&self) -> &str { + self.compiler.as_str() + } + + fn can_handle_large_requests(&self) -> bool { + self.can_handle_large_requests + } +} + +/// Enum describing the version of the software running on a peer. +#[derive(Clone,Debug,Eq,PartialEq,Serialize)] +pub enum ClientVersion { + /// The peer runs software from parity and the string format is known + ParityClient( + /// The actual information fields: name, version, os, ... + ParityClientData + ), + /// The string ID is recognized as Parity but the overall format + /// could not be parsed + ParityUnknownFormat(String), + /// Other software vendors than Parity + Other(String), +} + +impl Default for ClientVersion { + fn default() -> Self { + ClientVersion::Other("".to_owned()) + } +} + +/// Provide information about what a particular version of a +/// peer software can do +pub trait ClientCapabilities { + /// Parity versions before PARITY_CLIENT_LARGE_REQUESTS_VERSION would not + /// check the accumulated size of a packet when building a response to a + /// GET_BLOCK_BODIES request. If the packet was larger than a given limit, + /// instead of sending fewer blocks no packet would get sent at all. Query + /// if this version can handle requests for a large number of block bodies. + fn can_handle_large_requests(&self) -> bool; + + /// Service transactions are specific to parity. Query if this version + /// accepts them. + fn accepts_service_transaction(&self) -> bool; +} + +impl ClientCapabilities for ClientVersion { + fn can_handle_large_requests(&self) -> bool { + match self { + ClientVersion::ParityClient(data) => data.can_handle_large_requests(), + ClientVersion::ParityUnknownFormat(_) => false, // Play it safe + ClientVersion::Other(_) => true // As far as we know + } + } + + fn accepts_service_transaction(&self) -> bool { + match self { + ClientVersion::ParityClient(_) => true, + ClientVersion::ParityUnknownFormat(_) => true, + ClientVersion::Other(_) => false + } + } + +} + +fn is_parity(client_id: &str) -> bool { + client_id.starts_with(LEGACY_CLIENT_ID_PREFIX) || client_id.starts_with(PARITY_CLIENT_ID_PREFIX) +} + +/// Parse known parity formats. Recognizes either a short format with four fields +/// or a long format which includes the same fields and an identity one. +fn parse_parity_format(client_version: &str) -> Result { + const PARITY_ID_STRING_MINIMUM_TOKENS: usize = 4; + + let tokens: Vec<&str> = client_version.split("/").collect(); + + if tokens.len() < PARITY_ID_STRING_MINIMUM_TOKENS { + return Err(()) + } + + let name = tokens[0]; + + let identity = if tokens.len() - 3 > 1 { + Some(tokens[1..(tokens.len() - 3)].join("/")) + } else { + None + }; + + let compiler = tokens[tokens.len() - 1]; + let os = tokens[tokens.len() - 2]; + + // If version is in the right position and valid format return a valid + // result. Otherwise return an error. + get_number_from_version(tokens[tokens.len() - 3]) + .and_then(|v| Version::parse(v).ok()) + .map(|semver| ParityClientData::new( + name.to_owned(), + identity, + semver, + os.to_owned(), + compiler.to_owned(), + )) + .ok_or(()) +} + +/// Parse a version string and return the corresponding +/// ClientVersion. Only Parity clients are destructured right now, other +/// strings will just get wrapped in a variant so that the information is +/// not lost. +/// The parsing for parity may still fail, in which case return a ParityUnknownFormat with +/// the original version string. TryFrom would be a better trait to implement. +impl From for ClientVersion +where T: AsRef { + fn from(client_version: T) -> Self { + let client_version_str: &str = client_version.as_ref(); + + if !is_parity(client_version_str) { + return ClientVersion::Other(client_version_str.to_owned()); + } + + if let Ok(data) = parse_parity_format(client_version_str) { + ClientVersion::ParityClient(data) + } else { + ClientVersion::ParityUnknownFormat(client_version_str.to_owned()) + } + } +} + +fn format_parity_version_string(client_version: &ParityClientData, f: &mut fmt::Formatter) -> std::fmt::Result { + let name = client_version.name(); + let semver = client_version.semver(); + let os = client_version.os(); + let compiler = client_version.compiler(); + + match client_version.identity() { + None => write!(f, "{}/v{}/{}/{}", name, semver, os, compiler), + Some(identity) => write!(f, "{}/{}/v{}/{}/{}", name, identity, semver, os, compiler), + } +} + +impl fmt::Display for ClientVersion { + fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result { + match self { + ClientVersion::ParityClient(data) => format_parity_version_string(data, f), + ClientVersion::ParityUnknownFormat(id) => write!(f, "{}", id), + ClientVersion::Other(id) => write!(f, "{}", id) + } + } +} + +fn get_number_from_version(version: &str) -> Option<&str> { + if version.starts_with("v") { + return version.get(1..); + } + + None +} + +#[cfg(test)] +pub mod tests { + use super::*; + + const PARITY_CLIENT_SEMVER: &str = "2.4.0"; + const PARITY_CLIENT_OLD_SEMVER: &str = "2.2.0"; + const PARITY_CLIENT_OS: &str = "linux"; + const PARITY_CLIENT_COMPILER: &str = "rustc"; + const PARITY_CLIENT_IDENTITY: &str = "ExpanseSOLO"; + const PARITY_CLIENT_MULTITOKEN_IDENTITY: &str = "ExpanseSOLO/abc/v1.2.3"; + + + fn make_default_version_string() -> String { + format!( + "{}/v{}/{}/{}", + PARITY_CLIENT_ID_PREFIX, + PARITY_CLIENT_SEMVER, + PARITY_CLIENT_OS, + PARITY_CLIENT_COMPILER + ) + } + + fn make_default_long_version_string() -> String { + format!( + "{}/{}/v{}/{}/{}", + PARITY_CLIENT_ID_PREFIX, + PARITY_CLIENT_IDENTITY, + PARITY_CLIENT_SEMVER, + PARITY_CLIENT_OS, + PARITY_CLIENT_COMPILER + ) + } + + fn make_multitoken_identity_long_version_string() -> String { + format!( + "{}/{}/v{}/{}/{}", + PARITY_CLIENT_ID_PREFIX, + PARITY_CLIENT_MULTITOKEN_IDENTITY, + PARITY_CLIENT_SEMVER, + PARITY_CLIENT_OS, + PARITY_CLIENT_COMPILER + ) + } + + fn make_old_semver_version_string() -> String { + format!( + "{}/v{}/{}/{}", + PARITY_CLIENT_ID_PREFIX, + PARITY_CLIENT_OLD_SEMVER, + PARITY_CLIENT_OS, + PARITY_CLIENT_COMPILER + ) + } + + #[test] + pub fn client_version_when_from_empty_string_then_default() { + let default = ClientVersion::default(); + + assert_eq!(ClientVersion::from(""), default); + } + + #[test] + pub fn get_number_from_version_when_valid_then_number() { + let version_string = format!("v{}", PARITY_CLIENT_SEMVER); + + assert_eq!(get_number_from_version(&version_string).unwrap(), PARITY_CLIENT_SEMVER); + } + + #[test] + pub fn client_version_when_str_parity_format_and_valid_then_all_fields_match() { + let client_version_string = make_default_version_string(); + + if let ClientVersion::ParityClient(client_version) = ClientVersion::from(client_version_string.as_str()) { + assert_eq!(client_version.name(), PARITY_CLIENT_ID_PREFIX); + assert_eq!(*client_version.semver(), Version::parse(PARITY_CLIENT_SEMVER).unwrap()); + assert_eq!(client_version.os(), PARITY_CLIENT_OS); + assert_eq!(client_version.compiler(), PARITY_CLIENT_COMPILER); + } else { + panic!("shouldn't be here"); + } + } + + #[test] + pub fn client_version_when_str_parity_long_format_and_valid_then_all_fields_match() { + let client_version_string = make_default_long_version_string(); + + if let ClientVersion::ParityClient(client_version) = ClientVersion::from(client_version_string.as_str()) { + assert_eq!(client_version.name(), PARITY_CLIENT_ID_PREFIX); + assert_eq!(client_version.identity().unwrap(), PARITY_CLIENT_IDENTITY); + assert_eq!(*client_version.semver(), Version::parse(PARITY_CLIENT_SEMVER).unwrap()); + assert_eq!(client_version.os(), PARITY_CLIENT_OS); + assert_eq!(client_version.compiler(), PARITY_CLIENT_COMPILER); + } else { + panic!("shouldnt be here"); + } + } + + #[test] + pub fn client_version_when_str_parity_long_format_and_valid_and_identity_multiple_tokens_then_all_fields_match() { + let client_version_string = make_multitoken_identity_long_version_string(); + + if let ClientVersion::ParityClient(client_version) = ClientVersion::from(client_version_string.as_str()) { + assert_eq!(client_version.name(), PARITY_CLIENT_ID_PREFIX); + assert_eq!(client_version.identity().unwrap(), PARITY_CLIENT_MULTITOKEN_IDENTITY); + assert_eq!(*client_version.semver(), Version::parse(PARITY_CLIENT_SEMVER).unwrap()); + assert_eq!(client_version.os(), PARITY_CLIENT_OS); + assert_eq!(client_version.compiler(), PARITY_CLIENT_COMPILER); + } else { + panic!("shouldnt be here"); + } + } + + #[test] + pub fn client_version_when_string_parity_format_and_valid_then_all_fields_match() { + let client_version_string: String = make_default_version_string(); + + if let ClientVersion::ParityClient(client_version) = ClientVersion::from(client_version_string.as_str()) { + assert_eq!(client_version.name(), PARITY_CLIENT_ID_PREFIX); + assert_eq!(*client_version.semver(), Version::parse(PARITY_CLIENT_SEMVER).unwrap()); + assert_eq!(client_version.os(), PARITY_CLIENT_OS); + assert_eq!(client_version.compiler(), PARITY_CLIENT_COMPILER); + } else { + panic!("shouldn't be here"); + } + } + + #[test] + pub fn client_version_when_parity_format_and_invalid_then_equals_parity_unknown_client_version_string() { + // This is invalid because version has no leading 'v' + let client_version_string = format!( + "{}/{}/{}/{}", + PARITY_CLIENT_ID_PREFIX, + PARITY_CLIENT_SEMVER, + PARITY_CLIENT_OS, + PARITY_CLIENT_COMPILER); + + let client_version = ClientVersion::from(client_version_string.as_str()); + + let parity_unknown = ClientVersion::ParityUnknownFormat(client_version_string.to_string()); + + assert_eq!(client_version, parity_unknown); + } + + #[test] + pub fn client_version_when_parity_format_without_identity_and_missing_compiler_field_then_equals_parity_unknown_client_version_string() { + let client_version_string = format!( + "{}/v{}/{}", + PARITY_CLIENT_ID_PREFIX, + PARITY_CLIENT_SEMVER, + PARITY_CLIENT_OS, + ); + + let client_version = ClientVersion::from(client_version_string.as_str()); + + let parity_unknown = ClientVersion::ParityUnknownFormat(client_version_string.to_string()); + + assert_eq!(client_version, parity_unknown); + } + + #[test] + pub fn client_version_when_parity_format_with_identity_and_missing_compiler_field_then_equals_parity_unknown_client_version_string() { + let client_version_string = format!( + "{}/{}/v{}/{}", + PARITY_CLIENT_ID_PREFIX, + PARITY_CLIENT_IDENTITY, + PARITY_CLIENT_SEMVER, + PARITY_CLIENT_OS, + ); + + let client_version = ClientVersion::from(client_version_string.as_str()); + + let parity_unknown = ClientVersion::ParityUnknownFormat(client_version_string.to_string()); + + assert_eq!(client_version, parity_unknown); + } + + #[test] + pub fn client_version_when_not_parity_format_and_valid_then_other_with_client_version_string() { + let client_version_string = "Geth/main.jnode.network/v1.8.21-stable-9dc5d1a9/linux"; + + let client_version = ClientVersion::from(client_version_string); + + assert_eq!(client_version, ClientVersion::Other(client_version_string.to_string())); + } + + #[test] + pub fn client_version_when_parity_format_and_valid_then_to_string_equal() { + let client_version_string: String = make_default_version_string(); + + let client_version = ClientVersion::from(client_version_string.as_str()); + + assert_eq!(client_version.to_string(), client_version_string); + } + + #[test] + pub fn client_version_when_other_then_to_string_equal_input_string() { + let client_version_string: String = "Other".to_string(); + + let client_version = ClientVersion::from("Other"); + + assert_eq!(client_version.to_string(), client_version_string); + } + + #[test] + pub fn client_capabilities_when_parity_old_version_then_handles_large_requests_false() { + let client_version_string: String = make_old_semver_version_string(); + + let client_version = ClientVersion::from(client_version_string.as_str()); + + assert!(!client_version.can_handle_large_requests()); + } + + #[test] + pub fn client_capabilities_when_parity_beta_version_then_not_handles_large_requests_true() { + let client_version_string: String = format!( + "{}/v{}/{}/{}", + "Parity-Ethereum", + "2.4.0-beta", + "x86_64-linux-gnu", + "rustc1.31.1") + .to_string(); + + let client_version = ClientVersion::from(client_version_string.as_str()); + + assert!(!client_version.can_handle_large_requests()); + } + + #[test] + pub fn client_version_when_to_owned_then_both_objects_equal() { + let client_version_string: String = make_old_semver_version_string(); + + let origin = ClientVersion::from(client_version_string.as_str()); + + let borrowed = &origin; + + let owned = origin.to_owned(); + + assert_eq!(*borrowed, owned); + } + + #[test] + fn client_version_accepts_service_transaction_for_different_versions() { + assert!(!ClientVersion::from("Geth").accepts_service_transaction()); + assert!(ClientVersion::from("Parity-Ethereum/v2.6.0/linux/rustc").accepts_service_transaction()); + assert!(ClientVersion::from("Parity-Ethereum/ABCDEFGH/v2.7.3/linux/rustc").accepts_service_transaction()); + } + + #[test] + fn is_parity_when_parity_then_true() { + let client_id = format!("{}/", PARITY_CLIENT_ID_PREFIX); + + assert!(is_parity(&client_id)); + } + + #[test] + fn is_parity_when_empty_then_false() { + let client_id = ""; + + assert!(!is_parity(&client_id)); + } + + #[test] + fn is_parity_when_other_then_false() { + let client_id = "other"; + + assert!(!is_parity(&client_id)); + } +} diff --git a/util/network/src/error.rs b/util/network/src/error.rs index bce6be8919..bd48830c1b 100644 --- a/util/network/src/error.rs +++ b/util/network/src/error.rs @@ -14,6 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +// Silence: `use of deprecated item 'std::error::Error::cause': replaced by Error::source, which can support downcasting` +// https://github.com/paritytech/parity-ethereum/issues/10302 +#![allow(deprecated)] + use std::{io, net, fmt}; use libc::{ENFILE, EMFILE}; use io::IoError; diff --git a/util/network/src/lib.rs b/util/network/src/lib.rs index dd7c5c073d..9e6f71fdd1 100644 --- a/util/network/src/lib.rs +++ b/util/network/src/lib.rs @@ -24,6 +24,11 @@ extern crate rlp; extern crate ipnetwork; extern crate parity_snappy as snappy; extern crate libc; +extern crate semver; +extern crate serde; + +#[macro_use] +extern crate serde_derive; #[cfg(test)] #[macro_use] extern crate assert_matches; @@ -31,6 +36,11 @@ extern crate assert_matches; #[macro_use] extern crate error_chain; +#[macro_use] +extern crate lazy_static; + +pub mod client_version; + mod connection_filter; mod error; @@ -38,6 +48,7 @@ pub use connection_filter::{ConnectionFilter, ConnectionDirection}; pub use io::TimerToken; pub use error::{Error, ErrorKind, DisconnectReason}; +use client_version::ClientVersion; use std::cmp::Ordering; use std::collections::HashMap; use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr}; @@ -97,7 +108,7 @@ pub struct SessionInfo { /// Peer public key pub id: Option, /// Peer client ID - pub client_version: String, + pub client_version: ClientVersion, /// Peer RLPx protocol version pub protocol_version: u32, /// Session protocol capabilities @@ -275,7 +286,7 @@ pub trait NetworkContext { fn register_timer(&self, token: TimerToken, delay: Duration) -> Result<(), Error>; /// Returns peer identification string - fn peer_client_version(&self, peer: PeerId) -> String; + fn peer_client_version(&self, peer: PeerId) -> ClientVersion; /// Returns information on p2p session fn session_info(&self, peer: PeerId) -> Option; @@ -322,7 +333,7 @@ impl<'a, T> NetworkContext for &'a T where T: ?Sized + NetworkContext { (**self).register_timer(token, delay) } - fn peer_client_version(&self, peer: PeerId) -> String { + fn peer_client_version(&self, peer: PeerId) -> ClientVersion { (**self).peer_client_version(peer) } diff --git a/util/panic-hook/src/lib.rs b/util/panic-hook/src/lib.rs index f49fea67b8..03501a47fd 100644 --- a/util/panic-hook/src/lib.rs +++ b/util/panic-hook/src/lib.rs @@ -18,7 +18,6 @@ extern crate backtrace; -use std::io::{self, Write}; use std::panic::{self, PanicInfo}; use std::thread; use std::process; @@ -27,7 +26,7 @@ use backtrace::Backtrace; /// Set the panic hook to write to stderr and abort the process when a panic happens. pub fn set_abort() { set_with(|msg| { - let _ = io::stderr().write_all(msg.as_bytes()); + eprintln!("{}", msg); process::abort() }); } diff --git a/util/patricia-trie-ethereum/Cargo.toml b/util/patricia-trie-ethereum/Cargo.toml index e6880691a1..8cb8664a5e 100644 --- a/util/patricia-trie-ethereum/Cargo.toml +++ b/util/patricia-trie-ethereum/Cargo.toml @@ -6,14 +6,15 @@ description = "Merkle-Patricia Trie (Ethereum Style)" license = "GPL-3.0" [dependencies] -patricia-trie = "0.3.0" +trie-db = "0.11.0" keccak-hasher = { version = "0.1.1", path = "../keccak-hasher" } -hashdb = "0.3.0" +hash-db = "0.11.0" rlp = "0.3.0" parity-bytes = "0.1" ethereum-types = "0.4" elastic-array = "0.10" [dev-dependencies] -memorydb = "0.3.0" +memory-db = "0.11.0" keccak-hash = "0.1.2" +journaldb = { path = "../journaldb" } diff --git a/util/patricia-trie-ethereum/src/lib.rs b/util/patricia-trie-ethereum/src/lib.rs index 7b48257662..ab44f4e837 100644 --- a/util/patricia-trie-ethereum/src/lib.rs +++ b/util/patricia-trie-ethereum/src/lib.rs @@ -16,11 +16,11 @@ //! Façade crate for `patricia_trie` for Ethereum specific impls -pub extern crate patricia_trie as trie; // `pub` because we need to import this crate for the tests in `patricia_trie` and there were issues: https://gist.github.com/dvdplm/869251ee557a1b4bd53adc7c971979aa +pub extern crate trie_db as trie; // `pub` because we need to import this crate for the tests in `patricia_trie` and there were issues: https://gist.github.com/dvdplm/869251ee557a1b4bd53adc7c971979aa extern crate elastic_array; extern crate parity_bytes; extern crate ethereum_types; -extern crate hashdb; +extern crate hash_db; extern crate keccak_hasher; extern crate rlp; @@ -42,18 +42,19 @@ pub type RlpCodec = RlpNodeCodec; /// /// # Example /// ``` -/// extern crate patricia_trie as trie; +/// extern crate trie_db as trie; /// extern crate patricia_trie_ethereum as ethtrie; -/// extern crate hashdb; +/// extern crate hash_db; /// extern crate keccak_hasher; -/// extern crate memorydb; +/// extern crate memory_db; /// extern crate ethereum_types; /// extern crate elastic_array; +/// extern crate journaldb; /// /// use trie::*; -/// use hashdb::*; +/// use hash_db::*; /// use keccak_hasher::KeccakHasher; -/// use memorydb::*; +/// use memory_db::*; /// use ethereum_types::H256; /// use ethtrie::{TrieDB, TrieDBMut}; /// use elastic_array::ElasticArray128; @@ -61,7 +62,7 @@ pub type RlpCodec = RlpNodeCodec; /// type DBValue = ElasticArray128; /// /// fn main() { -/// let mut memdb = MemoryDB::::new(); +/// let mut memdb = journaldb::new_memory_db(); /// let mut root = H256::new(); /// TrieDBMut::new(&mut memdb, &mut root).insert(b"foo", b"bar").unwrap(); /// let t = TrieDB::new(&memdb, &root).unwrap(); @@ -85,26 +86,27 @@ pub type FatDB<'db> = trie::FatDB<'db, KeccakHasher, RlpCodec>; /// # Example /// ``` -/// extern crate patricia_trie as trie; +/// extern crate trie_db as trie; /// extern crate patricia_trie_ethereum as ethtrie; -/// extern crate hashdb; +/// extern crate hash_db; /// extern crate keccak_hash; /// extern crate keccak_hasher; -/// extern crate memorydb; +/// extern crate memory_db; /// extern crate ethereum_types; /// extern crate elastic_array; +/// extern crate journaldb; /// /// use keccak_hash::KECCAK_NULL_RLP; /// use ethtrie::{TrieDBMut, trie::TrieMut}; /// use keccak_hasher::KeccakHasher; -/// use memorydb::*; +/// use memory_db::*; /// use ethereum_types::H256; /// use elastic_array::ElasticArray128; /// /// type DBValue = ElasticArray128; /// /// fn main() { -/// let mut memdb = MemoryDB::::new(); +/// let mut memdb = journaldb::new_memory_db(); /// let mut root = H256::new(); /// let mut t = TrieDBMut::new(&mut memdb, &mut root); /// assert!(t.is_empty()); diff --git a/util/patricia-trie-ethereum/src/rlp_node_codec.rs b/util/patricia-trie-ethereum/src/rlp_node_codec.rs index e9d1d74586..ea8aea8a77 100644 --- a/util/patricia-trie-ethereum/src/rlp_node_codec.rs +++ b/util/patricia-trie-ethereum/src/rlp_node_codec.rs @@ -18,7 +18,7 @@ use elastic_array::ElasticArray128; use ethereum_types::H256; -use hashdb::Hasher; +use hash_db::Hasher; use keccak_hasher::KeccakHasher; use rlp::{DecoderError, RlpStream, Rlp, Prototype}; use std::marker::PhantomData; @@ -28,13 +28,17 @@ use trie::{NibbleSlice, NodeCodec, node::Node, ChildReference}; #[derive(Default, Clone)] pub struct RlpNodeCodec {mark: PhantomData} +const HASHED_NULL_NODE_BYTES : [u8;32] = [0x56, 0xe8, 0x1f, 0x17, 0x1b, 0xcc, 0x55, 0xa6, 0xff, 0x83, 0x45, 0xe6, 0x92, 0xc0, 0xf8, 0x6e, 0x5b, 0x48, 0xe0, 0x1b, 0x99, 0x6c, 0xad, 0xc0, 0x01, 0x62, 0x2f, 0xb5, 0xe3, 0x63, 0xb4, 0x21]; +const HASHED_NULL_NODE : H256 = H256( HASHED_NULL_NODE_BYTES ); // NOTE: what we'd really like here is: // `impl NodeCodec for RlpNodeCodec where H::Out: Decodable` // but due to the current limitations of Rust const evaluation we can't // do `const HASHED_NULL_NODE: H::Out = H::Out( … … )`. Perhaps one day soon? impl NodeCodec for RlpNodeCodec { type Error = DecoderError; - const HASHED_NULL_NODE : H256 = H256( [0x56, 0xe8, 0x1f, 0x17, 0x1b, 0xcc, 0x55, 0xa6, 0xff, 0x83, 0x45, 0xe6, 0x92, 0xc0, 0xf8, 0x6e, 0x5b, 0x48, 0xe0, 0x1b, 0x99, 0x6c, 0xad, 0xc0, 0x01, 0x62, 0x2f, 0xb5, 0xe3, 0x63, 0xb4, 0x21] ); + fn hashed_null_node() -> ::Out { + HASHED_NULL_NODE + } fn decode(data: &[u8]) -> ::std::result::Result { let r = Rlp::new(data); match r.prototype()? { @@ -49,9 +53,14 @@ impl NodeCodec for RlpNodeCodec { }, // branch - first 16 are nodes, 17th is a value (or empty). Prototype::List(17) => { - let mut nodes = [&[] as &[u8]; 16]; + let mut nodes = [None as Option<&[u8]>; 16]; for i in 0..16 { - nodes[i] = r.at(i)?.as_raw(); + let v = r.at(i)?; + if v.is_empty() { + nodes[i] = None; + } else { + nodes[i] = Some(v.as_raw()); + } } Ok(Node::Branch(nodes, if r.at(16)?.is_empty() { None } else { Some(r.at(16)?.data()?) })) }, @@ -72,54 +81,54 @@ impl NodeCodec for RlpNodeCodec { fn is_empty_node(data: &[u8]) -> bool { Rlp::new(data).is_empty() } - fn empty_node() -> Vec { - let mut stream = RlpStream::new(); - stream.append_empty_data(); - stream.drain() - } + fn empty_node() -> Vec { + let mut stream = RlpStream::new(); + stream.append_empty_data(); + stream.drain() + } - fn leaf_node(partial: &[u8], value: &[u8]) -> Vec { - let mut stream = RlpStream::new_list(2); - stream.append(&partial); - stream.append(&value); + fn leaf_node(partial: &[u8], value: &[u8]) -> Vec { + let mut stream = RlpStream::new_list(2); + stream.append(&partial); + stream.append(&value); stream.drain() - } + } fn ext_node(partial: &[u8], child_ref: ChildReference<::Out>) -> Vec { - let mut stream = RlpStream::new_list(2); - stream.append(&partial); - match child_ref { - ChildReference::Hash(h) => stream.append(&h), - ChildReference::Inline(inline_data, len) => { - let bytes = &AsRef::<[u8]>::as_ref(&inline_data)[..len]; - stream.append_raw(bytes, 1) - }, - }; - stream.drain() + let mut stream = RlpStream::new_list(2); + stream.append(&partial); + match child_ref { + ChildReference::Hash(h) => stream.append(&h), + ChildReference::Inline(inline_data, len) => { + let bytes = &AsRef::<[u8]>::as_ref(&inline_data)[..len]; + stream.append_raw(bytes, 1) + }, + }; + stream.drain() } // fn branch_node(children: I, value: Option>) -> Vec fn branch_node(children: I, value: Option>) -> Vec where I: IntoIterator::Out>>> - { - let mut stream = RlpStream::new_list(17); - for child_ref in children { - match child_ref { - Some(c) => match c { - ChildReference::Hash(h) => stream.append(&h), - ChildReference::Inline(inline_data, len) => { - let bytes = &AsRef::<[u8]>::as_ref(&inline_data)[..len]; - stream.append_raw(bytes, 1) - }, - }, - None => stream.append_empty_data() - }; - } - if let Some(value) = value { - stream.append(&&*value); - } else { - stream.append_empty_data(); - } - stream.drain() - } + { + let mut stream = RlpStream::new_list(17); + for child_ref in children { + match child_ref { + Some(c) => match c { + ChildReference::Hash(h) => stream.append(&h), + ChildReference::Inline(inline_data, len) => { + let bytes = &AsRef::<[u8]>::as_ref(&inline_data)[..len]; + stream.append_raw(bytes, 1) + }, + }, + None => stream.append_empty_data() + }; + } + if let Some(value) = value { + stream.append(&&*value); + } else { + stream.append_empty_data(); + } + stream.drain() + } } diff --git a/util/rlp-compress/src/common.rs b/util/rlp-compress/src/common.rs index 79f8a93c1f..81767955b6 100644 --- a/util/rlp-compress/src/common.rs +++ b/util/rlp-compress/src/common.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2017 Parity Technologies +// Copyright 2015-2019 Parity Technologies (UK) Ltd. // // Licensed under the Apache License, Version 2.0 or the MIT license diff --git a/util/rlp-compress/src/lib.rs b/util/rlp-compress/src/lib.rs index 38dabcd86b..48620ed239 100644 --- a/util/rlp-compress/src/lib.rs +++ b/util/rlp-compress/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 Parity Technologies +// Copyright 2015-2019 Parity Technologies (UK) Ltd. // // Licensed under the Apache License, Version 2.0 or the MIT license diff --git a/util/time-utils/Cargo.toml b/util/time-utils/Cargo.toml new file mode 100644 index 0000000000..38e7dd02c6 --- /dev/null +++ b/util/time-utils/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "time-utils" +version = "0.1.0" +authors = ["Parity Technologies "] +description = "Time utilities for checked arithmetic" +license = "GPL3" +edition = "2018" + +[dependencies] diff --git a/util/time-utils/src/lib.rs b/util/time-utils/src/lib.rs new file mode 100644 index 0000000000..0bfc3bb982 --- /dev/null +++ b/util/time-utils/src/lib.rs @@ -0,0 +1,66 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . + +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +/// Temporary trait for `checked operations` on SystemTime until these are available in the standard library +pub trait CheckedSystemTime { + /// Returns `Some` when the result less or equal to `i32::max_value` to prevent `SystemTime` to panic because + /// it is platform specific, possible representations are i32, i64, u64 or Duration. `None` otherwise + fn checked_add(self, _d: Duration) -> Option; + /// Returns `Some` when the result is successful and `None` when it is not + fn checked_sub(self, _d: Duration) -> Option; +} + +impl CheckedSystemTime for SystemTime { + fn checked_add(self, dur: Duration) -> Option { + let this_dur = self.duration_since(UNIX_EPOCH).ok()?; + let total_time = this_dur.checked_add(dur)?; + + if total_time.as_secs() <= i32::max_value() as u64 { + Some(self + dur) + } else { + None + } + } + + fn checked_sub(self, dur: Duration) -> Option { + let this_dur = self.duration_since(UNIX_EPOCH).ok()?; + let total_time = this_dur.checked_sub(dur)?; + + if total_time.as_secs() <= i32::max_value() as u64 { + Some(self - dur) + } else { + None + } + } +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + use super::CheckedSystemTime; + use std::time::{Duration, SystemTime, UNIX_EPOCH}; + + assert!(CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64 + 1, 0)).is_none()); + assert!(CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64, 0)).is_some()); + assert!(CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64 - 1, 1_000_000_000)).is_some()); + + assert!(CheckedSystemTime::checked_sub(UNIX_EPOCH, Duration::from_secs(120)).is_none()); + assert!(CheckedSystemTime::checked_sub(SystemTime::now(), Duration::from_secs(1000)).is_some()); + } +} diff --git a/util/triehash-ethereum/Cargo.toml b/util/triehash-ethereum/Cargo.toml index e46d5d6907..5b63642975 100644 --- a/util/triehash-ethereum/Cargo.toml +++ b/util/triehash-ethereum/Cargo.toml @@ -6,6 +6,6 @@ description = "Trie-root helpers, ethereum style" license = "GPL-3.0" [dependencies] -triehash = { version = "0.3.0", features = ["ethereum"] } +triehash = { version = "0.4.0", features = ["ethereum"] } ethereum-types = "0.4" keccak-hasher = { path = "../keccak-hasher" } diff --git a/util/version/Cargo.toml b/util/version/Cargo.toml index 32ee228c5c..b824894bfb 100644 --- a/util/version/Cargo.toml +++ b/util/version/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "parity-version" # NOTE: this value is used for Parity Ethereum version string (via env CARGO_PKG_VERSION) -version = "2.3.5" +version = "2.5.9" authors = ["Parity Technologies "] build = "build.rs" @@ -19,6 +19,7 @@ track = "stable" foundation = { forkBlock = 7280000, critical = false } ropsten = { forkBlock = 4939394, critical = false } kovan = { forkBlock = 10255201, critical = false } +goerli = { forkBlock = 0, critical = false } [dependencies] parity-bytes = "0.1" diff --git a/whisper/Cargo.toml b/whisper/Cargo.toml index fec601586b..bc29051b23 100644 --- a/whisper/Cargo.toml +++ b/whisper/Cargo.toml @@ -1,15 +1,15 @@ [package] +description = "Parity Ethereum Whisper Protocol Implementation" name = "parity-whisper" version = "0.1.0" authors = ["Parity Technologies "] -description = "Whisper Protocol implementation for Parity" [dependencies] bitflags = "0.9" byteorder = "1.0.0" ethereum-types = "0.4" ethcore-network = { path = "../util/network" } -parity-crypto = "0.2" +parity-crypto = "0.3.0" ethkey = { path = "../accounts/ethkey" } hex = "0.2" log = "0.4" @@ -24,7 +24,8 @@ serde_json = "1.0" slab = "0.3" smallvec = "0.6" tiny-keccak = "1.4" +time-utils = { path = "../util/time-utils" } -jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } -jsonrpc-macros = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } -jsonrpc-pubsub = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } +jsonrpc-core = "10.0.1" +jsonrpc-derive = "10.0.2" +jsonrpc-pubsub = "10.0.1" diff --git a/whisper/README.md b/whisper/README.md index 8dafc48af7..b64c0244f9 100644 --- a/whisper/README.md +++ b/whisper/README.md @@ -6,7 +6,7 @@ Implementation of Whisper based on the Whisper-v2 PoC. ``` Parity Whisper-v2 CLI. - Copyright 2015-2018 Parity Technologies (UK) Ltd. + Copyright 2015-2019 Parity Technologies (UK) Ltd. Usage: whisper [options] @@ -14,8 +14,11 @@ Usage: Options: --whisper-pool-size SIZE Specify Whisper pool size [default: 10]. - -p, --port PORT Specify which RPC port to use [default: 8545]. - -a, --address ADDRESS Specify which address to use [default: 127.0.0.1]. + -p, --port PORT Specify which P2P port to use [default: random]. + -a, --address ADDRESS Specify which P2P address to use [default: 127.0.0.1]. + -s, --secret KEYFILE Specify which file contains the key to generate the enode. + -P, --rpc-port PORT Specify which RPC port to use [default: 8545]. + -A, --rpc-address ADDRESS Specify which RPC address to use [default: 127.0.0.1]. -l, --log LEVEL Specify the logging level. Must conform to the same format as RUST_LOG [default: Error]. -h, --help Display this message and exit. ``` diff --git a/whisper/cli/Cargo.toml b/whisper/cli/Cargo.toml index 5147a6b563..5ed38e47d7 100644 --- a/whisper/cli/Cargo.toml +++ b/whisper/cli/Cargo.toml @@ -10,14 +10,16 @@ docopt = "1.0" env_logger = "0.5" ethcore-network = { path = "../../util/network" } ethcore-network-devp2p = { path = "../../util/network-devp2p" } -jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } -jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } -jsonrpc-pubsub = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" } +jsonrpc-core = "10.0.1" +jsonrpc-http-server = "10.0.1" +jsonrpc-pubsub = "10.0.1" log = "0.4" panic_hook = { path = "../../util/panic-hook" } parity-whisper = { path = "../" } serde = "1.0" serde_derive = "1.0" +ethkey = { path = "../../accounts/ethkey" } +rustc-hex = "2.0" [[bin]] name = "whisper" diff --git a/whisper/cli/src/main.rs b/whisper/cli/src/main.rs index f671b4a248..41d9e80e42 100644 --- a/whisper/cli/src/main.rs +++ b/whisper/cli/src/main.rs @@ -33,6 +33,8 @@ extern crate serde; extern crate jsonrpc_core; extern crate jsonrpc_pubsub; extern crate jsonrpc_http_server; +extern crate ethkey; +extern crate rustc_hex; #[macro_use] extern crate log as rlog; @@ -45,11 +47,15 @@ use std::{fmt, io, process, env, sync::Arc}; use jsonrpc_core::{Metadata, MetaIoHandler}; use jsonrpc_pubsub::{PubSubMetadata, Session}; use jsonrpc_http_server::{AccessControlAllowOrigin, DomainsValidation}; +use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr}; +use std::str::FromStr; +use ethkey::Secret; +use rustc_hex::FromHex; const POOL_UNIT: usize = 1024 * 1024; const USAGE: &'static str = r#" Parity Whisper-v2 CLI. - Copyright 2015-2018 Parity Technologies (UK) Ltd. + Copyright 2015-2019 Parity Technologies (UK) Ltd. Usage: whisper [options] @@ -57,8 +63,11 @@ Usage: Options: --whisper-pool-size SIZE Specify Whisper pool size [default: 10]. - -p, --port PORT Specify which RPC port to use [default: 8545]. - -a, --address ADDRESS Specify which address to use [default: 127.0.0.1]. + -p, --port PORT Specify which P2P port to use [default: random]. + -a, --address ADDRESS Specify which P2P address to use [default: 127.0.0.1]. + -s, --secret KEYFILE Specify which file contains the key to generate the enode. + -P, --rpc-port PORT Specify which RPC port to use [default: 8545]. + -A, --rpc-address ADDRESS Specify which RPC address to use [default: 127.0.0.1]. -l, --log LEVEL Specify the logging level. Must conform to the same format as RUST_LOG [default: Error]. -h, --help Display this message and exit. "#; @@ -79,7 +88,10 @@ struct Args { flag_whisper_pool_size: usize, flag_port: String, flag_address: String, + flag_rpc_port: String, + flag_rpc_address: String, flag_log: String, + flag_secret: String, } struct WhisperPoolHandle { @@ -131,6 +143,8 @@ enum Error { JsonRpc(jsonrpc_core::Error), Network(net::Error), SockAddr(std::net::AddrParseError), + FromHex(rustc_hex::FromHexError), + ParseInt(std::num::ParseIntError), } impl From for Error { @@ -163,6 +177,18 @@ impl From for Error { } } +impl From for Error { + fn from(err: rustc_hex::FromHexError) -> Self { + Error::FromHex(err) + } +} + +impl From for Error { + fn from(err: std::num::ParseIntError) -> Self { + Error::ParseInt(err) + } +} + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { @@ -171,6 +197,8 @@ impl fmt::Display for Error { Error::Io(ref e) => write!(f, "{}", e), Error::JsonRpc(ref e) => write!(f, "{:?}", e), Error::Network(ref e) => write!(f, "{}", e), + Error::ParseInt(ref e) => write!(f, "Invalid port: {}", e), + Error::FromHex(ref e) => write!(f, "Error deciphering key: {}", e), } } } @@ -196,7 +224,7 @@ fn execute(command: I) -> Result<(), Error> where I: IntoIterator, // Parse arguments let args: Args = Docopt::new(USAGE).and_then(|d| d.argv(command).deserialize())?; let pool_size = args.flag_whisper_pool_size * POOL_UNIT; - let url = format!("{}:{}", args.flag_address, args.flag_port); + let rpc_url = format!("{}:{}", args.flag_rpc_address, args.flag_rpc_port); initialize_logger(args.flag_log); info!(target: "whisper-cli", "start"); @@ -207,8 +235,29 @@ fn execute(command: I) -> Result<(), Error> where I: IntoIterator, // Whisper protocol network handler let whisper_network_handler = Arc::new(whisper::net::Network::new(pool_size, manager.clone())); + let network_config = { + let mut cfg = net::NetworkConfiguration::new(); + let port = match args.flag_port.as_str() { + "random" => 0 as u16, + port => port.parse::()?, + + }; + let addr = Ipv4Addr::from_str(&args.flag_address[..])?; + cfg.listen_address = Some(SocketAddr::V4(SocketAddrV4::new(addr, port))); + cfg.use_secret = match args.flag_secret.as_str() { + "" => None, + fname => { + let key_text = std::fs::read_to_string(fname)?; + let key : Vec = FromHex::from_hex(key_text.as_str())?; + Secret::from_slice(key.as_slice()) + } + }; + cfg.nat_enabled = false; + cfg + }; + // Create network service - let network = devp2p::NetworkService::new(net::NetworkConfiguration::new_local(), None)?; + let network = devp2p::NetworkService::new(network_config, None)?; // Start network service network.start().map_err(|(err, _)| err)?; @@ -233,7 +282,7 @@ fn execute(command: I) -> Result<(), Error> where I: IntoIterator, let server = jsonrpc_http_server::ServerBuilder::new(io) .cors(DomainsValidation::AllowOnly(vec![AccessControlAllowOrigin::Null])) - .start_http(&url.parse()?)?; + .start_http(&rpc_url.parse()?)?; server.wait(); diff --git a/whisper/src/lib.rs b/whisper/src/lib.rs index 2db7108f76..cdc88780d4 100644 --- a/whisper/src/lib.rs +++ b/whisper/src/lib.rs @@ -17,6 +17,8 @@ //! Whisper P2P messaging system as a DevP2P subprotocol, with RPC and Rust //! interface. +#![cfg_attr(feature = "time_checked_add", feature(time_checked_add))] + extern crate byteorder; extern crate parity_crypto as crypto; extern crate ethcore_network as network; @@ -34,6 +36,7 @@ extern crate smallvec; extern crate tiny_keccak; extern crate jsonrpc_core; +extern crate jsonrpc_derive; extern crate jsonrpc_pubsub; #[macro_use] @@ -42,12 +45,12 @@ extern crate bitflags; #[macro_use] extern crate log; -#[macro_use] -extern crate jsonrpc_macros; - #[macro_use] extern crate serde_derive; +#[cfg(not(time_checked_add))] +extern crate time_utils; + #[cfg(test)] extern crate serde_json; diff --git a/whisper/src/message.rs b/whisper/src/message.rs index 14a6fcf9ce..c10d39700f 100644 --- a/whisper/src/message.rs +++ b/whisper/src/message.rs @@ -24,6 +24,9 @@ use rlp::{self, DecoderError, RlpStream, Rlp}; use smallvec::SmallVec; use tiny_keccak::{keccak256, Keccak}; +#[cfg(not(time_checked_add))] +use time_utils::CheckedSystemTime; + /// Work-factor proved. Takes 3 parameters: size of message, time to live, /// and hash. /// @@ -32,12 +35,13 @@ pub fn work_factor_proved(size: u64, ttl: u64, hash: H256) -> f64 { assert!(size != 0 && ttl != 0); let leading_zeros = { - let leading_zeros = hash.iter().take_while(|&&x| x == 0).count(); - (leading_zeros * 8) + hash.get(leading_zeros + 1).map_or(0, |b| b.leading_zeros() as usize) + let leading_bytes = hash.iter().take_while(|&&x| x == 0).count(); + let remaining_leading_bits = hash.get(leading_bytes).map_or(0, |byte| byte.leading_zeros() as usize); + (leading_bytes * 8) + remaining_leading_bits }; let spacetime = size as f64 * ttl as f64; - (1u64 << leading_zeros) as f64 / spacetime + 2.0_f64.powi(leading_zeros as i32) / spacetime } /// A topic of a message. @@ -116,6 +120,7 @@ pub enum Error { EmptyTopics, LivesTooLong, IssuedInFuture, + TimestampOverflow, ZeroTTL, } @@ -132,6 +137,7 @@ impl fmt::Display for Error { Error::LivesTooLong => write!(f, "Message claims to be issued before the unix epoch."), Error::IssuedInFuture => write!(f, "Message issued in future."), Error::ZeroTTL => write!(f, "Message live for zero time."), + Error::TimestampOverflow => write!(f, "Timestamp overflow"), Error::EmptyTopics => write!(f, "Message has no topics."), } } @@ -225,10 +231,6 @@ impl rlp::Decodable for Envelope { } } -/// Error indicating no topics. -#[derive(Debug, Copy, Clone)] -pub struct EmptyTopics; - /// Message creation parameters. /// Pass this to `Message::create` to make a message. pub struct CreateParams { @@ -254,24 +256,25 @@ pub struct Message { impl Message { /// Create a message from creation parameters. /// Panics if TTL is 0. - pub fn create(params: CreateParams) -> Result { + pub fn create(params: CreateParams) -> Result { use byteorder::{BigEndian, ByteOrder}; use rand::{Rng, SeedableRng, XorShiftRng}; - if params.topics.is_empty() { return Err(EmptyTopics) } + if params.topics.is_empty() { return Err(Error::EmptyTopics) } let mut rng = { let mut thread_rng = ::rand::thread_rng(); - XorShiftRng::from_seed(thread_rng.gen::<[u32; 4]>()) }; assert!(params.ttl > 0); let expiry = { - let after_mining = SystemTime::now() + Duration::from_millis(params.work); - let since_epoch = after_mining.duration_since(time::UNIX_EPOCH) - .expect("time after now is after unix epoch; qed"); + let since_epoch = SystemTime::now() + .checked_add(Duration::from_secs(params.ttl)) + .and_then(|t| t.checked_add(Duration::from_millis(params.work))) + .ok_or(Error::TimestampOverflow)? + .duration_since(time::UNIX_EPOCH).expect("time after now is after unix epoch; qed"); // round up the sub-second to next whole second. since_epoch.as_secs() + if since_epoch.subsec_nanos() == 0 { 0 } else { 1 } @@ -356,7 +359,10 @@ impl Message { (envelope.expiry - envelope.ttl).saturating_sub(LEEWAY_SECONDS) ); - if time::UNIX_EPOCH + issue_time_adjusted > now { + let issue_time_adjusted = time::UNIX_EPOCH.checked_add(issue_time_adjusted) + .ok_or(Error::TimestampOverflow)?; + + if issue_time_adjusted > now { return Err(Error::IssuedInFuture); } @@ -399,8 +405,8 @@ impl Message { } /// Get the expiry time. - pub fn expiry(&self) -> SystemTime { - time::UNIX_EPOCH + Duration::from_secs(self.envelope.expiry) + pub fn expiry(&self) -> Option { + time::UNIX_EPOCH.checked_add(Duration::from_secs(self.envelope.expiry)) } /// Get the topics. @@ -416,6 +422,7 @@ impl Message { #[cfg(test)] mod tests { + use ethereum_types::H256; use super::*; use std::time::{self, Duration, SystemTime}; use rlp::Rlp; @@ -518,4 +525,14 @@ mod tests { let now = unix_time(95_000); Message::decode(Rlp::new(&*encoded), now).unwrap(); } + + #[test] + fn work_factor() { + // 256 leading zeros -> 2^256 / 1 + assert_eq!(work_factor_proved(1, 1, H256::from(0)), 115792089237316200000000000000000000000000000000000000000000000000000000000000.0); + // 255 leading zeros -> 2^255 / 1 + assert_eq!(work_factor_proved(1, 1, H256::from(1)), 57896044618658100000000000000000000000000000000000000000000000000000000000000.0); + // 0 leading zeros -> 2^0 / 1 + assert_eq!(work_factor_proved(1, 1, serde_json::from_str::("\"0xff00000000000000000000000000000000000000000000000000000000000000\"").unwrap()), 1.0); + } } diff --git a/whisper/src/net/mod.rs b/whisper/src/net/mod.rs index 64431d1426..d263f6cfbd 100644 --- a/whisper/src/net/mod.rs +++ b/whisper/src/net/mod.rs @@ -223,7 +223,10 @@ impl Messages { } } - let expiry = message.expiry(); + let expiry = match message.expiry() { + Some(time) => time, + _ => return false, + }; self.cumulative_size += message.encoded_size(); @@ -232,8 +235,8 @@ impl Messages { let sorted_entry = SortedEntry { slab_id: id, - work_proved: work_proved, - expiry: expiry, + work_proved, + expiry, }; match self.sorted.binary_search(&sorted_entry) { diff --git a/whisper/src/rpc/filter.rs b/whisper/src/rpc/filter.rs index 9c091de0b9..46cefd61e0 100644 --- a/whisper/src/rpc/filter.rs +++ b/whisper/src/rpc/filter.rs @@ -21,7 +21,7 @@ use std::{sync::{Arc, atomic, atomic::AtomicBool, mpsc}, thread}; use ethereum_types::{H256, H512}; use ethkey::Public; -use jsonrpc_macros::pubsub::{Subscriber, Sink}; +use jsonrpc_pubsub::typed::{Subscriber, Sink}; use parking_lot::{Mutex, RwLock}; use rand::{Rng, OsRng}; diff --git a/whisper/src/rpc/mod.rs b/whisper/src/rpc/mod.rs index c3958f77f7..03d98b51ff 100644 --- a/whisper/src/rpc/mod.rs +++ b/whisper/src/rpc/mod.rs @@ -24,8 +24,8 @@ use std::sync::Arc; use jsonrpc_core::{Error, ErrorCode, Metadata}; -use jsonrpc_pubsub::{Session, PubSubMetadata, SubscriptionId}; -use jsonrpc_macros::pubsub; +use jsonrpc_derive::rpc; +use jsonrpc_pubsub::{Session, PubSubMetadata, SubscriptionId, typed::Subscriber}; use ethereum_types::H256; use memzero::Memzero; @@ -68,81 +68,78 @@ fn abridge_topic(topic: &[u8]) -> Topic { abridged.into() } -build_rpc_trait! { - /// Whisper RPC interface. - pub trait Whisper { - /// Info about the node. - #[rpc(name = "shh_info")] - fn info(&self) -> Result; - - /// Generate a new asymmetric key pair and return an identity. - #[rpc(name = "shh_newKeyPair")] - fn new_key_pair(&self) -> Result; - - /// Import the given SECP2561k private key and return an identity. - #[rpc(name = "shh_addPrivateKey")] - fn add_private_key(&self, types::Private) -> Result; - - /// Generate a new symmetric key and return an identity. - #[rpc(name = "shh_newSymKey")] - fn new_sym_key(&self) -> Result; - - /// Import the given symmetric key and return an identity. - #[rpc(name = "shh_addSymKey")] - fn add_sym_key(&self, types::Symmetric) -> Result; - - /// Get public key. Succeeds if identity is stored and asymmetric. - #[rpc(name = "shh_getPublicKey")] - fn get_public(&self, types::Identity) -> Result; - - /// Get private key. Succeeds if identity is stored and asymmetric. - #[rpc(name = "shh_getPrivateKey")] - fn get_private(&self, types::Identity) -> Result; - - #[rpc(name = "shh_getSymKey")] - fn get_symmetric(&self, types::Identity) -> Result; - - /// Delete key pair denoted by given identity. - /// - /// Return true if successfully removed, false if unknown, - /// and error otherwise. - #[rpc(name = "shh_deleteKey")] - fn remove_key(&self, types::Identity) -> Result; - - /// Post a message to the network with given parameters. - #[rpc(name = "shh_post")] - fn post(&self, types::PostRequest) -> Result; - - /// Create a new polled filter. - #[rpc(name = "shh_newMessageFilter")] - fn new_filter(&self, types::FilterRequest) -> Result; - - /// Poll changes on a polled filter. - #[rpc(name = "shh_getFilterMessages")] - fn poll_changes(&self, types::Identity) -> Result, Error>; - - /// Delete polled filter. Return bool indicating success. - #[rpc(name = "shh_deleteMessageFilter")] - fn delete_filter(&self, types::Identity) -> Result; - } +/// Whisper RPC interface. +#[rpc] +pub trait Whisper { + /// Info about the node. + #[rpc(name = "shh_info")] + fn info(&self) -> Result; + + /// Generate a new asymmetric key pair and return an identity. + #[rpc(name = "shh_newKeyPair")] + fn new_key_pair(&self) -> Result; + + /// Import the given SECP2561k private key and return an identity. + #[rpc(name = "shh_addPrivateKey")] + fn add_private_key(&self, types::Private) -> Result; + + /// Generate a new symmetric key and return an identity. + #[rpc(name = "shh_newSymKey")] + fn new_sym_key(&self) -> Result; + + /// Import the given symmetric key and return an identity. + #[rpc(name = "shh_addSymKey")] + fn add_sym_key(&self, types::Symmetric) -> Result; + + /// Get public key. Succeeds if identity is stored and asymmetric. + #[rpc(name = "shh_getPublicKey")] + fn get_public(&self, types::Identity) -> Result; + + /// Get private key. Succeeds if identity is stored and asymmetric. + #[rpc(name = "shh_getPrivateKey")] + fn get_private(&self, types::Identity) -> Result; + + #[rpc(name = "shh_getSymKey")] + fn get_symmetric(&self, types::Identity) -> Result; + + /// Delete key pair denoted by given identity. + /// + /// Return true if successfully removed, false if unknown, + /// and error otherwise. + #[rpc(name = "shh_deleteKey")] + fn remove_key(&self, types::Identity) -> Result; + + /// Post a message to the network with given parameters. + #[rpc(name = "shh_post")] + fn post(&self, types::PostRequest) -> Result; + + /// Create a new polled filter. + #[rpc(name = "shh_newMessageFilter")] + fn new_filter(&self, types::FilterRequest) -> Result; + + /// Poll changes on a polled filter. + #[rpc(name = "shh_getFilterMessages")] + fn poll_changes(&self, types::Identity) -> Result, Error>; + + /// Delete polled filter. Return bool indicating success. + #[rpc(name = "shh_deleteMessageFilter")] + fn delete_filter(&self, types::Identity) -> Result; } -build_rpc_trait! { - /// Whisper RPC pubsub. - pub trait WhisperPubSub { - type Metadata; +/// Whisper RPC pubsub. +#[rpc] +pub trait WhisperPubSub { + // RPC Metadata + type Metadata; - #[pubsub(name = "shh_subscription")] { - /// Subscribe to messages matching the filter. - #[rpc(name = "shh_subscribe")] - fn subscribe(&self, Self::Metadata, pubsub::Subscriber, types::FilterRequest); + /// Subscribe to messages matching the filter. + #[pubsub(subscription = "shh_subscription", subscribe, name = "shh_subscribe")] + fn subscribe(&self, Self::Metadata, Subscriber, types::FilterRequest); - /// Unsubscribe from filter matching given ID. Return - /// true on success, error otherwise. - #[rpc(name = "shh_unsubscribe")] - fn unsubscribe(&self, SubscriptionId) -> Result; - } - } + /// Unsubscribe from filter matching given ID. Return + /// true on success, error otherwise. + #[pubsub(subscription = "shh_subscription", unsubscribe, name = "shh_unsubscribe")] + fn unsubscribe(&self, Option, SubscriptionId) -> Result; } /// Something which can send messages to the network. @@ -364,7 +361,7 @@ impl WhisperPubSub for fn subscribe( &self, _meta: Self::Metadata, - subscriber: pubsub::Subscriber, + subscriber: Subscriber, req: types::FilterRequest, ) { match Filter::new(req) { @@ -377,7 +374,7 @@ impl WhisperPubSub for } } - fn unsubscribe(&self, id: SubscriptionId) -> Result { + fn unsubscribe(&self, _: Option, id: SubscriptionId) -> Result { use std::str::FromStr; let res = match id {