diff --git a/.gitignore b/.gitignore index 4231fae3fd225..1b70fb7bcb660 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,6 @@ substrate/pwasm-alloc/Cargo.lock substrate/pwasm-libc/Cargo.lock demo/runtime/wasm/target/ **/._* -.vscode \ No newline at end of file +.vscode +polkadot.* +.DS_Store diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000000..137f7ebe1a606 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,53 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +### Facilitation, Not Strongarming + +We recognise that this software is merely a tool for users to create and maintain their blockchain of preference. We see that blockchains are naturally community platforms with users being the ultimate decision makers. We assert that good software will maximise user agency by facilitate user-expression on the network. As such: + +* This project will strive to give users as much choice as is both reasonable and possible over what protocol they adhere to; but +* use of the project's technical forums, commenting systems, pull requests and issue trackers as a means to express individual protocol preferences is forbidden. + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at admin@parity.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000000..1fc4eb3a5cf60 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,53 @@ +## `Polkadot` projects is a **OPENISH Open Source Project** +----------------------------------------- + +## What? + +Individuals making significant and valuable contributions are given commit-access to a project to contribute as they see fit. A project is more like an open wiki than a standard guarded open source project. + +## Rules + +There are a few basic ground-rules for contributors (including the maintainer(s) of the project): + +1. **No `--force` pushes** or modifying the Git history in any way. If you need to rebase, ensure you do it in your own repo. +1. **Non-master branches**, prefixed with a short name moniker (e.g. `gav-my-feature`) must be used for ongoing work. +1. **All modifications** must be made in a **pull-request** to solicit feedback from other contributors. +1. A pull-request *must not be merged until CI* has finished successfully. +1. Contributors should adhere to the house coding style, as specified on the wiki. + +Merging pull requests once CI is successful: + +1. A pull request that does not alter any logic (e.g. comments, dependencies, docs) may be tagged `insubstantial` and merged by its author. +1. A pull request with no large change to logic that is an urgent fix may be merged after a non-author contributor has reviewed it well. +1. All other PRs should sit for 48 hours with the `pleasereview` tag in order to garner feedback. +1. No PR should be merged until all reviews' comments are addressed. + +Reviewing pull requests: + +When reviewing a pull request, the end-goal is to suggest useful changes to the author. Reviews should finish with approval unless there are issues that would result in: + +1. Buggy behaviour. +1. Undue maintenance burden. +1. Breaking with house coding style. +1. Pessimisation (i.e. reduction of speed as measured in the projects benchmarks). +1. Feature reduction (i.e. it removes some aspect of functionality that a significant minority of users rely on). +1. Uselessness (i.e. it does not strictly add a feature or fix a known issue). + +Reviews may not be used as an effective veto for a PR because: + +1. There exists a somewhat cleaner/better/faster way of accomplishing the same feature/fix. +1. It does not fit well with some other contributors' longer-term vision for the project. + +## Releases + +Declaring formal releases remains the prerogative of the project maintainer(s). + +## Changes to this arrangement + +This is an experiment and feedback is welcome! This document may also be subject to pull-requests or changes by contributors where you believe you have something valuable to add or change. + +## Heritage + +These contributing guidelines are modified from the "OPEN Open Source Project" guidelines for the Level project: https://github.com/Level/community/blob/master/CONTRIBUTING.md + +----------------------------------------- diff --git a/Cargo.lock b/Cargo.lock index e5d1ff228f551..92be9f69c4d9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,6 +6,20 @@ dependencies = [ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "aio-limited" +version = "0.1.0" +source = "git+https://github.com/paritytech/aio-limited.git#1f42497dcd2a6f85b83af97cd80314b26a1e4a9e" +dependencies = [ + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ansi_term" version = "0.9.0" @@ -35,6 +49,11 @@ dependencies = [ "xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayref" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayvec" version = "0.4.7" @@ -43,6 +62,14 @@ dependencies = [ "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "asn1_der" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "etrace 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "assert_matches" version = "1.2.0" @@ -79,6 +106,11 @@ dependencies = [ "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base-x" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "base58" version = "0.1.0" @@ -101,6 +133,15 @@ dependencies = [ "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base64" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "base64" version = "0.9.1" @@ -110,6 +151,20 @@ dependencies = [ "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bigint" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bitflags" version = "0.9.1" @@ -129,6 +184,30 @@ dependencies = [ "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "block-buffer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bs58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byte-tools" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.2.3" @@ -156,6 +235,15 @@ name = "cfg-if" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "chashmap" +version = "2.2.1" +source = "git+https://github.com/redox-os/tfs#3e7dcdb0c586d0d8bb3f25bfd948d2f418a4ab10" +dependencies = [ + "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "chrono" version = "0.4.2" @@ -166,21 +254,39 @@ dependencies = [ "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cid" +version = "0.2.3" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "integer-encoding 1.0.5 (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.1-pre (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", +] + [[package]] name = "clap" -version = "2.31.2" +version = "2.32.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.10 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cmake" version = "0.1.31" @@ -297,18 +403,31 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "datastore" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "chashmap 2.2.1 (git+https://github.com/redox-os/tfs)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "demo-cli" version = "0.1.0" dependencies = [ - "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)", "demo-executor 0.1.0", "demo-primitives 0.1.0", "demo-runtime 0.1.0", "ed25519 0.1.0", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -321,7 +440,7 @@ dependencies = [ "substrate-rpc-servers 0.1.0", "substrate-runtime-io 0.1.0", "substrate-state-machine 0.1.0", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -337,6 +456,7 @@ dependencies = [ "substrate-executor 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-staking 0.1.0", @@ -351,8 +471,8 @@ name = "demo-primitives" version = "0.1.0" dependencies = [ "pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-primitives 0.1.0", @@ -369,8 +489,8 @@ dependencies = [ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 0.1.0", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", @@ -386,6 +506,7 @@ dependencies = [ "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", "substrate-runtime-timestamp 0.1.0", + "substrate-runtime-version 0.1.0", ] [[package]] @@ -393,6 +514,14 @@ name = "difference" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "digest" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "dtoa" version = "0.4.2" @@ -449,6 +578,14 @@ dependencies = [ "backtrace 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "error-chain" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "eth-secp256k1" version = "0.5.7" @@ -467,19 +604,19 @@ dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethcore-bytes" version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" [[package]] name = "ethcore-crypto" version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" dependencies = [ "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -491,12 +628,11 @@ dependencies = [ [[package]] name = "ethcore-io" version = "1.12.0" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" dependencies = [ "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -507,7 +643,7 @@ dependencies = [ [[package]] name = "ethcore-logger" version = "1.12.0" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -520,56 +656,6 @@ dependencies = [ "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ethcore-network" -version = "1.12.0" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" -dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-crypto 0.1.0 (git+https://github.com/paritytech/parity.git)", - "ethcore-io 1.12.0 (git+https://github.com/paritytech/parity.git)", - "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethkey 0.3.0 (git+https://github.com/paritytech/parity.git)", - "ipnetwork 0.12.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.1 (git+https://github.com/paritytech/parity.git)", - "snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)", -] - -[[package]] -name = "ethcore-network-devp2p" -version = "1.12.0" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" -dependencies = [ - "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)", - "ethcore-crypto 0.1.0 (git+https://github.com/paritytech/parity.git)", - "ethcore-io 1.12.0 (git+https://github.com/paritytech/parity.git)", - "ethcore-logger 1.12.0 (git+https://github.com/paritytech/parity.git)", - "ethcore-network 1.12.0 (git+https://github.com/paritytech/parity.git)", - "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethkey 0.3.0 (git+https://github.com/paritytech/parity.git)", - "igd 0.7.0 (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 (git+https://github.com/paritytech/parity.git)", - "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "path 0.1.0 (git+https://github.com/paritytech/parity.git)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.1 (git+https://github.com/paritytech/parity.git)", - "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.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ethereum-types" version = "0.3.2" @@ -580,7 +666,7 @@ dependencies = [ "ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "uint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -589,13 +675,13 @@ name = "ethereum-types-serialize" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethkey" version = "0.3.0" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "edit-distance 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -609,18 +695,30 @@ dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "etrace" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "exit-future" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fdlimit" version = "0.1.1" @@ -667,6 +765,15 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fs-swap" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -700,6 +807,14 @@ name = "gcc" version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +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)", +] + [[package]] name = "getopts" version = "0.2.17" @@ -720,7 +835,7 @@ dependencies = [ [[package]] name = "hashdb" version = "0.1.1" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -798,7 +913,7 @@ dependencies = [ "relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-proto 0.1.1 (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.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -816,20 +931,9 @@ dependencies = [ ] [[package]] -name = "igd" -version = "0.7.0" +name = "integer-encoding" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.21 (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.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-retry 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "xmltree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "integer-sqrt" @@ -871,19 +975,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jsonrpc-core" version = "8.0.2" -source = "git+https://github.com/paritytech/jsonrpc.git#3e358b48b71bf90dc60b4099de47e65b030dc319" +source = "git+https://github.com/paritytech/jsonrpc.git#c3f02dfbbef0c4afe16633f503917d4a0501ee9d" dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-http-server" version = "8.0.1" -source = "git+https://github.com/paritytech/jsonrpc.git#3e358b48b71bf90dc60b4099de47e65b030dc319" +source = "git+https://github.com/paritytech/jsonrpc.git#c3f02dfbbef0c4afe16633f503917d4a0501ee9d" dependencies = [ "hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)", @@ -896,46 +1000,46 @@ dependencies = [ [[package]] name = "jsonrpc-macros" version = "8.0.1" -source = "git+https://github.com/paritytech/jsonrpc.git#3e358b48b71bf90dc60b4099de47e65b030dc319" +source = "git+https://github.com/paritytech/jsonrpc.git#c3f02dfbbef0c4afe16633f503917d4a0501ee9d" dependencies = [ "jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)", "jsonrpc-pubsub 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-pubsub" version = "8.0.1" -source = "git+https://github.com/paritytech/jsonrpc.git#3e358b48b71bf90dc60b4099de47e65b030dc319" +source = "git+https://github.com/paritytech/jsonrpc.git#c3f02dfbbef0c4afe16633f503917d4a0501ee9d" dependencies = [ "jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-server-utils" version = "8.0.1" -source = "git+https://github.com/paritytech/jsonrpc.git#3e358b48b71bf90dc60b4099de47e65b030dc319" +source = "git+https://github.com/paritytech/jsonrpc.git#c3f02dfbbef0c4afe16633f503917d4a0501ee9d" dependencies = [ "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "globset 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-ws-server" version = "8.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git#3e358b48b71bf90dc60b4099de47e65b030dc319" +source = "git+https://github.com/paritytech/jsonrpc.git#c3f02dfbbef0c4afe16633f503917d4a0501ee9d" dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)", "jsonrpc-server-utils 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ws 0.7.5 (git+https://github.com/tomusdrw/ws-rs)", ] @@ -953,7 +1057,7 @@ dependencies = [ [[package]] name = "keccak-hash" version = "0.1.2" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" dependencies = [ "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -971,17 +1075,17 @@ dependencies = [ [[package]] name = "kvdb" version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)", ] [[package]] name = "kvdb-memorydb" version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" dependencies = [ "kvdb 0.1.0 (git+https://github.com/paritytech/parity.git)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -990,10 +1094,11 @@ dependencies = [ [[package]] name = "kvdb-rocksdb" version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fs-swap 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0 (git+https://github.com/paritytech/parity.git)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1028,6 +1133,287 @@ name = "libc" version = "0.2.41" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "libp2p" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-dns 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-floodsub 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-identify 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-kad 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-mplex 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-ping 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-ratelimit 0.1.1 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-relay 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-secio 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-tcp-transport 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-transport-timeout 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-websocket 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-yamux 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-core" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "bs58 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.8 (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.21 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "multihash 0.8.1-pre (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "multistream-select 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "smallvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-dns" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "tokio-dns-unofficial 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-floodsub" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "bs58 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.8 (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.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", +] + +[[package]] +name = "libp2p-identify" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "bytes 0.4.8 (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.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", +] + +[[package]] +name = "libp2p-kad" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bigint 4.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "datastore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-identify 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-ping 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", +] + +[[package]] +name = "libp2p-mplex" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "bytes 0.4.8 (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.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", +] + +[[package]] +name = "libp2p-peerstore" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "bs58 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "datastore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-ping" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "multistream-select 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-ratelimit" +version = "0.1.1" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "aio-limited 0.1.0 (git+https://github.com/paritytech/aio-limited.git)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-relay" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "protobuf 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", +] + +[[package]] +name = "libp2p-secio" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "asn1_der 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-tcp-transport" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-transport-timeout" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-websocket" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "rw-stream-sink 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "websocket 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-yamux" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "yamux 0.1.0 (git+https://github.com/paritytech/yamux)", +] + [[package]] name = "linked-hash-map" version = "0.5.1" @@ -1043,6 +1429,15 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lock_api" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "log" version = "0.3.9" @@ -1067,7 +1462,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mem" version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" [[package]] name = "memchr" @@ -1090,7 +1485,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memorydb" version = "0.1.1" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1146,6 +1541,60 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "multiaddr" +version = "0.3.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cid 0.2.3 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "integer-encoding 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "multibase" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base-x 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "multihash" +version = "0.8.1-pre" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +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)", +] + +[[package]] +name = "multistream-select" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", +] + +[[package]] +name = "names" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nan-preserving-float" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "native-tls" version = "0.1.5" @@ -1175,6 +1624,15 @@ name = "nodrop" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num-bigint" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-integer" version = "0.1.38" @@ -1238,17 +1696,7 @@ dependencies = [ [[package]] name = "parity-wasm" -version = "0.27.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-wasm" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1282,6 +1730,15 @@ dependencies = [ "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.2.14" @@ -1289,19 +1746,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "path" -version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" - [[package]] name = "patricia-trie" version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)", @@ -1329,7 +1781,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "plain_hasher" version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1337,17 +1789,20 @@ dependencies = [ [[package]] name = "polkadot" -version = "0.2.0" +version = "0.3.0" dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "polkadot-cli 0.2.0", + "ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "polkadot-cli 0.3.0", + "vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "polkadot-api" version = "0.1.0" dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-executor 0.1.0", "polkadot-primitives 0.1.0", "polkadot-runtime 0.1.0", @@ -1364,53 +1819,50 @@ dependencies = [ [[package]] name = "polkadot-cli" -version = "0.2.0" +version = "0.3.0" dependencies = [ - "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)", - "ed25519 0.1.0", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-primitives 0.1.0", "polkadot-runtime 0.1.0", - "polkadot-service 0.2.0", + "polkadot-service 0.3.0", "polkadot-transaction-pool 0.1.0", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-cli 0.3.0", "substrate-client 0.1.0", + "substrate-codec 0.1.0", + "substrate-extrinsic-pool 0.1.0", "substrate-network 0.1.0", "substrate-primitives 0.1.0", "substrate-rpc 0.1.0", "substrate-rpc-servers 0.1.0", "substrate-runtime-primitives 0.1.0", + "substrate-service 0.3.0", "substrate-state-machine 0.1.0", - "substrate-telemetry 0.2.0", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-telemetry 0.3.0", + "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "polkadot-collator" version = "0.1.0" dependencies = [ + "ed25519 0.1.0", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "polkadot-parachain 0.1.0", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "polkadot-api 0.1.0", + "polkadot-cli 0.3.0", "polkadot-primitives 0.1.0", "polkadot-runtime 0.1.0", + "substrate-client 0.1.0", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", + "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1418,27 +1870,26 @@ name = "polkadot-consensus" version = "0.1.0" dependencies = [ "ed25519 0.1.0", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "exit-future 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-api 0.1.0", - "polkadot-collator 0.1.0", "polkadot-parachain 0.1.0", "polkadot-primitives 0.1.0", "polkadot-runtime 0.1.0", "polkadot-statement-table 0.1.0", "polkadot-transaction-pool 0.1.0", + "rhododendron 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-bft 0.1.0", "substrate-client 0.1.0", "substrate-codec 0.1.0", "substrate-keyring 0.1.0", - "substrate-network 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-support 0.1.0", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1449,14 +1900,33 @@ dependencies = [ "substrate-executor 0.1.0", ] +[[package]] +name = "polkadot-network" +version = "0.1.0" +dependencies = [ + "ed25519 0.1.0", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "polkadot-api 0.1.0", + "polkadot-consensus 0.1.0", + "polkadot-primitives 0.1.0", + "rhododendron 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-bft 0.1.0", + "substrate-codec 0.1.0", + "substrate-network 0.1.0", + "substrate-primitives 0.1.0", + "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "polkadot-parachain" version = "0.1.0" dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1464,8 +1934,8 @@ name = "polkadot-primitives" version = "0.1.0" dependencies = [ "pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-primitives 0.1.0", @@ -1482,8 +1952,8 @@ dependencies = [ "polkadot-primitives 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 0.1.0", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", @@ -1499,41 +1969,36 @@ dependencies = [ "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", "substrate-runtime-timestamp 0.1.0", + "substrate-runtime-version 0.1.0", "substrate-serializer 0.1.0", ] [[package]] name = "polkadot-service" -version = "0.2.0" +version = "0.3.0" dependencies = [ - "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "ed25519 0.1.0", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "exit-future 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-api 0.1.0", "polkadot-consensus 0.1.0", "polkadot-executor 0.1.0", + "polkadot-network 0.1.0", "polkadot-primitives 0.1.0", "polkadot-runtime 0.1.0", "polkadot-transaction-pool 0.1.0", "slog 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-client 0.1.0", - "substrate-client-db 0.1.0", "substrate-codec 0.1.0", - "substrate-executor 0.1.0", - "substrate-keystore 0.1.0", "substrate-network 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", - "substrate-runtime-primitives 0.1.0", - "substrate-state-machine 0.1.0", - "substrate-telemetry 0.2.0", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-service 0.3.0", + "substrate-telemetry 0.3.0", + "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1541,6 +2006,7 @@ name = "polkadot-statement-table" version = "0.1.0" dependencies = [ "polkadot-primitives 0.1.0", + "substrate-codec 0.1.0", "substrate-primitives 0.1.0", ] @@ -1549,7 +2015,7 @@ name = "polkadot-transaction-pool" version = "0.1.0" dependencies = [ "ed25519 0.1.0", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-api 0.1.0", @@ -1593,6 +2059,11 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "protobuf" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pulldown-cmark" version = "0.0.3" @@ -1615,14 +2086,19 @@ version = "0.1.0" [[package]] name = "pwasm-utils" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quick-error" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quick-error" version = "1.2.2" @@ -1656,6 +2132,23 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand" +version = "0.5.3" +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-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rayon" version = "0.8.2" @@ -1710,6 +2203,18 @@ dependencies = [ "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "regex" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "regex-syntax" version = "0.5.6" @@ -1718,6 +2223,14 @@ dependencies = [ "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "regex-syntax" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "relay" version = "0.1.1" @@ -1734,6 +2247,16 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rhododendron" +version = "0.2.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)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ring" version = "0.12.1" @@ -1749,7 +2272,7 @@ dependencies = [ [[package]] name = "rlp" version = "0.2.1" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1829,6 +2352,16 @@ dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rw-stream-sink" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "safe-mix" version = "0.1.0" @@ -1895,12 +2428,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.64" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.64" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1910,18 +2443,34 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.19" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "sha1" -version = "0.2.0" +name = "sha1" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sha1" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sha2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "shell32-sys" @@ -1941,11 +2490,6 @@ dependencies = [ "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "slab" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "slab" version = "0.3.0" @@ -1977,8 +2521,8 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1999,21 +2543,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "snappy" -version = "0.1.0" -source = "git+https://github.com/paritytech/rust-snappy#40ac9a0d9fd613e7f38df800a11a589b7296da73" +name = "smallvec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", - "snappy-sys 0.1.0 (git+https://github.com/paritytech/rust-snappy)", + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2030,6 +2573,11 @@ name = "stable_deref_trait" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "stdweb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "strsim" version = "0.7.0" @@ -2049,18 +2597,48 @@ name = "substrate-bft" version = "0.1.0" dependencies = [ "ed25519 0.1.0", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rhododendron 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-executor 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-support 0.1.0", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-runtime-version 0.1.0", + "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-cli" +version = "0.3.0" +dependencies = [ + "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-client 0.1.0", + "substrate-extrinsic-pool 0.1.0", + "substrate-network 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-service 0.3.0", + "substrate-telemetry 0.3.0", + "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2068,11 +2646,12 @@ name = "substrate-client" version = "0.1.0" dependencies = [ "ed25519 0.1.0", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-bft 0.1.0", "substrate-codec 0.1.0", "substrate-executor 0.1.0", @@ -2082,6 +2661,7 @@ dependencies = [ "substrate-runtime-primitives 0.1.0", "substrate-runtime-support 0.1.0", "substrate-state-machine 0.1.0", + "substrate-telemetry 0.3.0", "substrate-test-client 0.1.0", "triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2101,9 +2681,11 @@ dependencies = [ "patricia-trie 0.1.0 (git+https://github.com/paritytech/parity.git)", "substrate-client 0.1.0", "substrate-codec 0.1.0", + "substrate-executor 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-support 0.1.0", + "substrate-state-db 0.1.0", "substrate-state-machine 0.1.0", ] @@ -2121,31 +2703,37 @@ dependencies = [ "assert_matches 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "ed25519 0.1.0", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.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.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", + "substrate-runtime-version 0.1.0", "substrate-serializer 0.1.0", "substrate-state-machine 0.1.0", "triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wabt 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-extrinsic-pool" version = "0.1.0" dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "transaction-pool 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "transaction-pool 1.12.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2162,13 +2750,13 @@ name = "substrate-keystore" version = "0.1.0" dependencies = [ "ed25519 0.1.0", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-crypto 0.1.0 (git+https://github.com/paritytech/parity.git)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2177,6 +2765,7 @@ dependencies = [ name = "substrate-misbehavior-check" version = "0.1.0" dependencies = [ + "rhododendron 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-bft 0.1.0", "substrate-codec 0.1.0", "substrate-keyring 0.1.0", @@ -2192,30 +2781,48 @@ dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "ed25519 0.1.0", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-io 1.12.0 (git+https://github.com/paritytech/parity.git)", - "ethcore-network 1.12.0 (git+https://github.com/paritytech/parity.git)", - "ethcore-network-devp2p 1.12.0 (git+https://github.com/paritytech/parity.git)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-bft 0.1.0", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-client 0.1.0", "substrate-codec 0.1.0", "substrate-keyring 0.1.0", + "substrate-network-libp2p 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-primitives 0.1.0", - "substrate-runtime-support 0.1.0", - "substrate-serializer 0.1.0", - "substrate-state-machine 0.1.0", "substrate-test-client 0.1.0", ] +[[package]] +name = "substrate-network-libp2p" +version = "0.1.0" +dependencies = [ + "assert_matches 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)", + "ethcore-io 1.12.0 (git+https://github.com/paritytech/parity.git)", + "ethcore-logger 1.12.0 (git+https://github.com/paritytech/parity.git)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0 (git+https://github.com/paritytech/parity.git)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "ipnetwork 0.12.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)", +] + [[package]] name = "substrate-primitives" version = "0.1.0" @@ -2226,14 +2833,14 @@ dependencies = [ "fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)", "pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-runtime-std 0.1.0", "substrate-serializer 0.1.0", "twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)", - "wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2241,20 +2848,21 @@ name = "substrate-rpc" version = "0.1.0" dependencies = [ "assert_matches 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)", "jsonrpc-macros 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)", "jsonrpc-pubsub 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-client 0.1.0", + "substrate-codec 0.1.0", "substrate-executor 0.1.0", "substrate-extrinsic-pool 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-state-machine 0.1.0", "substrate-test-client 0.1.0", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2275,8 +2883,8 @@ name = "substrate-runtime-consensus" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", @@ -2291,12 +2899,22 @@ name = "substrate-runtime-contract" version = "0.1.0" dependencies = [ "assert_matches 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pwasm-utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pwasm-utils 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", "substrate-runtime-sandbox 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-staking 0.1.0", "substrate-runtime-std 0.1.0", - "wabt 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", + "substrate-runtime-timestamp 0.1.0", + "wabt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2306,8 +2924,8 @@ dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)", "safe-mix 0.1.0", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", @@ -2320,6 +2938,7 @@ dependencies = [ "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", + "substrate-runtime-timestamp 0.1.0", ] [[package]] @@ -2328,8 +2947,8 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 0.1.0", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-consensus 0.1.0", @@ -2340,6 +2959,7 @@ dependencies = [ "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", + "substrate-runtime-timestamp 0.1.0", ] [[package]] @@ -2347,8 +2967,8 @@ name = "substrate-runtime-executive" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-consensus 0.1.0", @@ -2359,6 +2979,7 @@ dependencies = [ "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", + "substrate-runtime-timestamp 0.1.0", ] [[package]] @@ -2380,10 +3001,11 @@ name = "substrate-runtime-primitives" version = "0.1.0" dependencies = [ "integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", @@ -2400,8 +3022,8 @@ dependencies = [ "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-std 0.1.0", - "wabt 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2410,8 +3032,8 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 0.1.0", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", @@ -2421,6 +3043,7 @@ dependencies = [ "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", + "substrate-runtime-timestamp 0.1.0", ] [[package]] @@ -2429,13 +3052,12 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 0.1.0", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-consensus 0.1.0", - "substrate-runtime-contract 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-sandbox 0.1.0", @@ -2443,7 +3065,8 @@ dependencies = [ "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", - "wabt 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-runtime-timestamp 0.1.0", + "wabt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2461,8 +3084,8 @@ version = "0.1.0" dependencies = [ "ed25519 0.1.0", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", @@ -2475,8 +3098,8 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 0.1.0", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", @@ -2490,10 +3113,11 @@ name = "substrate-runtime-timestamp" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-std 0.1.0", @@ -2501,12 +3125,65 @@ dependencies = [ "substrate-runtime-system 0.1.0", ] +[[package]] +name = "substrate-runtime-version" +version = "0.1.0" +dependencies = [ + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", +] + [[package]] name = "substrate-serializer" version = "0.1.0" dependencies = [ - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-service" +version = "0.3.0" +dependencies = [ + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-client 0.1.0", + "substrate-client-db 0.1.0", + "substrate-codec 0.1.0", + "substrate-executor 0.1.0", + "substrate-extrinsic-pool 0.1.0", + "substrate-keystore 0.1.0", + "substrate-network 0.1.0", + "substrate-primitives 0.1.0", + "substrate-rpc 0.1.0", + "substrate-rpc-servers 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-telemetry 0.3.0", + "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-state-db" +version = "0.1.0" +dependencies = [ + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", ] [[package]] @@ -2517,7 +3194,6 @@ dependencies = [ "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.1 (git+https://github.com/paritytech/parity.git)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity.git)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "memorydb 0.1.1 (git+https://github.com/paritytech/parity.git)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2528,7 +3204,7 @@ dependencies = [ [[package]] name = "substrate-telemetry" -version = "0.2.0" +version = "0.3.0" dependencies = [ "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2544,6 +3220,7 @@ dependencies = [ name = "substrate-test-client" version = "0.1.0" dependencies = [ + "rhododendron 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-bft 0.1.0", "substrate-client 0.1.0", "substrate-codec 0.1.0", @@ -2562,8 +3239,8 @@ dependencies = [ "ed25519 0.1.0", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", @@ -2571,6 +3248,7 @@ dependencies = [ "substrate-runtime-primitives 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", + "substrate-runtime-version 0.1.0", ] [[package]] @@ -2598,6 +3276,11 @@ name = "take_mut" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "target_info" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "tempdir" version = "0.3.7" @@ -2607,6 +3290,18 @@ dependencies = [ "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tempfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "termion" version = "1.5.1" @@ -2619,7 +3314,7 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.9.0" +version = "0.10.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)", @@ -2662,21 +3357,31 @@ dependencies = [ [[package]] name = "tokio" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-fs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-codec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-core" version = "0.1.17" @@ -2688,11 +3393,31 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.14 (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.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-current-thread" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-dns-unofficial" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2709,13 +3434,13 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2736,7 +3461,7 @@ dependencies = [ "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2750,18 +3475,7 @@ dependencies = [ "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-retry" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (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)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2781,13 +3495,13 @@ dependencies = [ "futures 0.1.21 (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.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2800,16 +3514,7 @@ dependencies = [ [[package]] name = "tokio-timer" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.21 (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.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2824,7 +3529,7 @@ dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2836,7 +3541,7 @@ dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2855,19 +3560,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "transaction-pool" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "trace-time 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "triehash" version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#93054ef24b590a8d854cd6b2d1de6567667d39da" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2904,6 +3609,11 @@ name = "typeable" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ucd-util" version = "0.1.1" @@ -2997,6 +3707,19 @@ name = "utf8-ranges" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "varint" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2#725f9f78ebeddc038941316f120a99daaebc9231" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "vcpkg" version = "0.2.3" @@ -3007,6 +3730,15 @@ name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "vergen" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "version_check" version = "0.1.3" @@ -3019,19 +3751,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wabt" -version = "0.1.8" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "wabt-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wabt-sys" -version = "0.1.4" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3050,12 +3781,13 @@ dependencies = [ [[package]] name = "wasmi" -version = "0.1.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.27.6 (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.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3073,7 +3805,7 @@ dependencies = [ "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3139,50 +3871,62 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "xml-rs" -version = "0.7.0" +name = "yaml-rust" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "xmltree" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "yamux" +version = "0.1.0" +source = "git+https://github.com/paritytech/yamux#4e3ae609ad29cae56c249353be37a473413a84da" dependencies = [ - "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "yaml-rust" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [metadata] "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" +"checksum aio-limited 0.1.0 (git+https://github.com/paritytech/aio-limited.git)" = "" "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" "checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" +"checksum arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0fd1479b7c29641adbd35ff3b5c293922d696a92f25c8c975da3e0acbc87258f" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" +"checksum asn1_der 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f9dec199e4d3e3263a71ec23fd7f0259b3c6963ff83e6bb4871d9d91343d4c81" "checksum assert_matches 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "664470abf00fae0f31c0eb6e1ca12d82961b2a2541ef898bc9dd51a9254d218b" "checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1" "checksum backtrace 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dbdd17cd962b570302f5297aea8648d5923e22e555c2ed2d8b2e34eca646bf6d" "checksum backtrace-sys 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "bff67d0c06556c0b8e6b5f090f0eac52d950d9dfd1d35ba04e4ca3543eaf6a7e" +"checksum base-x 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f59103b47307f76e03bef1633aec7fa9e29bfb5aa6daf5a334f94233c71f6c1" "checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" "checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557" "checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" +"checksum base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5032d51da2741729bfdaeb2664d9b8c6d9fd1e2b90715c660b6def36628499c2" "checksum base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9263aa6a38da271eec5c91a83ce1e800f093c8535788d403d626d8d5c3f8f007" +"checksum bigint 4.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da1dde4308822ffaa13665757273a1b787481212f3f9b1c470a864b179a01f1b" +"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.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" +"checksum bs58 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e6ea4851598d7433fbdba71fa2509d9b0df68124b9c0effe7588f5149692d9f" +"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" +"checksum byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96c8b41881888cc08af32d47ac4edd52bc7fa27fef774be47a92443756451304" "checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" "checksum bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dd32989a66957d3f0cba6588f15d4281a733f4e9ffc43fcd2385f57d3bf99ff" "checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d" "checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18" +"checksum chashmap 2.2.1 (git+https://github.com/redox-os/tfs)" = "" "checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6" -"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" +"checksum cid 0.2.3 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "95470235c31c726d72bf2e1f421adc1e65b9d561bf5529612cbe1a72da1467b3" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67" @@ -3197,36 +3941,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d636a8b3bcc1b409d7ffd3facef8f21dcb4009626adbd0c5e6c4305c07253c7b" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)" = "" +"checksum datastore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" "checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" +"checksum digest 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3cae2388d706b52f2f2f9afe280f9d768be36544bd71d1b8120cb34ea6450b55" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum edit-distance 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3bd26878c3d921f89797a4e1a1711919f999a9f6946bb6f5a4ffda126d297b7e" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" +"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)" = "" "checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386" "checksum ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum ethcore-crypto 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum ethcore-io 1.12.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum ethcore-logger 1.12.0 (git+https://github.com/paritytech/parity.git)" = "" -"checksum ethcore-network 1.12.0 (git+https://github.com/paritytech/parity.git)" = "" -"checksum ethcore-network-devp2p 1.12.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c48729b8aea8aedb12cf4cb2e5cef439fdfe2dda4a89e47eeebd15778ef53b6" "checksum ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac59a21a9ce98e188f3dace9eb67a6c4a3c67ec7fbc7218cb827852679dc002" "checksum ethkey 0.3.0 (git+https://github.com/paritytech/parity.git)" = "" -"checksum exit-future 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6c30ec160f83d938faf4dd6fdaba4f42316f1bd3df76b902df2d824f47fa9db7" +"checksum etrace 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5a3eb49b4ae7e88cc23caa812e8072c9f83a3e202e0b789ff4f9319cf796d8ca" +"checksum exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9aa7b56cef68c4182db7212dece19cc9f6e2916cf9412e57e6cea53ec02f316d" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa" "checksum fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "" "checksum fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18d6fd718fb4396e7a9c93ac59ba7143501467ca7a143c145b5555a571d5576" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fs-swap 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31a94e9407e53addc49de767234a0b000978523c59117e5badb575ccbb8370f6" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" +"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" "checksum globset 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "142754da2c9b3722affd909f9e27f2a6700a7a303f362971e0a74c652005a43d" "checksum hashdb 0.1.1 (git+https://github.com/paritytech/parity.git)" = "" @@ -3238,7 +3987,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2" "checksum hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)" = "34a590ca09d341e94cddf8e5af0bbccde205d5fbc2fa3c09dd67c7f85cea59d7" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" -"checksum igd 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a254e265e8810deb357a9de757f784787ec415d056ededf410c0aa460afee9e" +"checksum integer-encoding 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "26746cbc2e680af687e88d717f20ff90079bd10fc984ad57d277cd0e37309fa5" "checksum integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)" = "" "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" @@ -3262,8 +4011,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739" "checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" "checksum libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)" = "ac8ebf8343a981e2fa97042b14768f02ed3e1d602eac06cae6166df3c8ced206" +"checksum libp2p 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum libp2p-dns 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum libp2p-floodsub 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum libp2p-identify 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum libp2p-kad 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum libp2p-mplex 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum libp2p-ping 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum libp2p-ratelimit 0.1.1 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum libp2p-relay 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum libp2p-secio 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum libp2p-tcp-transport 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum libp2p-transport-timeout 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum libp2p-websocket 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum libp2p-yamux 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" "checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e" "checksum local-encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1ceb20f39ff7ae42f3ff9795f3986b1daad821caaa1e1732a0944103a5a1a66" +"checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" @@ -3276,9 +4042,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum mime 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0b28683d0b09bbc20be1c9b3f6f24854efb1356ffcffee08ea3f6e65596e85fa" "checksum mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "6d771e3ef92d58a8da8df7d6976bfca9371ed1de6619d9d5a5ce5b1f29b85bfe" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9c35dac080fd6e16a99924c8dfdef0af89d797dd851adab25feaffacf7850d6" +"checksum multihash 0.8.1-pre (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum multistream-select 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" +"checksum names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef320dab323286b50fb5cdda23f61c796a72a89998ab565ca32525c5c556f2da" +"checksum nan-preserving-float 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34d4f00fcc2f4c9efa8cc971db0da9e28290e28e97af47585e48691ef10ff31f" "checksum native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f74dbadc8b43df7864539cedb7bc91345e532fdd913cfdc23ad94f4d2d40fbc0" "checksum net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" +"checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" "checksum num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac0ea58d64a89d9d6b7688031b3be9358d6c919badcf7fbb0527ccfd891ee45" "checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" @@ -3286,13 +4059,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985" "checksum openssl-sys 0.9.33 (registry+https://github.com/rust-lang/crates.io-index)" = "d8abc04833dcedef24221a91852931df2f63e3369ae003134e70aff3645775cc" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum parity-wasm 0.27.6 (registry+https://github.com/rust-lang/crates.io-index)" = "bd4dc02a80a0315b109e48992c46942c79bcdb8fac416dd575d330ed9ced6cbd" -"checksum parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41083957b80abb8a01fac4d2773d5f92653aed8f0b740c8d3da1da62c7857abe" +"checksum parity-wasm 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1c91199d14bd5b78ecade323d4a891d094799749c1b9e82d9c590c2e2849a40" "checksum parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0dec124478845b142f68b446cbee953d14d4b41f1bc0425024417720dce693" "checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" "checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" +"checksum parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "901d6514273469bb17380c1ac3f51fb3ce54be1f960e51a6f04901eba313ab8d" "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" -"checksum path 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum patricia-trie 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f" @@ -3301,21 +4073,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0" "checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892" "checksum proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1fa93823f53cfd0f5ac117b189aed6cfdfb2cfc0a9d82e956dd7927595ed7d46" +"checksum protobuf 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7fec4b8f0fa26c52d29c66e93e8624aad859458ec5e5d4f6ddf923954293436a" "checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07" -"checksum pwasm-utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3a822d2a1624b10c46572c231c149575bcc261c37d84fd3f1a2f5ae1f65515" +"checksum pwasm-utils 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "efd695333cfae6e9dbe2703a6d040e252b57a6fc3b9a65c712615ac042b2e0c5" +"checksum quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb6ccf8db7bbcb9c2eae558db5ab4f3da1c2a87e4e597ed394726bc8ea6ca1d" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" +"checksum rand 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6802c0e883716383777e147b7c21323d5de7527257c8b6dc1365a7f2983e90f6" +"checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" "checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8" "checksum rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80e811e76f1dbf68abf87a759083d34600017fc4e10b6bd5ad84a700f9dba4b1" "checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8" "checksum redox_syscall 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8493950b18ff11387fef7fd9a9979f4dd77a36e182f754385838c70404b73e" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" +"checksum regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5bbbea44c5490a1e84357ff28b7d518b4619a159fed5d25f6c1de2d19cc42814" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" +"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "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 rhododendron 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e38401cc1b63e71ec9119115c7e1354fcf54c8006ad59a22409dd8bd93737b2" "checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c" "checksum rlp 0.2.1 (git+https://github.com/paritytech/parity.git)" = "" "checksum rlp 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "89db7f8dfdd5eb7ab3ac3ece7a07fd273a680b4b224cb231181280e8996f9f0b" @@ -3327,6 +4106,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a" +"checksum rw-stream-sink 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "85fd9df495640643ad2d00443b3d78aae69802ad488debab4f1dd52fc1806ade" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" @@ -3335,13 +4115,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5421621e836278a0b139268f36eee0dc7e389b784dc3f79d8f11aabadf41bead" "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 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "fba5be06346c5200249c8c8ca4ccba4a09e8747c71c16e420bd359a0db4d8f91" -"checksum serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "79e4620ba6fbe051fc7506fab6f84205823564d55da18d55b695160fb3479cd8" -"checksum serde_json 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "93aee34bb692dde91e602871bc792dd319e489c7308cdbbe5f27cf27c64280f5" +"checksum serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "0c3adf19c07af6d186d91dae8927b83b0553d07ca56cbf7f2f32560455c91920" +"checksum serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "3525a779832b08693031b8ecfb0de81cd71cfd3812088fafe9a7496789572124" +"checksum serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "84b8035cabe9b35878adec8ac5fe03d5f6bc97ff6edd7ccb96b44c1276ba390e" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" +"checksum sha1 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "171698ce4ec7cbb93babeb3190021b4d72e96ccb98e33d277ae4ea959d6f2d9e" +"checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" "checksum shell32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee04b46101f57121c9da2b151988283b6beb79b34f5bb29a58ee48cb695122c" "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.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" "checksum slog 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2f7bfce6405155042d42ec0e645efe43eddedd7be280063ce0623b120014e7f9" @@ -3349,46 +4130,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum slog-json 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddd14b8df2df39378b3e933c79784350bf715b11444d99f903df0253bbe524e5" "checksum slog-scope 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "053344c94c0e2b22da6305efddb698d7c485809427cf40555dc936085f67a9df" "checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" -"checksum smallvec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4f357e8cd37bf8822e1b964e96fd39e2cb5a0424f8aaa284ccaccc2162411c" -"checksum smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03dab98ab5ded3a8b43b2c80751194608d0b2aa0f1d46cf95d1c35e192844aa7" -"checksum snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "" +"checksum smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f90c5e5fe535e48807ab94fc611d323935f39d4660c52b26b96446a7b33aef10" +"checksum smallvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1347484b6f8bc4b32a9323d9800b6d934376391002ad9c528cc659fe8afc08ee" +"checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8" "checksum snappy-sys 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" +"checksum stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc7f6353c2ee5407358d063a14cccc1630804527090a6fb5a9489ce4924280fb" "checksum syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6dfd71b2be5a58ee30a6f8ea355ba8290d397131c00dfa55c3d34e6e13db5101" "checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" +"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 tempfile 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11ce2fe9db64b842314052e2421ac61a73ce41b898dc8e3750398b219c5fc1e0" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" -"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" +"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" "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 tokio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d00555353b013e170ed8bc4e13f648a317d1fd12157dbcae13f7013f6cf29f5" +"checksum tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8ee337e5f4e501fc32966fec6fe0ca0cc1c237b0b1b14a335f8bfe3c5f06e286" +"checksum tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "881e9645b81c2ce95fcb799ded2c29ffb9f25ef5bef909089a420e5961dd8ccb" "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" +"checksum tokio-current-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f785265962bde425bf3b77dd6abac6674b8c6d5e8831427383aa9c56c5210e1" +"checksum tokio-dns-unofficial 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb9bf62ca2c53bf2f2faec3e48a98b6d8c9577c27011cb0203a4beacdc8ab328" "checksum tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8cac2a7883ff3567e9d66bb09100d09b33d90311feca0206c7ca034bc0c55113" "checksum tokio-fs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76766830bbf9a2d5bfb50c95350d56a2e79e2c80f675967fff448bc615899708" -"checksum tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6af9eb326f64b2d6b68438e1953341e00ab3cf54de7e35d92bfc73af8555313a" +"checksum tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a5c9635ee806f26d302b8baa1e145689a280d8f5aa8d0552e7344808da54cc21" "checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389" "checksum tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3cedc8e5af5131dc3423ffa4f877cce78ad25259a9a62de0613735a13ebc64b" -"checksum tokio-retry 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f05746ae87dca83a2016b4f5dba5b237b897dd12fd324f60afe282112f16969a" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" "checksum tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec9b094851aadd2caf83ba3ad8e8c4ce65a42104f7b94d9e6550023f0407853f" -"checksum tokio-threadpool 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5783254b10c7c84a56f62c74766ef7e5b83d1f13053218c7cab8d3f2c826fa0e" -"checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc" -"checksum tokio-timer 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535fed0ccee189f3d48447587697ba3fd234b3dbbb091f0ec4613ddfec0a7c4c" +"checksum tokio-threadpool 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c3873a6d8d0b636e024e77b9a82eaab6739578a06189ecd0e731c7308fbc5d" +"checksum tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "028b94314065b90f026a21826cffd62a4e40a92cda3e5c069cc7b02e5945f5e9" "checksum tokio-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "772f4b04e560117fe3b0a53e490c16ddc8ba6ec437015d91fa385564996ed913" "checksum tokio-udp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "137bda266504893ac4774e0ec4c2108f7ccdbcb7ac8dced6305fe9e4e0b5041a" "checksum trace-time 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5aea07da6582e957c6e737eeb63a5af79e648eeeaaaba8fd9a417f1124bafa41" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -"checksum transaction-pool 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd61073aadeb282056e97180e5d0dd9774413f954bd221c07692578dab466b26" +"checksum transaction-pool 1.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be1efb673ddf49ab4a99893eb3af02f6563636033fb832c2b7f937641ad62b17" "checksum triehash 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2033893a813c70e7d8a739ca6c36dc0a7a2c913ec718d7cbf84a3837bbe3c7ce" "checksum try-lock 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2aa4715743892880f70885373966c83d73ef1b0838a664ef0c76fffd35e7c2" "checksum twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "475352206e7a290c5fccc27624a163e8d0d115f7bb60ca18a64fc9ce056d7435" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "" "checksum uint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "38051a96565903d81c9a9210ce11076b2218f3b352926baa1f5f6abbdfce8273" @@ -3402,14 +4188,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" "checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=polkadot-2)" = "" "checksum vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ed0f6789c8a85ca41bbc1c9d175422116a9869bd1cf31bb08e1493ecce60380" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c3365f36c57e5df714a34be40902b27a992eeddb9996eca52d0584611cf885d" "checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wabt 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "e902997144209c90311321b90dd658d964dd8e58b23a5919e66a1d068a0050e5" -"checksum wabt-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fc67b1d96cd7839be6996edf94be66351d83f614e9cc7c6edc33accd9f5e6529" +"checksum wabt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "182ae543249ccf2705f324d233891c1176fca142e137b55ba43d9dbfe93f18a2" +"checksum wabt-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ca77c6b934a2b32618941b2f565aac43b8cb7141378c3b4fba4d8fcdcd57da3" "checksum want 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a05d9d966753fa4b5c8db73fcab5eed4549cfe0e1e4e66911e5564a0085c35d1" -"checksum wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d19da510b59247935ad5f598357b3cc739912666d75d3d28318026478d95bbdb" +"checksum wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b4a6d379e9332b1b1f52c5a87f2481c85c7c931d8ec411963dfb8f26b1ec1e3" "checksum websocket 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eb277e7f4c23dc49176f74ae200e77651764efb2c25f56ad2d22623b63826369" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" @@ -3419,6 +4207,5 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ws 0.7.5 (git+https://github.com/tomusdrw/ws-rs)" = "" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a66b7c2281ebde13cf4391d70d4c7e5946c3c25e72a7b859ca8f677dcd0b0c61" -"checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2" -"checksum xmltree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9cfb54ca6b8f17d2377219ce485b134d53561b77e1393c7ea416f543a527431" "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" +"checksum yamux 0.1.0 (git+https://github.com/paritytech/yamux)" = "" diff --git a/Cargo.toml b/Cargo.toml index b1602fb3d270d..6b5271641edec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,12 +4,18 @@ path = "polkadot/src/main.rs" [package] name = "polkadot" -version = "0.2.0" +version = "0.3.0" authors = ["Parity Technologies "] +build = "build.rs" [dependencies] -error-chain = "0.11" +error-chain = "0.12" polkadot-cli = { path = "polkadot/cli" } +futures = "0.1" +ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" } + +[build-dependencies] +vergen = "0.1" [workspace] members = [ @@ -18,13 +24,16 @@ members = [ "polkadot/collator", "polkadot/consensus", "polkadot/executor", - "polkadot/parachain", + "polkadot/network", "polkadot/primitives", "polkadot/runtime", "polkadot/service", "polkadot/statement-table", "polkadot/transaction-pool", + "polkadot/service", + "substrate/bft", + "substrate/cli", "substrate/client", "substrate/client/db", "substrate/codec", @@ -51,7 +60,10 @@ members = [ "substrate/runtime/staking", "substrate/runtime/system", "substrate/runtime/timestamp", + "substrate/runtime/version", "substrate/serializer", + "substrate/service", + "substrate/state-db", "substrate/state-machine", "substrate/test-runtime", "substrate/telemetry", @@ -71,3 +83,13 @@ exclude = [ "substrate/pwasm-libc", "substrate/test-runtime/wasm", ] + +[badges] +travis-ci = { repository = "paritytech/polkadot", branch = "master" } +maintenance = { status = "actively-developed" } +is-it-maintained-issue-resolution = { repository = "paritytech/polkadot" } +is-it-maintained-open-issues = { repository = "paritytech/polkadot" } + +[profile.release] +# Substrate runtime requires unwinding. +panic = "unwind" diff --git a/README.adoc b/README.adoc new file mode 100644 index 0000000000000..85ee539b1e675 --- /dev/null +++ b/README.adoc @@ -0,0 +1,209 @@ += Polkadot +:Author: Polkadot developers +:Revision: 0.2.0 +:toc: +:sectnums: + +Implementation of a https://polkadot.network node in Rust. + + +== To play + +If you'd like to play with Polkadot, you'll need to install a client like this +one. First, get Rust (1.26.1 or later) and the support software if you don't already have it: + +[source, shell] +---- +curl https://sh.rustup.rs -sSf | sh +sudo apt install make clang pkg-config libssl-dev +---- + +Then, install Polkadot PoC-2: + +[source, shell] +cargo install --git https://github.com/paritytech/polkadot.git --branch v0.2 polkadot + +You'll now have a `polkadot` binary installed to your `PATH`. You can drop the +`--branch v0.2` or run `cargo install --git https://github.com/paritytech/polkadot.git polkadot` +to get the very latest version of Polkadot, but these instructions might not work in that case. + +=== Krumme Lanke Testnet + +You will connect to the global Krumme Lanke testnet by default. To do this, just use: + +[source, shell] +polkadot + +If you want to do anything on it (not that there's much to do), then you'll need +to get some Krumme Lanke DOTs. Ask in the Polkadot watercooler. + +=== Development + +You can run a simple single-node development "network" on your machine by +running in a terminal: + +[source, shell] +polkadot --dev + +You can muck around by cloning and building the http://github.com/paritytech/polka-ui and http://github.com/paritytech/polkadot-ui or just heading to https://polkadot.js.org/apps. + + +== Local Two-node Testnet + +If you want to see the multi-node consensus algorithm in action locally, then +you can create a local testnet. You'll need two terminals open. In one, run: + +[source, shell] +polkadot --chain=local --validator --key Alice -d /tmp/alice + +and in the other, run: + +[source, shell] +polkadot --chain=local --validator --key Bob -d /tmp/bob --port 30334 --bootnodes '/ip4/127.0.0.1/tcp/30333/p2p/ALICE_BOOTNODE_ID_HERE' + +Ensure you replace `ALICE_BOOTNODE_ID_HERE` with the node ID from the output of +the first terminal. + + +== Hacking on Polkadot + +If you'd actually like hack on Polkadot, you can just grab the source code and +build it. Ensure you have Rust and the support software installed: + +[source, shell] +---- +curl https://sh.rustup.rs -sSf | sh +rustup update nightly +rustup target add wasm32-unknown-unknown --toolchain nightly +rustup update stable +cargo install --git https://github.com/alexcrichton/wasm-gc +sudo apt install cmake pkg-config libssl-dev git +---- + +Then, grab the Polkadot source code: + +[source, shell] +---- +git clone https://github.com/paritytech/polkadot.git +cd polkadot +---- + +Then build the code: + +[source, shell] +---- +./build.sh # Builds the WebAssembly binaries +cargo build # Builds all native code +---- + +You can run the tests if you like: + +[source, shell] +cargo test --all + +You can start a development chain with: + +[source, shell] +cargo run -- --dev + + +== Using Docker + +=== The easiest way + +The easiest/faster option is to use the latest image. + + +.First run +Let´s first check the version we have. The first time you run this command, the polkadot docker image will be downloaded. This takes a bit of time and bandwidth, be patient: + +[source, shell] +docker run --rm -it chevdor/polkadot:latest ./version + + +.Polkadot arguments +You can also pass any argument/flag that polkadot supports: + +[source, shell] +docker run --rm -it chevdor/polkadot:latest polkadot --name "PolkaDocker" + + +.Run as deamon +Once you are done experimenting and picking the best node name :) you can start polkadot as daemon, exposes the polkadot ports and mount a volume that will keep your blockchain data locally: + +[source, shell] +docker run -d -p 30333:30333 -p 9933:9933 -p 9944:9944 -v /my/local/folder:/data chevdor/polkadot:latest polkadot + +.Docker image update +If you have an image such as `latest` locally, docker will *not* bother downloading the very latest that may be available. +To update: + +- stop and delete your containers (`docker stop ...` `docker rm ...`) +- delete your previous image (`docker rmi chevdor/polkadot:latest`) +- run as daemon again, the very latest image will be downloaded again + +=== Build your own image + +To get up and running with the smallest footprint on your system, you may use the Polkadot Docker image. +You can either build it yourself (it takes a while...): + +[source, shell] +---- +ccd docker +./build.sh +---- + +=== Reporting issues + +If you run into issues with polkadot when using docker, please run the following command +(replace the tag with the appropriate one if you do not use latest): + +[source, shell] +docker run --rm -it chevdor/polkadot:latest version + +This will show you the polkadot version as well as the git commit ref that was used to build your container. +Just paste that in the issue you create. + + +== Shell completion + +The Polkadot cli command supports shell auto-completion. For this to work, you will need to run the completion script matching you build and system. + +Assuming you built a release version using `cargo build --release` and use `bash` run the following: + +[source, shell] +source target/release/completion-scripts/polkadot.bash + +You can find completion scripts for: +- bash +- fish +- zsh +- elvish +- powershell + +To make this change persistent, you can proceed as follow: + +=== First install + +[source, shell] +---- +COMPL_DIR=$HOME/.completion +mkdir -p $COMPL_DIR +cp -f target/release/completion-scripts/polkadot.bash $COMPL_DIR/ +echo "source $COMPL_DIR/polkadot.bash" >> $HOME/.bash_profile +source $HOME/.bash_profile +---- + +=== Update + +When you build a new version of Polkadot, the following will ensure you auto-completion script matches the current binary: + +[source, shell] +---- +COMPL_DIR=$HOME/.completion +mkdir -p $COMPL_DIR +cp -f target/release/completion-scripts/polkadot.bash $COMPL_DIR/ +source $HOME/.bash_profile +---- + +include::doc/packages.adoc[] diff --git a/README.md b/README.md deleted file mode 100644 index ccf8d7b165937..0000000000000 --- a/README.md +++ /dev/null @@ -1,104 +0,0 @@ -# Polkadot - -Implementation of a https://polkadot.io node in Rust. - -## To play - -If you'd like to play with Polkadot, you'll need to install a client like this -one. First, get Rust (1.26.1 or later) and the support software if you don't already have it: - -``` -curl https://sh.rustup.rs -sSf | sh -sudo apt install make clang -``` - -Then, install Polkadot PoC-1: - -``` -cargo install --git https://github.com/paritytech/polkadot.git --branch v0.1 -``` - -You'll now have a `polkadot` binary installed to your `PATH`. You can drop the -`--branch v0.1` or run `cargo install --git https://github.com/paritytech/polkadot.git polkadot` -to get the very latest version of Polkadot, but these instructions will not work in that case. - -### Development - -You can run a simple single-node development "network" on your machine by -running in a terminal: - -``` -polkadot --chain=dev --validator --key Alice -``` - -You can muck around by cloning and building the http://github.com/paritytech/polka-ui and http://github.com/paritytech/polkadot-ui or just heading to https://polkadot.js.org/apps. - -### PoC-1 Testnet - -You can also connect to the global PoC-1 testnet. To do this, just use: - -``` -polkadot --chain=poc-1 -``` - -If you want to do anything on it (not that there's much to do), then you'll need -to get some PoC-1 testnet DOTs. Ask in the Polkadot watercooler. - -## Local Two-node Testnet - -If you want to see the multi-node consensus algorithm in action locally, then -you can create a local testnet. You'll need two terminals open. In one, run: - -``` -polkadot --chain=local --validator --key Alice -d /tmp/alice -``` - -and in the other, run: - -``` -polkadot --chain=local --validator --key Bob -d /tmp/bob --port 30334 --bootnodes 'enode://ALICE_BOOTNODE_ID_HERE@127.0.0.1:30333' -``` - -Ensure you replace `ALICE_BOOTNODE_ID_HERE` with the node ID from the output of -the first terminal. - -## Hacking on Polkadot - -If you'd actually like hack on Polkadot, you can just grab the source code and -build it. Ensure you have Rust and the support software installed: - -``` -curl https://sh.rustup.rs -sSf | sh -rustup update nightly -rustup target add wasm32-unknown-unknown --toolchain nightly -rustup update stable -cargo install --git https://github.com/alexcrichton/wasm-gc -cargo install --git https://github.com/pepyakin/wasm-export-table.git -sudo apt install cmake pkg-config libssl-dev -``` - -Then, grab the Polkadot source code: - -``` -git clone https://github.com/paritytech/polkadot.git -cd polkadot -``` - -Then build the code: - -``` -./build.sh # Builds the WebAssembly binaries -cargo build # Builds all native code -``` - -You can run the tests if you like: - -``` -cargo test --all -``` - -You can start a development chain with: - -``` -cargo run -- --chain=dev --validator --key Alice -``` diff --git a/build.rs b/build.rs new file mode 100644 index 0000000000000..efe19e0a8da33 --- /dev/null +++ b/build.rs @@ -0,0 +1,26 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +extern crate vergen; + +use vergen::{vergen, OutputFns}; + +const ERROR_MSG: &'static str = "Failed to generate metadata files"; + +fn main() { + vergen(OutputFns::all()).expect(ERROR_MSG); + println!("cargo:rerun-if-changed=.git/HEAD"); +} diff --git a/build.sh b/build.sh index 8cac3c5e5c1af..f2ced1300ac03 100755 --- a/build.sh +++ b/build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script assumes that all pre-requisites are installed. diff --git a/ci/publish-wasm.sh b/ci/publish-wasm.sh index 3b9ffa07bdba1..ee1db2942f722 100755 --- a/ci/publish-wasm.sh +++ b/ci/publish-wasm.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Publish wasm binaries into the special repository. # This script assumes that wasm binaries have already been built. diff --git a/ci/script.sh b/ci/script.sh index 4c67182987d8b..8d8ded7d7bdd8 100755 --- a/ci/script.sh +++ b/ci/script.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eux diff --git a/common.sh b/common.sh index ba131bd969b5e..847aa23820439 100644 --- a/common.sh +++ b/common.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash ROOT=`dirname "$0"` diff --git a/demo/cli/Cargo.toml b/demo/cli/Cargo.toml index 6f488c2ad84e7..0a9ba64315f98 100644 --- a/demo/cli/Cargo.toml +++ b/demo/cli/Cargo.toml @@ -10,10 +10,10 @@ ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" } ed25519 = { path = "../../substrate/ed25519" } env_logger = "0.4" futures = "0.1.17" -error-chain = "0.11" +error-chain = "0.12" hex-literal = "0.1" log = "0.3" -tokio-core = "0.1.12" +tokio = "0.1.7" triehash = "0.1" substrate-client = { path = "../../substrate/client" } substrate-codec = { path = "../../substrate/codec" } diff --git a/demo/cli/src/lib.rs b/demo/cli/src/lib.rs index 0267ac35607a9..08834541f52bf 100644 --- a/demo/cli/src/lib.rs +++ b/demo/cli/src/lib.rs @@ -22,7 +22,7 @@ extern crate ctrlc; extern crate ed25519; extern crate env_logger; extern crate futures; -extern crate tokio_core; +extern crate tokio; extern crate triehash; extern crate substrate_client as client; extern crate substrate_codec as codec; @@ -49,20 +49,36 @@ pub mod error; use std::sync::Arc; use demo_primitives::Hash; -use demo_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfig, - SessionConfig, StakingConfig, BuildStorage}; -use demo_runtime::{Block, UncheckedExtrinsic}; +use demo_runtime::{Block, BlockId, UncheckedExtrinsic, GenesisConfig, + ConsensusConfig, CouncilConfig, DemocracyConfig, SessionConfig, StakingConfig, + TimestampConfig}; use futures::{Future, Sink, Stream}; +use tokio::runtime::Runtime; +use demo_executor::NativeExecutor; struct DummyPool; -impl extrinsic_pool::api::ExtrinsicPool for DummyPool { +impl extrinsic_pool::api::ExtrinsicPool for DummyPool { type Error = extrinsic_pool::txpool::Error; - fn submit(&self, _: Vec) + fn submit(&self, _block: BlockId, _: Vec) -> Result, Self::Error> { Err("unimplemented".into()) } + + fn submit_and_watch(&self, _block: BlockId, _: UncheckedExtrinsic) + -> Result, Self::Error> + { + Err("unimplemented".into()) + } + + fn light_status(&self) -> extrinsic_pool::txpool::LightStatus { + unreachable!() + } + + fn import_notification_stream(&self) -> extrinsic_pool::api::EventStream { + unreachable!() + } } struct DummySystem; @@ -98,19 +114,19 @@ pub fn run(args: I) -> error::Result<()> where init_logger(log_pattern); // Create client - let executor = demo_executor::Executor::new(); + let executor = NativeExecutor::with_heap_pages(8, 8); let god_key = hex!["3d866ec8a9190c8343c2fc593d21d8a6d0c5c4763aaab2349de3a6111d64d124"]; - let genesis_storage = GenesisConfig { + let genesis_config = GenesisConfig { consensus: Some(ConsensusConfig { code: vec![], // TODO - authorities: vec![god_key.clone()], + authorities: vec![god_key.clone().into()], }), system: None, - // block_time: 5, // 5 second block time. session: Some(SessionConfig { validators: vec![god_key.clone().into()], session_length: 720, // that's 1 hour per session. + broken_percent_late: 30, }), staking: Some(StakingConfig { current_era: 0, @@ -119,13 +135,14 @@ pub fn run(args: I) -> error::Result<()> where transaction_byte_fee: 1, transfer_fee: 0, creation_fee: 0, - contract_fee: 0, reclaim_rebate: 0, existential_deposit: 500, balances: vec![(god_key.clone().into(), 1u64 << 63)].into_iter().collect(), validator_count: 12, sessions_per_era: 24, // 24 hours per era. bonding_duration: 90, // 90 days per bond. + early_era_slash: 10000, + session_reward: 100, }), democracy: Some(DemocracyConfig { launch_period: 120 * 24 * 14, // 2 weeks per public referendum @@ -147,15 +164,18 @@ pub fn run(args: I) -> error::Result<()> where cooloff_period: 90 * 120 * 24, // 90 day cooling off period if council member vetoes a proposal. voting_period: 7 * 120 * 24, // 7 day voting period for council members. }), - }.build_storage(); - - let client = Arc::new(client::new_in_mem::<_, Block, _>(executor, genesis_storage)?); - let mut core = ::tokio_core::reactor::Core::new().expect("Unable to spawn event loop."); + timestamp: Some(TimestampConfig { + period: 5, // 5 second block time. + }), + }; + let client = Arc::new(client::new_in_mem::, Block, _>(executor, genesis_config)?); + let mut runtime = Runtime::new()?; let _rpc_servers = { let handler = || { - let chain = rpc::apis::chain::Chain::new(client.clone(), core.remote()); - rpc::rpc_handler::(client.clone(), chain, Arc::new(DummyPool), DummySystem) + let chain = rpc::apis::chain::Chain::new(client.clone(), runtime.executor()); + let author = rpc::apis::author::Author::new(client.clone(), Arc::new(DummyPool), runtime.executor()); + rpc::rpc_handler::(client.clone(), chain, author, DummySystem) }; let http_address = "127.0.0.1:9933".parse().unwrap(); let ws_address = "127.0.0.1:9944".parse().unwrap(); @@ -172,7 +192,8 @@ pub fn run(args: I) -> error::Result<()> where ctrlc::CtrlC::set_handler(move || { exit_send.clone().send(()).wait().expect("Error sending exit notification"); }); - core.run(exit.into_future()).expect("Error running informant event loop"); + + runtime.block_on(exit.into_future()).expect("Error running informant event loop"); return Ok(()) } diff --git a/demo/executor/Cargo.toml b/demo/executor/Cargo.toml index 2cdc0088399a3..c154a7c16501d 100644 --- a/demo/executor/Cargo.toml +++ b/demo/executor/Cargo.toml @@ -22,3 +22,4 @@ substrate-keyring = { path = "../../substrate/keyring" } substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" } substrate-runtime-staking = { path = "../../substrate/runtime/staking" } substrate-runtime-system = { path = "../../substrate/runtime/system" } +substrate-runtime-consensus = { path = "../../substrate/runtime/consensus" } diff --git a/demo/executor/src/lib.rs b/demo/executor/src/lib.rs index 538a5fc0f2aad..24ec4e5f573c9 100644 --- a/demo/executor/src/lib.rs +++ b/demo/executor/src/lib.rs @@ -32,16 +32,18 @@ extern crate triehash; #[cfg(test)] extern crate substrate_runtime_support as runtime_support; #[cfg(test)] extern crate substrate_runtime_staking as staking; #[cfg(test)] extern crate substrate_runtime_system as system; +#[cfg(test)] extern crate substrate_runtime_consensus as consensus; #[cfg(test)] #[macro_use] extern crate hex_literal; -native_executor_instance!(pub Executor, demo_runtime::api::dispatch, include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm")); +pub use substrate_executor::NativeExecutor; +native_executor_instance!(pub Executor, demo_runtime::api::dispatch, demo_runtime::VERSION, include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm")); #[cfg(test)] mod tests { use runtime_io; use super::Executor; - use substrate_executor::WasmExecutor; - use codec::{Slicable, Joiner}; + use substrate_executor::{WasmExecutor, NativeExecutionDispatch}; + use codec::{Encode, Decode, Joiner}; use keyring::Keyring; use runtime_support::{Hashable, StorageValue, StorageMap}; use state_machine::{CodeExecutor, TestExternalities}; @@ -49,7 +51,7 @@ mod tests { use demo_primitives::{Hash, BlockNumber, AccountId}; use runtime_primitives::traits::Header as HeaderT; use runtime_primitives::{ApplyOutcome, ApplyError, ApplyResult, MaybeUnsigned}; - use {staking, system}; + use {staking, system, consensus}; use demo_runtime::{Header, Block, UncheckedExtrinsic, Extrinsic, Call, Concrete, Staking, BuildStorage, GenesisConfig, SessionConfig, StakingConfig, BareExtrinsic}; use ed25519::{Public, Pair}; @@ -92,6 +94,10 @@ mod tests { Header::new(n, Default::default(), Default::default(), [69; 32].into(), Default::default()) } + fn executor() -> ::substrate_executor::NativeExecutor { + ::substrate_executor::NativeExecutor::with_heap_pages(8, 8) + } + #[test] fn panic_execution_with_foreign_code_gives_error() { let mut t: TestExternalities = map![ @@ -104,9 +110,9 @@ mod tests { twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; - let r = Executor::new().call(&mut t, BLOATY_CODE, "initialise_block", &vec![].and(&from_block_number(1u64))); + let r = executor().call(&mut t, BLOATY_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0; assert!(r.is_ok()); - let v = Executor::new().call(&mut t, BLOATY_CODE, "apply_extrinsic", &vec![].and(&xt())).unwrap(); + let v = executor().call(&mut t, BLOATY_CODE, "apply_extrinsic", &vec![].and(&xt()), true).0.unwrap(); let r = ApplyResult::decode(&mut &v[..]).unwrap(); assert_eq!(r, Err(ApplyError::CantPay)); } @@ -123,9 +129,9 @@ mod tests { twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; - let r = Executor::new().call(&mut t, COMPACT_CODE, "initialise_block", &vec![].and(&from_block_number(1u64))); + let r = executor().call(&mut t, COMPACT_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0; assert!(r.is_ok()); - let v = Executor::new().call(&mut t, COMPACT_CODE, "apply_extrinsic", &vec![].and(&xt())).unwrap(); + let v = executor().call(&mut t, COMPACT_CODE, "apply_extrinsic", &vec![].and(&xt()), true).0.unwrap(); let r = ApplyResult::decode(&mut &v[..]).unwrap(); assert_eq!(r, Err(ApplyError::CantPay)); } @@ -142,9 +148,9 @@ mod tests { twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; - let r = Executor::new().call(&mut t, COMPACT_CODE, "initialise_block", &vec![].and(&from_block_number(1u64))); + let r = executor().call(&mut t, COMPACT_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0; assert!(r.is_ok()); - let r = Executor::new().call(&mut t, COMPACT_CODE, "apply_extrinsic", &vec![].and(&xt())); + let r = executor().call(&mut t, COMPACT_CODE, "apply_extrinsic", &vec![].and(&xt()), true).0; assert!(r.is_ok()); runtime_io::with_externalities(&mut t, || { @@ -165,9 +171,9 @@ mod tests { twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; - let r = Executor::new().call(&mut t, BLOATY_CODE, "initialise_block", &vec![].and(&from_block_number(1u64))); + let r = executor().call(&mut t, BLOATY_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0; assert!(r.is_ok()); - let r = Executor::new().call(&mut t, BLOATY_CODE, "apply_extrinsic", &vec![].and(&xt())); + let r = executor().call(&mut t, BLOATY_CODE, "apply_extrinsic", &vec![].and(&xt()), true).0; assert!(r.is_ok()); runtime_io::with_externalities(&mut t, || { @@ -185,6 +191,7 @@ mod tests { session: Some(SessionConfig { session_length: 2, validators: vec![One.to_raw_public().into(), Two.to_raw_public().into(), three], + broken_percent_late: 100, }), staking: Some(StakingConfig { sessions_per_era: 2, @@ -198,12 +205,14 @@ mod tests { existential_deposit: 0, transfer_fee: 0, creation_fee: 0, - contract_fee: 0, reclaim_rebate: 0, + early_era_slash: 0, + session_reward: 0, }), democracy: Some(Default::default()), council: Some(Default::default()), - }.build_storage() + timestamp: Some(Default::default()), + }.build_storage().unwrap() } fn construct_block(number: BlockNumber, parent_hash: Hash, state_root: Hash, extrinsics: Vec) -> (Vec, Hash) { @@ -220,7 +229,7 @@ mod tests { UncheckedExtrinsic::new(extrinsic, signature) }).collect::>(); - let extrinsics_root = ordered_trie_root(extrinsics.iter().map(Slicable::encode)).0.into(); + let extrinsics_root = ordered_trie_root(extrinsics.iter().map(Encode::encode)).0.into(); let header = Header { parent_hash, @@ -238,7 +247,7 @@ mod tests { construct_block( 1, [69u8; 32].into(), - hex!("4f7a61bceecddc19d49fbee53f82402c2a8727c1b2aeb5e5070a59f0777a203b").into(), + hex!("b97d52254fc967bb94bed485de6a738e9fad05decfda3453711677b8becf6d0a").into(), vec![BareExtrinsic { signed: alice(), index: 0, @@ -251,7 +260,7 @@ mod tests { construct_block( 2, block1().1, - hex!("67c588603dd727601263cf8d6138a2003ffc0df793c5ea34e7defc945da24bf0").into(), + hex!("a1f018d2faa339f72f5ee29050b4670d971e2e271cc06c41ee9cbe1f4c6feec9").into(), vec![ BareExtrinsic { signed: bob(), @@ -267,18 +276,31 @@ mod tests { ) } + fn block1big() -> (Vec, Hash) { + construct_block( + 1, + [69u8; 32].into(), + hex!("41d07010f49aa29b2c9aca542cbaa6f59aafd3dda53cdf711c51ddb7d386912e").into(), + vec![BareExtrinsic { + signed: alice(), + index: 0, + function: Call::Consensus(consensus::Call::remark(vec![0; 60000])), + }] + ) + } + #[test] fn full_native_block_import_works() { let mut t = new_test_ext(); - Executor::new().call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap(); + executor().call(&mut t, COMPACT_CODE, "execute_block", &block1().0, true).0.unwrap(); runtime_io::with_externalities(&mut t, || { assert_eq!(Staking::voting_balance(&alice()), 41); assert_eq!(Staking::voting_balance(&bob()), 69); }); - Executor::new().call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap(); + executor().call(&mut t, COMPACT_CODE, "execute_block", &block2().0, true).0.unwrap(); runtime_io::with_externalities(&mut t, || { assert_eq!(Staking::voting_balance(&alice()), 30); @@ -290,14 +312,14 @@ mod tests { fn full_wasm_block_import_works() { let mut t = new_test_ext(); - WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap(); + WasmExecutor::new(8, 8).call(&mut t, COMPACT_CODE, "execute_block", &block1().0, true).0.unwrap(); runtime_io::with_externalities(&mut t, || { assert_eq!(Staking::voting_balance(&alice()), 41); assert_eq!(Staking::voting_balance(&bob()), 69); }); - WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap(); + WasmExecutor::new(8, 8).call(&mut t, COMPACT_CODE, "execute_block", &block2().0, true).0.unwrap(); runtime_io::with_externalities(&mut t, || { assert_eq!(Staking::voting_balance(&alice()), 30); @@ -305,6 +327,30 @@ mod tests { }); } + #[test] + fn wasm_big_block_import_fails() { + let mut t = new_test_ext(); + + let r = WasmExecutor::new(8, 8).call(&mut t, COMPACT_CODE, "execute_block", &block1big().0, true).0; + assert!(!r.is_ok()); + } + + #[test] + fn native_big_block_import_succeeds() { + let mut t = new_test_ext(); + + let r = Executor::with_heap_pages(8, 8).call(&mut t, COMPACT_CODE, "execute_block", &block1big().0, true).0; + assert!(r.is_ok()); + } + + #[test] + fn native_big_block_import_fails_on_fallback() { + let mut t = new_test_ext(); + + let r = Executor::with_heap_pages(8, 8).call(&mut t, COMPACT_CODE, "execute_block", &block1big().0, false).0; + assert!(!r.is_ok()); + } + #[test] fn panic_execution_gives_error() { let mut t: TestExternalities = map![ @@ -318,9 +364,9 @@ mod tests { ]; let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm"); - let r = WasmExecutor.call(&mut t, &foreign_code[..], "initialise_block", &vec![].and(&from_block_number(1u64))); + let r = WasmExecutor::new(8, 8).call(&mut t, &foreign_code[..], "initialise_block", &vec![].and(&from_block_number(1u64)), true).0; assert!(r.is_ok()); - let r = WasmExecutor.call(&mut t, &foreign_code[..], "apply_extrinsic", &vec![].and(&xt())).unwrap(); + let r = WasmExecutor::new(8, 8).call(&mut t, &foreign_code[..], "apply_extrinsic", &vec![].and(&xt()), true).0.unwrap(); let r = ApplyResult::decode(&mut &r[..]).unwrap(); assert_eq!(r, Err(ApplyError::CantPay)); } @@ -338,9 +384,9 @@ mod tests { ]; let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm"); - let r = WasmExecutor.call(&mut t, &foreign_code[..], "initialise_block", &vec![].and(&from_block_number(1u64))); + let r = WasmExecutor::new(8, 8).call(&mut t, &foreign_code[..], "initialise_block", &vec![].and(&from_block_number(1u64)), true).0; assert!(r.is_ok()); - let r = WasmExecutor.call(&mut t, &foreign_code[..], "apply_extrinsic", &vec![].and(&xt())).unwrap(); + let r = WasmExecutor::new(8, 8).call(&mut t, &foreign_code[..], "apply_extrinsic", &vec![].and(&xt()), true).0.unwrap(); let r = ApplyResult::decode(&mut &r[..]).unwrap(); assert_eq!(r, Ok(ApplyOutcome::Success)); diff --git a/demo/runtime/Cargo.toml b/demo/runtime/Cargo.toml index cb9988ffc9e01..e541dcb029e4c 100644 --- a/demo/runtime/Cargo.toml +++ b/demo/runtime/Cargo.toml @@ -25,6 +25,7 @@ substrate-runtime-session = { path = "../../substrate/runtime/session" } substrate-runtime-staking = { path = "../../substrate/runtime/staking" } substrate-runtime-system = { path = "../../substrate/runtime/system" } substrate-runtime-timestamp = { path = "../../substrate/runtime/timestamp" } +substrate-runtime-version = { path = "../../substrate/runtime/version" } demo-primitives = { path = "../primitives" } [features] @@ -44,6 +45,7 @@ std = [ "substrate-runtime-staking/std", "substrate-runtime-system/std", "substrate-runtime-timestamp/std", + "substrate-runtime-version/std", "demo-primitives/std", "serde_derive", "serde/std", diff --git a/demo/runtime/src/lib.rs b/demo/runtime/src/lib.rs index 77bcad3d25eb6..3f5165ef2998b 100644 --- a/demo/runtime/src/lib.rs +++ b/demo/runtime/src/lib.rs @@ -43,12 +43,15 @@ extern crate substrate_runtime_session as session; extern crate substrate_runtime_staking as staking; extern crate substrate_runtime_system as system; extern crate substrate_runtime_timestamp as timestamp; +#[macro_use] +extern crate substrate_runtime_version as version; extern crate demo_primitives; use rstd::prelude::*; use demo_primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, SessionKey, Signature}; use runtime_primitives::generic; use runtime_primitives::traits::{Convert, HasPublicAux, BlakeTwo256}; +use version::RuntimeVersion; #[cfg(any(feature = "std", test))] pub use runtime_primitives::BuildStorage; @@ -59,6 +62,22 @@ pub use runtime_primitives::BuildStorage; /// Concrete runtime type used to parameterize the various modules. pub struct Concrete; +/// Runtime version. +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: ver_str!("demo"), + impl_name: ver_str!("parity-demo"), + authoring_version: 1, + spec_version: 1, + impl_version: 0, +}; + +/// Version module for this concrete runtime. +pub type Version = version::Module; + +impl version::Trait for Concrete { + const VERSION: RuntimeVersion = VERSION; +} + impl HasPublicAux for Concrete { type PublicAux = AccountId; } @@ -85,9 +104,9 @@ impl consensus::Trait for Concrete { pub type Consensus = consensus::Module; impl timestamp::Trait for Concrete { - const SET_POSITION: u32 = 0; + const TIMESTAMP_SET_POSITION: u32 = 0; - type Value = u64; + type Moment = u64; } /// Timestamp module for this concrete runtime. @@ -97,12 +116,13 @@ pub type Timestamp = timestamp::Module; pub struct SessionKeyConversion; impl Convert for SessionKeyConversion { fn convert(a: AccountId) -> SessionKey { - a.0 + a.0.into() } } impl session::Trait for Concrete { type ConvertAccountIdToSessionKey = SessionKeyConversion; + type OnSessionChange = Staking; } /// Session module for this concrete runtime. @@ -110,8 +130,8 @@ pub type Session = session::Module; impl staking::Trait for Concrete { type Balance = Balance; - type DetermineContractAddress = BlakeTwo256; type AccountIndex = AccountIndex; + type OnAccountKill = (); } /// Staking module for this concrete runtime. @@ -162,6 +182,8 @@ pub type Address = staking::Address; pub type Header = generic::Header>; /// Block type as expected by this runtime. pub type Block = generic::Block; +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Extrinsic type as expected by this runtime. This is not the type that is signed. @@ -180,11 +202,13 @@ impl_outer_config! { StakingConfig => staking, DemocracyConfig => democracy, CouncilConfig => council, + TimestampConfig => timestamp, } } pub mod api { impl_stubs!( + version => |()| super::Version::version(), authorities => |()| super::Consensus::authorities(), initialise_block => |header| super::Executive::initialise_block(&header), apply_extrinsic => |extrinsic| super::Executive::apply_extrinsic(extrinsic), diff --git a/demo/runtime/wasm/Cargo.lock b/demo/runtime/wasm/Cargo.lock index dfaa019b250c8..d5eac31f66037 100644 --- a/demo/runtime/wasm/Cargo.lock +++ b/demo/runtime/wasm/Cargo.lock @@ -137,6 +137,7 @@ dependencies = [ "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", "substrate-runtime-timestamp 0.1.0", + "substrate-runtime-version 0.1.0", ] [[package]] @@ -172,11 +173,6 @@ dependencies = [ name = "environmental" version = "0.1.0" -[[package]] -name = "error-chain" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "ethbloom" version = "0.5.0" @@ -329,16 +325,6 @@ dependencies = [ "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "kvdb" -version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#dec390a89fe038337399315daf15e628ffbb4d8e" -dependencies = [ - "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)", -] - [[package]] name = "lazy_static" version = "0.2.11" @@ -402,6 +388,11 @@ dependencies = [ "rlp 0.2.1 (git+https://github.com/paritytech/parity.git)", ] +[[package]] +name = "nan-preserving-float" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "nodrop" version = "0.1.12" @@ -430,17 +421,7 @@ dependencies = [ [[package]] name = "parity-wasm" -version = "0.27.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-wasm" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -535,16 +516,6 @@ dependencies = [ name = "pwasm-libc" version = "0.1.0" -[[package]] -name = "pwasm-utils" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "quote" version = "0.6.3" @@ -759,7 +730,7 @@ dependencies = [ "substrate-runtime-std 0.1.0", "twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)", - "wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -778,17 +749,6 @@ dependencies = [ "substrate-runtime-system 0.1.0", ] -[[package]] -name = "substrate-runtime-contract" -version = "0.1.0" -dependencies = [ - "parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pwasm-utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-codec 0.1.0", - "substrate-runtime-sandbox 0.1.0", - "substrate-runtime-std 0.1.0", -] - [[package]] name = "substrate-runtime-council" version = "0.1.0" @@ -866,6 +826,7 @@ name = "substrate-runtime-primitives" version = "0.1.0" dependencies = [ "integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", @@ -885,7 +846,7 @@ dependencies = [ "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-std 0.1.0", - "wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -905,6 +866,7 @@ dependencies = [ "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", + "substrate-runtime-timestamp 0.1.0", ] [[package]] @@ -919,7 +881,6 @@ dependencies = [ "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-consensus 0.1.0", - "substrate-runtime-contract 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-sandbox 0.1.0", @@ -927,6 +888,7 @@ dependencies = [ "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", + "substrate-runtime-timestamp 0.1.0", ] [[package]] @@ -977,6 +939,7 @@ dependencies = [ "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-std 0.1.0", @@ -984,6 +947,17 @@ dependencies = [ "substrate-runtime-system 0.1.0", ] +[[package]] +name = "substrate-runtime-version" +version = "0.1.0" +dependencies = [ + "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", +] + [[package]] name = "substrate-state-machine" version = "0.1.0" @@ -992,7 +966,6 @@ dependencies = [ "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.1 (git+https://github.com/paritytech/parity.git)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity.git)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "memorydb 0.1.1 (git+https://github.com/paritytech/parity.git)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1134,12 +1107,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasmi" -version = "0.1.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.27.6 (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.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1179,7 +1153,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" -"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386" "checksum ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum ethcore-logger 1.12.0 (git+https://github.com/paritytech/parity.git)" = "" @@ -1197,7 +1170,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)" = "" "checksum keccak-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b7f51f30d7986536accaec4a6a288008dfb3dbffe8a2863a65292bc395a3ae7" "checksum keccak-hash 0.1.2 (git+https://github.com/paritytech/parity.git)" = "" -"checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739" "checksum libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)" = "ac8ebf8343a981e2fa97042b14768f02ed3e1d602eac06cae6166df3c8ced206" @@ -1207,12 +1179,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" "checksum memorydb 0.1.1 (git+https://github.com/paritytech/parity.git)" = "" +"checksum nan-preserving-float 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34d4f00fcc2f4c9efa8cc971db0da9e28290e28e97af47585e48691ef10ff31f" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum parity-wasm 0.27.6 (registry+https://github.com/rust-lang/crates.io-index)" = "bd4dc02a80a0315b109e48992c46942c79bcdb8fac416dd575d330ed9ced6cbd" -"checksum parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41083957b80abb8a01fac4d2773d5f92653aed8f0b740c8d3da1da62c7857abe" +"checksum parity-wasm 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1c91199d14bd5b78ecade323d4a891d094799749c1b9e82d9c590c2e2849a40" "checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" "checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" @@ -1221,7 +1193,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0" "checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892" "checksum proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1fa93823f53cfd0f5ac117b189aed6cfdfb2cfc0a9d82e956dd7927595ed7d46" -"checksum pwasm-utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3a822d2a1624b10c46572c231c149575bcc261c37d84fd3f1a2f5ae1f65515" "checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" @@ -1260,7 +1231,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d19da510b59247935ad5f598357b3cc739912666d75d3d28318026478d95bbdb" +"checksum wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b4a6d379e9332b1b1f52c5a87f2481c85c7c931d8ec411963dfb8f26b1ec1e3" "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/demo/runtime/wasm/Cargo.toml b/demo/runtime/wasm/Cargo.toml index 32af7412f4b2c..8490777097eef 100644 --- a/demo/runtime/wasm/Cargo.toml +++ b/demo/runtime/wasm/Cargo.toml @@ -23,6 +23,7 @@ substrate-runtime-session = { path = "../../../substrate/runtime/session", defau substrate-runtime-staking = { path = "../../../substrate/runtime/staking", default-features = false } substrate-runtime-system = { path = "../../../substrate/runtime/system", default-features = false } substrate-runtime-timestamp = { path = "../../../substrate/runtime/timestamp", default-features = false } +substrate-runtime-version = { path = "../../../substrate/runtime/version", default-features = false } demo-primitives = { path = "../../primitives", default-features = false } [features] @@ -43,6 +44,7 @@ std = [ "substrate-runtime-staking/std", "substrate-runtime-system/std", "substrate-runtime-timestamp/std", + "substrate-runtime-version/std", "demo-primitives/std", ] diff --git a/demo/runtime/wasm/build.sh b/demo/runtime/wasm/build.sh index 093e8c1a8a21b..0769faeba9b3e 100755 --- a/demo/runtime/wasm/build.sh +++ b/demo/runtime/wasm/build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e cargo +nightly build --target=wasm32-unknown-unknown --release diff --git a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm index 702eed6d580d7..353df1156ad7d 100644 Binary files a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm and b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm differ diff --git a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm index da26399725e23..604500c98b590 100755 Binary files a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm and b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm differ diff --git a/doc/packages.adoc b/doc/packages.adoc new file mode 100644 index 0000000000000..f21c307077a98 --- /dev/null +++ b/doc/packages.adoc @@ -0,0 +1,33 @@ + +== Cargo Packages + +:leveloffset: +2 + +include::../polkadot/api/README.adoc[] + +include::../polkadot/cli/README.adoc[] + +include::../polkadot/collator/README.adoc[] + +include::../polkadot/consensus/README.adoc[] + +include::../polkadot/executor/README.adoc[] + +include::../polkadot/network/README.adoc[] + +include::../polkadot/parachain/README.adoc[] + +include::../polkadot/primitives/README.adoc[] + +include::../polkadot/runtime/README.adoc[] + +include::../polkadot/service/README.adoc[] + +include::../polkadot/src/README.adoc[] + +include::../polkadot/statement-table/README.adoc[] + +include::../polkadot/transaction-pool/README.adoc[] + +:leveloffset: -2 + diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000000000..dfc4ff77877b1 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,33 @@ +FROM phusion/baseimage:0.10.1 +LABEL maintainer "chevdor@gmail.com" + +ARG PROFILE=release + +RUN mkdir -p polkadot && \ + apt-get update && \ + apt-get upgrade -y && \ + apt-get install -y cmake pkg-config libssl-dev git && \ + apt-get clean && \ + mkdir -p /root/.local/share/Polkadot && \ + ln -s /root/.local/share/Polkadot /data + +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y && \ + export PATH=$PATH:$HOME/.cargo/bin && \ + rustup update nightly && \ + rustup target add wasm32-unknown-unknown --toolchain nightly && \ + rustup update stable && \ + cargo install --git https://github.com/alexcrichton/wasm-gc && \ + git clone https://github.com/paritytech/polkadot.git && \ + cd polkadot && \ + ./build.sh && \ + cargo build --$PROFILE && \ + mv target/$PROFILE/polkadot /usr/local/bin && \ + cargo clean && \ + rm -rf /root/.cargo /root/.rustup /tmp/* + +COPY version /polkadot +WORKDIR /polkadot +EXPOSE 30333 9933 9944 +VOLUME ["/data"] + +CMD ["/bin/sh", "polkadot"] diff --git a/docker/build.sh b/docker/build.sh new file mode 100755 index 0000000000000..fdbe8c3f8108c --- /dev/null +++ b/docker/build.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -e + +# Find the current version from Cargo.toml +VERSION=`grep "^version" ../Cargo.toml | egrep -o "([0-9\.]+)"` +GITUSER=chevdor +GITREPO=polkadot + +# Build the image +echo "Building ${GITREPO}:$VERSION docker image, hang on!" +time docker build --build-arg PROFILE=release -t ${GITUSER}/${GITREPO}:$VERSION . + +# Show the list of available images for this repo +echo "Image is ready" +docker images | grep ${GITREPO} + +echo -e "\nIf you just built the latest, you may want to update your tag:" +echo " $ docker tag ${GITUSER}/${GITREPO}:$VERSION ${GITUSER}/${GITREPO}:latest" diff --git a/docker/cleanup.sh b/docker/cleanup.sh new file mode 100755 index 0000000000000..b4de473a1b54f --- /dev/null +++ b/docker/cleanup.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# This script helps reduce the size of the built image +# It removes data that is not required. + +export PATH=$PATH:$HOME/.cargo/bin + +cargo clean +rm -rf /root/.cargo /root/.rustup /tmp/* diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000000000..b76d41da1d03a --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,15 @@ +version: '3' +services: + polkadot: + build: + context: . + ports: + - "127.0.0.1:30333:30333/tcp" + - "127.0.0.1:9933:9933/tcp" + image: chevdor/polkadot:latest + volumes: + - "polkadot-data:/data" + command: polkadot + +volumes: + polkadot-data: diff --git a/docker/readme-docker.adoc b/docker/readme-docker.adoc new file mode 100644 index 0000000000000..bbaceacd7f5c6 --- /dev/null +++ b/docker/readme-docker.adoc @@ -0,0 +1,16 @@ + +== Polkadot Docker + +=== Start a Polkadot docker container + +Run the following command + + docker run -d chevdor/polkadot:latest polkadot + +=== Building the image + +To build your own image from the source, you can run the following command: + + ./build.sh + +NOTE: Building the image takes a while. Count at least 30min on a good machine. diff --git a/docker/version b/docker/version new file mode 100755 index 0000000000000..047da3302ab95 --- /dev/null +++ b/docker/version @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# This script show the polkadot version and commit ref that was +# used to build the image. +# If you report an issue, call this script to get all details. +# This script will no longer be required once the polkadot cli +# can report its commit ref. + +echo "-----------------------------------------" +printf "Polkadot Docker Container: " +polkadot --version +printf " " +git rev-parse HEAD +echo "-----------------------------------------" diff --git a/init.sh b/init.sh index 6e70b76d32712..2bd46709b8e88 100755 --- a/init.sh +++ b/init.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e @@ -11,9 +11,3 @@ rustup update stable # Install wasm-gc. It's useful for stripping slimming down wasm binaries. command -v wasm-gc || \ cargo +nightly install --git https://github.com/alexcrichton/wasm-gc - -# At the moment of writing, rustc still uses LLD 6 which produces wasm binaries -# that don't export a table. Meanwhile, we are waiting for LLD 7 to come -# in rustc we could use this handy little tool. -command -v wasm-export-table || \ - cargo +nightly install --git https://github.com/pepyakin/wasm-export-table.git diff --git a/polkadot/api/Cargo.toml b/polkadot/api/Cargo.toml index 5a883cfd2cdff..7b5015b99130c 100644 --- a/polkadot/api/Cargo.toml +++ b/polkadot/api/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] -error-chain = "0.11" +error-chain = "0.12" polkadot-executor = { path = "../executor" } polkadot-runtime = { path = "../runtime" } polkadot-primitives = { path = "../primitives" } diff --git a/polkadot/api/README.adoc b/polkadot/api/README.adoc new file mode 100644 index 0000000000000..8f382d4f43919 --- /dev/null +++ b/polkadot/api/README.adoc @@ -0,0 +1,5 @@ + += Polkadot API + +placeholder +//TODO Write content :) diff --git a/polkadot/api/src/full.rs b/polkadot/api/src/full.rs index 46931653e0c14..caf9a8907281b 100644 --- a/polkadot/api/src/full.rs +++ b/polkadot/api/src/full.rs @@ -16,11 +16,11 @@ //! Strongly typed API for full Polkadot client. -use client::backend::{Backend, LocalBackend}; +use client::backend::LocalBackend; use client::block_builder::BlockBuilder as ClientBlockBuilder; use client::{Client, LocalCallExecutor}; use polkadot_executor::Executor as LocalDispatch; -use substrate_executor::{NativeExecutionDispatch, NativeExecutor}; +use substrate_executor::NativeExecutor; use state_machine; use runtime::Address; @@ -28,23 +28,13 @@ use runtime_primitives::traits::AuxLookup; use primitives::{AccountId, Block, Header, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic}; use primitives::parachain::{CandidateReceipt, DutyRoster, Id as ParaId}; -use {CheckedBlockId, BlockBuilder, PolkadotApi, LocalPolkadotApi, ErrorKind, Error, Result}; - -/// A checked block ID used for the substrate-client implementation of CheckedBlockId; -#[derive(Debug, Clone, Copy)] -pub struct CheckedId(pub(crate) BlockId); - -impl CheckedBlockId for CheckedId { - fn block_id(&self) -> &BlockId { - &self.0 - } -} +use {BlockBuilder, PolkadotApi, LocalPolkadotApi, ErrorKind, Error, Result}; // set up the necessary scaffolding to execute a set of calls to the runtime. // this creates a new block on top of the given ID and initialises it. macro_rules! with_runtime { ($client: ident, $at: expr, $exec: expr) => {{ - let parent = $at.block_id(); + let parent = $at; let header = Header { parent_hash: $client.block_hash_from_id(&parent)? .ok_or_else(|| ErrorKind::UnknownBlock(format!("{:?}", parent)))?, @@ -67,9 +57,7 @@ macro_rules! with_runtime { }} } -impl> BlockBuilder for ClientBlockBuilder>, Block> - where ::client::error::Error: From<<>::State as state_machine::backend::Backend>::Error> -{ +impl> BlockBuilder for ClientBlockBuilder>, Block> { fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> { self.push(extrinsic).map_err(Into::into) } @@ -80,44 +68,32 @@ impl> BlockBuilder for ClientBlockBuilder> PolkadotApi for Client>, Block> - where ::client::error::Error: From<<>::State as state_machine::backend::Backend>::Error> -{ - type CheckedBlockId = CheckedId; +impl> PolkadotApi for Client>, Block> { type BlockBuilder = ClientBlockBuilder>, Block>; - fn check_id(&self, id: BlockId) -> Result { - // bail if the code is not the same as the natively linked. - if self.code_at(&id.into())? != LocalDispatch::native_equivalent() { - bail!("This node is out of date. Block authoring may not work correctly. Bailing.") - } - - Ok(CheckedId(id)) - } - - fn session_keys(&self, at: &CheckedId) -> Result> { + fn session_keys(&self, at: &BlockId) -> Result> { with_runtime!(self, at, ::runtime::Consensus::authorities) } - fn validators(&self, at: &CheckedId) -> Result> { + fn validators(&self, at: &BlockId) -> Result> { with_runtime!(self, at, ::runtime::Session::validators) } - fn random_seed(&self, at: &CheckedId) -> Result { + fn random_seed(&self, at: &BlockId) -> Result { with_runtime!(self, at, ::runtime::System::random_seed) } - fn duty_roster(&self, at: &CheckedId) -> Result { + fn duty_roster(&self, at: &BlockId) -> Result { with_runtime!(self, at, ::runtime::Parachains::calculate_duty_roster) } - fn timestamp(&self, at: &CheckedId) -> Result { - with_runtime!(self, at, ::runtime::Timestamp::now) + fn timestamp(&self, at: &BlockId) -> Result { + with_runtime!(self, at, ::runtime::Timestamp::get) } - fn evaluate_block(&self, at: &CheckedId, block: Block) -> Result { + fn evaluate_block(&self, at: &BlockId, block: Block) -> Result { use substrate_executor::error::ErrorKind as ExecErrorKind; - use codec::Slicable; + use codec::{Decode, Encode}; use runtime::Block as RuntimeBlock; let encoded = block.encode(); @@ -136,28 +112,28 @@ impl> PolkadotApi for Client Result { + fn index(&self, at: &BlockId, account: AccountId) -> Result { with_runtime!(self, at, || ::runtime::System::account_nonce(account)) } - fn lookup(&self, at: &Self::CheckedBlockId, address: Address) -> Result> { + fn lookup(&self, at: &BlockId, address: Address) -> Result> { with_runtime!(self, at, || <::runtime::Staking as AuxLookup>::lookup(address).ok()) } - fn active_parachains(&self, at: &CheckedId) -> Result> { + fn active_parachains(&self, at: &BlockId) -> Result> { with_runtime!(self, at, ::runtime::Parachains::active_parachains) } - fn parachain_code(&self, at: &CheckedId, parachain: ParaId) -> Result>> { + fn parachain_code(&self, at: &BlockId, parachain: ParaId) -> Result>> { with_runtime!(self, at, || ::runtime::Parachains::parachain_code(parachain)) } - fn parachain_head(&self, at: &CheckedId, parachain: ParaId) -> Result>> { + fn parachain_head(&self, at: &BlockId, parachain: ParaId) -> Result>> { with_runtime!(self, at, || ::runtime::Parachains::parachain_head(parachain)) } - fn build_block(&self, at: &CheckedId, timestamp: Timestamp, new_heads: Vec) -> Result { - let mut block_builder = self.new_block_at(at.block_id())?; + fn build_block(&self, at: &BlockId, timestamp: Timestamp, new_heads: Vec) -> Result { + let mut block_builder = self.new_block_at(at)?; for inherent in self.inherent_extrinsics(at, timestamp, new_heads)? { block_builder.push(inherent)?; } @@ -165,14 +141,14 @@ impl> PolkadotApi for Client) -> Result> { - use codec::Slicable; + fn inherent_extrinsics(&self, at: &BlockId, timestamp: Timestamp, new_heads: Vec) -> Result> { + use codec::{Encode, Decode}; with_runtime!(self, at, || { let extrinsics = ::runtime::inherent_extrinsics(timestamp, new_heads); extrinsics.into_iter() .map(|x| x.encode()) // get encoded representation - .map(|x| Slicable::decode(&mut &x[..])) // get byte-vec equivalent to extrinsic + .map(|x| Decode::decode(&mut &x[..])) // get byte-vec equivalent to extrinsic .map(|x| x.expect("UncheckedExtrinsic has encoded representation equivalent to Vec; qed")) .collect() }) @@ -180,7 +156,6 @@ impl> PolkadotApi for Client> LocalPolkadotApi for Client>, Block> - where ::client::error::Error: From<<>::State as state_machine::backend::Backend>::Error> {} #[cfg(test)] @@ -190,7 +165,7 @@ mod tests { use client::LocalCallExecutor; use client::in_mem::Backend as InMemory; use substrate_executor::NativeExecutionDispatch; - use runtime::{GenesisConfig, ConsensusConfig, SessionConfig, BuildStorage}; + use runtime::{GenesisConfig, ConsensusConfig, SessionConfig}; fn validators() -> Vec { vec![ @@ -201,8 +176,8 @@ mod tests { fn session_keys() -> Vec { vec![ - Keyring::One.to_raw_public(), - Keyring::Two.to_raw_public(), + Keyring::One.to_raw_public().into(), + Keyring::Two.to_raw_public().into(), ] } @@ -216,20 +191,22 @@ mod tests { session: Some(SessionConfig { validators: validators(), session_length: 100, + broken_percent_late: 100, }), council: Some(Default::default()), democracy: Some(Default::default()), parachains: Some(Default::default()), staking: Some(Default::default()), + timestamp: Some(Default::default()), }; - ::client::new_in_mem(LocalDispatch::new(), genesis_config.build_storage()).unwrap() + ::client::new_in_mem(LocalDispatch::with_heap_pages(8, 8), genesis_config).unwrap() } #[test] fn gets_session_and_validator_keys() { let client = client(); - let id = client.check_id(BlockId::number(0)).unwrap(); + let id = BlockId::number(0); assert_eq!(client.session_keys(&id).unwrap(), session_keys()); assert_eq!(client.validators(&id).unwrap(), validators()); } @@ -238,7 +215,7 @@ mod tests { fn build_block_implicit_succeeds() { let client = client(); - let id = client.check_id(BlockId::number(0)).unwrap(); + let id = BlockId::number(0); let block_builder = client.build_block(&id, 1_000_000, Vec::new()).unwrap(); let block = block_builder.bake().unwrap(); @@ -250,10 +227,10 @@ mod tests { fn build_block_with_inherent_succeeds() { let client = client(); - let id = client.check_id(BlockId::number(0)).unwrap(); + let id = BlockId::number(0); let inherent = client.inherent_extrinsics(&id, 1_000_000, Vec::new()).unwrap(); - let mut block_builder = client.new_block_at(id.block_id()).unwrap(); + let mut block_builder = client.new_block_at(&id).unwrap(); for extrinsic in inherent { block_builder.push(extrinsic).unwrap(); } @@ -264,16 +241,11 @@ mod tests { assert!(block.header.extrinsics_root != Default::default()); } - #[test] - fn fails_to_check_id_for_unknown_block() { - assert!(client().check_id(BlockId::number(100)).is_err()); - } - #[test] fn gets_random_seed_with_genesis() { let client = client(); - let id = client.check_id(BlockId::number(0)).unwrap(); + let id = BlockId::number(0); assert!(client.random_seed(&id).is_ok()); } } diff --git a/polkadot/api/src/lib.rs b/polkadot/api/src/lib.rs index 81e3b024201e3..27bea18a0d0a3 100644 --- a/polkadot/api/src/lib.rs +++ b/polkadot/api/src/lib.rs @@ -77,12 +77,6 @@ impl From for Error { } } -/// A checked block identifier. -pub trait CheckedBlockId: Clone + 'static { - /// Yield the underlying block ID. - fn block_id(&self) -> &BlockId; -} - /// Build new blocks. pub trait BlockBuilder { /// Push an extrinsic onto the block. Fails if the extrinsic is invalid. @@ -96,57 +90,49 @@ pub trait BlockBuilder { /// /// All calls should fail when the exact runtime is unknown. pub trait PolkadotApi { - /// A checked block ID. Used to avoid redundancy of code check. - type CheckedBlockId: CheckedBlockId; /// The block builder for this API type. type BlockBuilder: BlockBuilder; - /// Check whether requests at the given block ID can be served. - /// - /// It should not be possible to instantiate this type without going - /// through this function. - fn check_id(&self, id: BlockId) -> Result; - /// Get session keys at a given block. - fn session_keys(&self, at: &Self::CheckedBlockId) -> Result>; + fn session_keys(&self, at: &BlockId) -> Result>; /// Get validators at a given block. - fn validators(&self, at: &Self::CheckedBlockId) -> Result>; + fn validators(&self, at: &BlockId) -> Result>; /// Get the value of the randomness beacon at a given block. - fn random_seed(&self, at: &Self::CheckedBlockId) -> Result; + fn random_seed(&self, at: &BlockId) -> Result; /// Get the authority duty roster at a block. - fn duty_roster(&self, at: &Self::CheckedBlockId) -> Result; + fn duty_roster(&self, at: &BlockId) -> Result; /// Get the timestamp registered at a block. - fn timestamp(&self, at: &Self::CheckedBlockId) -> Result; + fn timestamp(&self, at: &BlockId) -> Result; /// Get the nonce (né index) of an account at a block. - fn index(&self, at: &Self::CheckedBlockId, account: AccountId) -> Result; + fn index(&self, at: &BlockId, account: AccountId) -> Result; /// Get the account id of an address at a block. - fn lookup(&self, at: &Self::CheckedBlockId, address: Address) -> Result>; + fn lookup(&self, at: &BlockId, address: Address) -> Result>; /// Get the active parachains at a block. - fn active_parachains(&self, at: &Self::CheckedBlockId) -> Result>; + fn active_parachains(&self, at: &BlockId) -> Result>; /// Get the validation code of a parachain at a block. If the parachain is active, this will always return `Some`. - fn parachain_code(&self, at: &Self::CheckedBlockId, parachain: ParaId) -> Result>>; + fn parachain_code(&self, at: &BlockId, parachain: ParaId) -> Result>>; /// Get the chain head of a parachain. If the parachain is active, this will always return `Some`. - fn parachain_head(&self, at: &Self::CheckedBlockId, parachain: ParaId) -> Result>>; + fn parachain_head(&self, at: &BlockId, parachain: ParaId) -> Result>>; /// Evaluate a block. Returns true if the block is good, false if it is known to be bad, /// and an error if we can't evaluate for some reason. - fn evaluate_block(&self, at: &Self::CheckedBlockId, block: Block) -> Result; + fn evaluate_block(&self, at: &BlockId, block: Block) -> Result; /// Build a block on top of the given, with inherent extrinsics pre-pushed. - fn build_block(&self, at: &Self::CheckedBlockId, timestamp: Timestamp, new_heads: Vec) -> Result; + fn build_block(&self, at: &BlockId, timestamp: Timestamp, new_heads: Vec) -> Result; /// Attempt to produce the (encoded) inherent extrinsics for a block being built upon the given. /// This may vary by runtime and will fail if a runtime doesn't follow the same API. - fn inherent_extrinsics(&self, at: &Self::CheckedBlockId, timestamp: Timestamp, new_heads: Vec) -> Result>; + fn inherent_extrinsics(&self, at: &BlockId, timestamp: Timestamp, new_heads: Vec) -> Result>; } /// Mark for all Polkadot API implementations, that are making use of state data, stored locally. diff --git a/polkadot/api/src/light.rs b/polkadot/api/src/light.rs index 6a4f1f0322438..7e2015c0b701e 100644 --- a/polkadot/api/src/light.rs +++ b/polkadot/api/src/light.rs @@ -19,13 +19,11 @@ use std::sync::Arc; use client::backend::{Backend, RemoteBackend}; use client::{Client, CallExecutor}; -use codec::Slicable; -use state_machine; +use codec::Decode; use primitives::{AccountId, Block, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic}; use runtime::Address; use primitives::parachain::{CandidateReceipt, DutyRoster, Id as ParaId}; -use full::CheckedId; -use {PolkadotApi, BlockBuilder, RemotePolkadotApi, CheckedBlockId, Result, ErrorKind}; +use {PolkadotApi, BlockBuilder, RemotePolkadotApi, Result, ErrorKind}; /// Light block builder. TODO: make this work (efficiently) #[derive(Clone, Copy)] @@ -44,72 +42,63 @@ impl BlockBuilder for LightBlockBuilder { /// Remote polkadot API implementation. pub struct RemotePolkadotApiWrapper, E: CallExecutor>(pub Arc>); -impl, E: CallExecutor> PolkadotApi for RemotePolkadotApiWrapper - where ::client::error::Error: From<<>::State as state_machine::backend::Backend>::Error> -{ - type CheckedBlockId = CheckedId; +impl, E: CallExecutor> PolkadotApi for RemotePolkadotApiWrapper { type BlockBuilder = LightBlockBuilder; - fn check_id(&self, id: BlockId) -> Result { - Ok(CheckedId(id)) - } - - fn session_keys(&self, at: &CheckedId) -> Result> { - self.0.executor().call(at.block_id(), "authorities", &[]) + fn session_keys(&self, at: &BlockId) -> Result> { + self.0.executor().call(at, "authorities", &[]) .and_then(|r| Vec::::decode(&mut &r.return_data[..]) .ok_or("error decoding session keys".into())) .map_err(Into::into) } - fn validators(&self, _at: &CheckedId) -> Result> { + fn validators(&self, _at: &BlockId) -> Result> { Err(ErrorKind::UnknownRuntime.into()) } - fn random_seed(&self, _at: &Self::CheckedBlockId) -> Result { + fn random_seed(&self, _at: &BlockId) -> Result { Err(ErrorKind::UnknownRuntime.into()) } - fn duty_roster(&self, _at: &CheckedId) -> Result { + fn duty_roster(&self, _at: &BlockId) -> Result { Err(ErrorKind::UnknownRuntime.into()) } - fn timestamp(&self, _at: &CheckedId) -> Result { + fn timestamp(&self, _at: &BlockId) -> Result { Err(ErrorKind::UnknownRuntime.into()) } - fn evaluate_block(&self, _at: &CheckedId, _block: Block) -> Result { + fn evaluate_block(&self, _at: &BlockId, _block: Block) -> Result { Err(ErrorKind::UnknownRuntime.into()) } - fn index(&self, _at: &CheckedId, _account: AccountId) -> Result { + fn index(&self, _at: &BlockId, _account: AccountId) -> Result { Err(ErrorKind::UnknownRuntime.into()) } - fn lookup(&self, _at: &CheckedId, _address: Address) -> Result> { + fn lookup(&self, _at: &BlockId, _address: Address) -> Result> { Err(ErrorKind::UnknownRuntime.into()) } - fn active_parachains(&self, _at: &Self::CheckedBlockId) -> Result> { + fn active_parachains(&self, _at: &BlockId) -> Result> { Err(ErrorKind::UnknownRuntime.into()) } - fn parachain_code(&self, _at: &Self::CheckedBlockId, _parachain: ParaId) -> Result>> { + fn parachain_code(&self, _at: &BlockId, _parachain: ParaId) -> Result>> { Err(ErrorKind::UnknownRuntime.into()) } - fn parachain_head(&self, _at: &Self::CheckedBlockId, _parachain: ParaId) -> Result>> { + fn parachain_head(&self, _at: &BlockId, _parachain: ParaId) -> Result>> { Err(ErrorKind::UnknownRuntime.into()) } - fn build_block(&self, _at: &Self::CheckedBlockId, _timestamp: Timestamp, _new_heads: Vec) -> Result { + fn build_block(&self, _at: &BlockId, _timestamp: Timestamp, _new_heads: Vec) -> Result { Err(ErrorKind::UnknownRuntime.into()) } - fn inherent_extrinsics(&self, _at: &Self::CheckedBlockId, _timestamp: Timestamp, _new_heads: Vec) -> Result>> { + fn inherent_extrinsics(&self, _at: &BlockId, _timestamp: Timestamp, _new_heads: Vec) -> Result>> { Err(ErrorKind::UnknownRuntime.into()) } } -impl, E: CallExecutor> RemotePolkadotApi for RemotePolkadotApiWrapper - where ::client::error::Error: From<<>::State as state_machine::backend::Backend>::Error> -{} +impl, E: CallExecutor> RemotePolkadotApi for RemotePolkadotApiWrapper {} diff --git a/polkadot/cli/Cargo.toml b/polkadot/cli/Cargo.toml index 82e63d16b712c..3ccf81b1851eb 100644 --- a/polkadot/cli/Cargo.toml +++ b/polkadot/cli/Cargo.toml @@ -1,40 +1,33 @@ [package] name = "polkadot-cli" -version = "0.2.0" +version = "0.3.0" authors = ["Parity Technologies "] description = "Polkadot node implementation in Rust." [dependencies] -clap = { version = "2.27", features = ["yaml"] } -env_logger = "0.4" -error-chain = "0.11" +clap = { version = "~2.32", features = ["yaml"] } +error-chain = "0.12" log = "0.3" -atty = "0.2" -regex = "0.2" -time = "0.1" slog = "^2" -ansi_term = "0.10" lazy_static = "1.0" -hex-literal = "0.1" -triehash = "0.1" -ed25519 = { path = "../../substrate/ed25519" } -app_dirs = "1.2" -tokio-core = "0.1.12" +tokio = "0.1.7" futures = "0.1.17" -ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" } -fdlimit = "0.1" parking_lot = "0.4" -serde_json = "1.0" -serde = "1.0" +exit-future = "0.1" +substrate-cli = { path = "../../substrate/cli" } substrate-client = { path = "../../substrate/client" } -substrate-state-machine = { path = "../../substrate/state-machine" } -substrate-rpc = { path = "../../substrate/rpc" } -substrate-rpc-servers = { path = "../../substrate/rpc-servers" } +substrate-codec = { path = "../../substrate/codec" } +substrate-extrinsic-pool = { path = "../../substrate/extrinsic-pool" } substrate-network = { path = "../../substrate/network" } substrate-primitives = { path = "../../substrate/primitives" } +substrate-rpc = { path = "../../substrate/rpc" } +substrate-rpc-servers = { path = "../../substrate/rpc-servers" } substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" } +substrate-service = { path = "../../substrate/service" } +substrate-state-machine = { path = "../../substrate/state-machine" } substrate-telemetry = { path = "../../substrate/telemetry" } polkadot-primitives = { path = "../primitives" } polkadot-runtime = { path = "../runtime" } polkadot-service = { path = "../service" } polkadot-transaction-pool = { path = "../transaction-pool" } + diff --git a/polkadot/cli/poc-1.json b/polkadot/cli/poc-1.json deleted file mode 100644 index 9f2f741e25498..0000000000000 --- a/polkadot/cli/poc-1.json +++ /dev/null @@ -1,38 +0,0 @@ -{ -"0x9768f3cbdd14c1a63474dfbdbe052f42": "0x80f4030000000000", -"0x3b700687fecdff5ec1c4a5b714521eb6": "0x0000000000000000", -"0xa059ae3b3ef725721e97452642803b61": "0x0c00000000000000", -"0x81c1e7165a6371a30eda241a30ea26dd": "0x6400000000000000", -"0x45e71d57a2e3a4eace16dbc9286652e3": "0x00000000", -"0x1d72be21946c0b245c026b7be8256cc5": "0x00000000", -"0xd68ee884e4baac617d9823d543ab9295": "0x0000000000000010", -"0x1d007e138cb61e2524a67b15ec01d8cb": "0x0000000000000010", -"0xbfde7c86a8efd60ee5db2de6446703d5": "0xc04e000000000000", -"0x3a617574683a6c656e": "0x04000000", -"0xb54b186fe8782c2a03f2fd15f95c26bf": "0x00000000", -"0x9dd24013e492bdbb3544fba06734baf7": "0xd002000000000000", -"0xd52c584b1e542130e5b277f1af7b7714": "0x00000000", -"0x3a617574683a03000000": "0x8101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c", -"0x916dbd78366f27a9597bd4c831e7914d": "0x00e9070000000000", -"0xf37d2c26c6953b18878dbc1dc65edbc0": "0x1800000000000000", -"0x8d62e0fbc08e8694f8991f88d763c5fb": "0x5a00000000000000", -"0xa659ecb253960cfd890e08809104b815": "0x809d000000000000", -"0x3a617574683a00000000": "0x82c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf5", -"0x3a617574683a02000000": "0x063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca5", -"0xe885ffcc2245c8b7d128685cac6b1a0b": "0x0100000000000000", -"0x94b01408fc662bcf2e97df23ce6d67e2": "0x0100000000000000", -"0x6cac40e934558080fbf29c55c113b461": "0x0000000000000000", -"0x8379e35e0cd953085e0404b9223c0cb0": "0xc04e000000000000", -"0x5a3dcf1edb28ea65a038d1eef6767380": "0x003b010000000000", -"0x7a5bafa684003bc748abe89bfbd20f76": "0xe803000000000000", -"0x3d5680071e92ff27a2914bba661e5d83": "0x400b000000000000", -"0x274351e20682cb2ed212b6eab04ef89f": "0x00000000", -"0x3a617574683a01000000": "0x4de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7", -"0x482b5d7b62ccccac45d55bd43c767266": "0x6400000000000000", -"0x35b8ced31f34a951bc3b56db2f425c51": "0x00000000", -"0x98b9e95963cac608a3d0d537fbeaf5c2": "0x0400000082c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf54de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca58101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c", -"0xce83497694648564e47482d0dc444564": "0x18000000", -"0xa0c2154e69bce912f28e890561fcb95c": "0x0400000082c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf54de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca58101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c", -"0x9b7ecc8eb0fade7c91d94b8715fc9ee1": "0xe803000000000000", -"0x3a636f6465": "0x0061736d010000000197011760027f7f0060057f7f7f7f7f017f60017f017f60037f7f7f017f60017f0060000060037f7f7f0060047f7f7f7f006000017e60027f7f017f60027f7e0060037e7f7f0060017f017e600a7f7f7f7f7f7f7f7f7f7f0060017e0060067f7f7f7f7f7f0060047f7f7f7f017f60047f7f7f7f017e60067f7f7f7f7f7f017f60057f7f7f7f7f0060027f7f017e60027f7e017f60037f7f7e0002f1031603656e76146578745f6765745f73746f726167655f696e746f000103656e760a6578745f6d616c6c6f63000203656e76086578745f66726565000403656e760c6578745f74776f785f313238000603656e760f6578745f7365745f73746f72616765000703656e76116578745f636c6561725f73746f72616765000003656e760a6578745f6d656d636d70000303656e76186578745f656e756d6572617465645f747269655f726f6f74000703656e760e6578745f7072696e745f75746638000003656e760d6578745f7072696e745f6e756d000e03656e760a6578745f6d656d637079000303656e760b6578745f6d656d6d6f7665000303656e760a6578745f6d656d736574000303656e76166578745f73616e64626f785f6d656d6f72795f6e6577000903656e76176578745f73616e64626f785f696e7374616e7469617465001203656e76126578745f73616e64626f785f696e766f6b65001003656e76166578745f73616e64626f785f6d656d6f72795f676574001003656e76166578745f73616e64626f785f6d656d6f72795f736574001003656e760e6578745f626c616b65325f323536000603656e760d6578745f7072696e745f686578000003656e76106578745f73746f726167655f726f6f74000403656e76126578745f656432353531395f766572696679001003d001ce010003040505050500030000020404050400060000060505000804040900000505040004030004060a040b0005000c0c00040405060404060d0504050002040400050505050505050505050505050505050505040504050405050405040505040504050405040504050405040506060000060007070f070f0710070707071107130906000409060000040500140014061404140a06041414140002060a15000000000400000004040000040c000405070a1400000000000413060706160704140616060000060000000000000000090405017001161605030100110609017f0141d0c3c0000b07a8010b066d656d6f7279020011727573745f626567696e5f756e77696e64004d066d616c6c6f630052046672656500530b617574686f72697469657300a10110696e697469616c6973655f626c6f636b00a3010f6170706c795f65787472696e73696300a5010d657865637574655f626c6f636b00a7010e66696e616c6973655f626c6f636b00ab010f76616c696461746f725f636f756e7400ac010a76616c696461746f727300ad010930010041010b158f019001910192019301cc01cd01ce01c601cf01d001d101c701d30195019b01d4019401d501d6019c010abbe40cce01ea0403067f017e057f230041106b220224002002410036020020012001280208220341002001280200220420012802042205200241042003100022032003417f461b2203410420034104491b6a22063602080240024002400240200341034d0d0020022802002207ad420c7e2208422088a70d022008a72203417f4c0d01024002402003450d002003100122090d010c050b410421090b20022007360204200220093602002002410036020802402007450d00200141086a210a4100210b4100210c03402002410036020c200a4100200420052002410c6a41042006100022012001417f461b2201410420014104491b20066a2206360200024002400240200141034d0d00200228020c2201417f4c0d01024002402001450d00200110012203450d0a20034100200110171a0c010b410121030b200a20014100200420052003200120061000220d200d417f461b220d200d20014b1b20066a220636020002402001200d4b0d002003450d01200c41016a210c2001ad22084220862008842108200b2002280204470d0320021018200241086a280200210b200228020021090c030b200310020b200228020021060240200b450d00200b410c6c21032006210103400240200141046a280200450d00200128020010020b2001410c6a2101200341746a22030d000b0b2002280204450d04200610020c040b1019000b2009200b410c6c6a2201200837020420012003360200200241086a200b41016a220b360200200c2007490d000b200228020021090b2009450d002000200229020437020420002009360200200241106a24000f0b20004100360200200241106a24000f0b101a000b101b000b101c000b0a00200020012002100c0b810101057f410421010240024002400240200041046a2802002202450d00200241186c2201417f4c0d0320002802002103200110012204450d022004200320012002410c6c2205200520014b1b101e1a20031002200241017421010c010b413010012204450d010b20002004360200200041046a20013602000f0b101c000b1073000b05001041000b05001041000b05001041000b0500104e000bc11105097f037e017f017e027f230041a0026b220224002001280200210320024180026a20012802042204412020044120491b22056a41004100412020056b2005411f4b1b10171a20024180026a20032005101e1a2001200420056b22063602042001200320056a22053602000240024002400240024002400240024002402004411f4d0d00200241e0016a41186a220420024180026a41186a2203290300370300200241e0016a41106a220720024180026a41106a2208290300370300200241e0016a41086a220920024180026a41086a220a29030037030020022002290380023703e00120032004290300220b37030020082007290300220c370300200a2009290300220d370300200241c0006a41086a2204200d370300200241c0006a41106a2203200c370300200241c0006a41186a2207200b370300200220022903e001220b3703402002200b37038002200241206a41186a2007290300370300200241206a41106a2003290300370300200241206a41086a200429030037030020022002290340370320200242003703800220024180026a20052006410820064108491b2204101e1a200141046a2207200620046b22033602002001200520046a2204360200200641074d0d01200229038002210c20024180026a2003412020034120491b22056a41004100412020056b2005411f4b1b10171a20024180026a20042005101e1a2007200320056b22063602002001200420056a22043602002003411f4d0d02200241e0016a41186a220320024180026a41186a2207290300370300200241e0016a41106a220820024180026a41106a2209290300370300200241e0016a41086a220a20024180026a41086a220e29030037030020022002290380023703e00120072003290300220b37030020092008290300220d370300200e200a290300220f37030020024180016a41086a2205200f37030020024180016a41106a2210200d37030020024180016a41186a2211200b370300200220022903e001220b370380012002200b37038002200241e0006a41186a2011290300370300200241e0006a41106a2010290300370300200241e0006a41086a2005290300370300200220022903800137036020024180026a2006412020064120491b22056a41004100412020056b2005411f4b1b10171a20024180026a20042005101e1a200141046a2211200620056b22103602002001200420056a22053602002006411f4d0d032003200729030037030020082009290300370300200a200e29030037030020022002290380023703e00120072003290300220b37030020092008290300220d370300200e200a290300220f370300200241c0016a41086a2204200f370300200241c0016a41106a2203200d370300200241c0016a41186a2206200b370300200220022903e001220b3703c0012002200b37038002200241a0016a41186a2006290300370300200241a0016a41106a2003290300370300200241a0016a41086a2004290300370300200220022903c0013703a001200241003602800220024180026a20052010410420104104491b2204101e1a2011201020046b3602002001200520046a360200201041034d0d062002280280022208ad420c7e220b422088a70d08200ba72205417f4c0d072005450d042005100122070d05101c000b20024180026a41186a200241e0016a41186a29000037030020024180026a41106a200241e0016a41106a29000037030020024180026a41086a200241e0016a41086a290000370300200220022900e0013703800220004100360208200241a0026a24000f0b20004100360208200241a0026a24000f0b20024180026a41186a200241e0016a41186a29000037030020024180026a41106a200241e0016a41106a29000037030020024180026a41086a200241e0016a41086a290000370300200220022900e0013703800220004100360208200241a0026a24000f0b2007200329000037030020092008290000370300200e200a290000370300200220022900e0013703800220004100360208200241a0026a24000f0b410421070b200220083602e401200220073602e00141002105200241003602e80102402008450d00200241e8016a210941002104034020024180026a2001101f024002402002280280022203450d00200441016a2104200229028402210b200520022802e401470d01200241e0016a10182009280200210520022802e00121070c010b20022802e001210402402005450d002005410c6c21052004210103400240200141046a280200450d00200128020010020b2001410c6a2101200541746a22050d000b0b20022802e401450d03200410020c030b20072005410c6c6a2206200b370204200620033602002009200541016a220536020020042008490d000b20022802e00121070b2007450d0020022902e401210b20024180026a41186a2201200241206a41186a29030037030020024180026a41106a2205200241206a41106a29030037030020024180026a41086a2204200241206a41086a290300370300200241e0016a41086a2203200241e0006a41086a290300370300200241e0016a41106a2206200241e0006a41106a290300370300200241e0016a41186a2208200241e0006a41186a290300370300200241086a2209200241a0016a41086a290300370300200241106a220a200241a0016a41106a290300370300200241186a220e200241a0016a41186a2903003703002002200229032037038002200220022903603703e001200220022903a001370300200020073602082000200c3703002000200b37020c200041146a2002290380023702002000411c6a2004290300370200200041246a20052903003702002000412c6a2001290300370200200041346a20022903e0013702002000413c6a2003290300370200200041c4006a2006290300370200200041cc006a2008290300370200200041ec006a200e290300370200200041e4006a200a290300370200200041dc006a2009290300370200200041d4006a2002290300370200200241a0026a24000f0b20004100360208200241a0026a24000f0b101a000b101b000b0a00200020012002100a0b880201067f230041106b220224002002410036020c2002410c6a2001280200220320012802042204410420044104491b2205101e1a2001200420056b22063602042001200320056a220536020002400240024002400240200441034d0d00200228020c2204417f4c0d032004450d01200410012207450d0420074100200410171a0c020b20004100360200200241106a24000f0b410121070b200720052006200420062004491b2203101e2107200141046a200620036b3602002001200520036a3602000240200620044f0d002000410036020020071002200241106a24000f0b2000200436020420002007360200200041086a2004360200200241106a24000f0b1019000b101c000ba6c80107097f047e047f027e257f057e077f230041f0126b2202240020012001280200200128020422034104200341044922041b22056a22063602002001200320056b2203360204024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020040d00200241d8096a2003412020034120491b22046a41004100412020046b2004411f4b1b10171a200241d8096a20062004101e1a200141046a200320046b22053602002001200620046a22043602002003411f4d0d01200241086a41186a2203200241d8096a41186a2206290300370300200241086a41106a2207200241d8096a41106a2208290300370300200241086a41086a2209200241d8096a41086a220a290300370300200220022903d80937030820062003290300220b37030020082007290300220c370300200a2009290300220d370300200241e0076a41086a2203200d370300200241e0076a41106a2206200c370300200241e0076a41186a2207200b37030020022002290308220b3703e0072002200b3703d809200241c0076a41186a2007290300370300200241c0076a41106a2006290300370300200241c0076a41086a2003290300370300200220022903e0073703c00720024200370308200241086a200420054108200541084922061b2203101e1a200141046a2207200520036b22053602002001200420036a220336020020060d022002290308210e200241003a0008200241086a200320054100472204101e1a2007200520046b220f3602002001200320046a22043602002005450d184107210320022d0008221041074b0d37024020100e08000507083b090406000b200241003a0008200241086a2004200f4100472205101e1a200141046a2208200f20056b22063602002001200420056a2207360200410321094200210d20022d00084108744100200f1b2005724181fe03714101470d35200241f8096a2006412020064120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20072004101e1a2008200620046b22053602002001200720046a22043602002006411f4d0d0c200241086a41186a2206200241f8096a41186a2207290300370300200241086a41106a2208200241f8096a41106a220a290300370300200241086a41086a2211200241f8096a41086a2212290300370300200220022903f80937030820072006290300220b370300200a2008290300220c370300201220112903002213370300200241d8116a41086a22062013370300200241d8116a41106a2207200c370300200241d8116a41186a2208200b37030020022002290308220b3703d8112002200b3703f80920024198106a41186a200829030037030020024198106a41106a200729030037030020024198106a41086a2006290300370300200220022903d8113703981020024200370308200241086a200420054108200541084922071b2206101e1a200141046a2208200520066b22053602002001200420066a220636020020070d332002290308210b200241f8096a2005412020054120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20062004101e1a2008200520046b22073602002001200620046a22043602002005411f4d0d20200241086a41186a2205200241f8096a41186a2206290300370300200241086a41106a2208200241f8096a41106a220a290300370300200241086a41086a2211200241f8096a41086a2212290300370300200220022903f80937030820062005290300220c370300200a20082903002213370300201220112903002214370300200241d8116a41086a22052014370300200241d8116a41106a22062013370300200241d8116a41186a2208200c37030020022002290308220c3703d8112002200c3703f809200241b8106a41186a2008290300370300200241b8106a41106a2006290300370300200241b8106a41086a2005290300370300200220022903d8113703b810200241003a0008200241086a200420074100472205101e1a200141046a200720056b22063602002001200420056a22043602002007450d3341014102410320022d000822054112461b20054111461b22054101460d2b20054103460d3320024100360208200241086a20042006410420064104491b2205101e1a200141046a2208200620056b22073602002001200420056a2205360200200641034d0d3320022802082115200241f8096a2007412020074120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20052004101e1a2008200720046b22063602002001200520046a22083602002007411f4d0d2a200241086a41186a2216200241f8096a41186a2207290300370300200241086a41106a2217200241f8096a41106a2218290300370300200241086a41086a2219200241f8096a41086a221a290300370300200220022903f80937030820182017290300370300201a20192903003703002007201629030037030020024198126a41086a2204200241870a6a221b280000360200200220022903083703f809200220022900ff093703981220072d0000210520022800fb09211c20022d008b0a211d20022d008c0a211e20022f008d0a210a20022d008f0a211120022f00910a210f20022d00930a211220022d00940a211f20022f00950a212020022d00970a211020022f01f809212120022d00fa092122200241d8096a41086a200428020036020020022002290398123703d809200241f8096a200641c000200641c000491b22046a4100410041c00020046b2004413f4b1b10171a200241f8096a20082004101e1a200141046a2223200620046b22243602002001200820046a22253602002006413f4d0d29200241086a41386a2204200241f8096a41386a2206290300370300200241086a41306a2208200241f8096a41306a2226290300370300200241086a41286a2227200241f8096a41286a2228290300370300200241086a41206a2229200241f8096a41206a222a29030037030020162007290300370300201720182903003703002019201a290300370300200220022903f80937030820182017290300370300201a201929030037030020072016290300370300202a202929030037030020282027290300370300202620082903003703002006200429030037030020024198116a41086a2204201b29000037030020024198116a41106a22062002418f0a6a29000037030020024198116a41186a2207200241f8096a411f6a29000037030020024198116a41206a22082002419f0a6a29000037030020024198116a41286a2216200241a70a6a29000037030020024198116a41306a2217200241af0a6a29000037030020024198116a41386a2218200241f8096a413f6a2d00003a0000200220022903083703f809200220022900ff093703981120023502f809210c20023201fc09211320023100fe092114200241d8106a41086a2004290300370300200241d8106a41106a2006290300370300200241d8106a41186a2007290300370300200241d8106a41206a2008290300370300200241d8106a41286a2016290300370300200241d8106a41306a2017290300370300200241d8106a41386a20182d00003a000020022002290398113703d81020022f01e209211620022d00e109210820022d00e009211920022f01de09211720022d00dd09210720022d00dc09211820022802d809212b200241f8096a2024412020244120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20252004101e1a2023202420046b22063602002001202520046a222c3602002024411f4d0d28200241086a41186a222d200241f8096a41186a222e290300370300200241086a41106a222f200241f8096a41106a2230290300370300200241086a41086a2231200241f8096a41086a2232290300370300200220022903f8093703082030202f29030037030020322031290300370300202e202d290300370300200241b8126a41086a2204200241870a6a280000360200200220022903083703f809200220022900ff093703b812202e2d0000212620022800fb09211a20022d008b0a212420022d008c0a212520022f008d0a211b20022d008f0a212320022f00910a212720022d00930a212820022d00940a212920022f00950a212a20022d00970a213320022f01f809213420022d00fa092135200241d8096a41086a22362004280200360200200220022903b8123703d809200241f8096a200641c000200641c000491b22046a4100410041c00020046b2004413f4b1b10171a200241f8096a202c2004101e1a200141046a200620046b3602002001202c20046a3602002006413f4d0d2720212022411074722137200c201320144210868442208684210c20342035411074722106200241086a41386a2204200241f8096a41386a2221290300370300200241086a41306a2222200241f8096a41306a222c290300370300200241086a41286a2234200241f8096a41286a2235290300370300200241086a41206a2238200241f8096a41206a2239290300370300202d202e290300370300202f203029030037030020312032290300370300200220022903f809370308202120042903002213370300202c2022290300221437030020352034290300223a37030020392038290300223b370300202e202d290300223c3703002030202f290300223d37030020322031290300223e370300200241d8116a41086a223f203e370300200241d8116a41106a2240203d370300200241d8116a41186a2241203c370300200241d8116a41206a2242203b370300200241d8116a41286a2243203a370300200241d8116a41306a22442014370300200241d8116a41386a224520133703002002200229030822133703d811200220133703f809200241e0126a41086a20362802003602002031203f290300370300202f2040290300370300202d204129030037030020382042290300370300203420432903003703002022204429030037030020042045290300370300200220022903d8093703e012200220022903d8113703082021200241d8106a41386a2d00003a0000202c200241d8106a41306a2903003703002035200241d8106a41286a2903003703002039200241d8106a41206a290300370300202e200241d8106a41186a2903003703002030200241d8106a41106a2903003703002032200241d8106a41086a290300370300200220022903d8103703f809410121040c2c0b200041073a0008200241f0126a24000f0b200241d8096a41186a200241086a41186a290000370300200241d8096a41106a200241086a41106a290000370300200241d8096a41086a200241086a41086a290000370300200220022900083703d8090b410721040c380b200241003a0008200241086a2004200f4100472206101e1a200141046a200f20066b22053602002001200420066a2206360200200f450d3320022d0008220441044b0d33024020040e050019161714000b20024100360208200241086a20062005410420054104491b2207101e1a200141046a200520076b22043602002001200620076a2206360200200541034d0d332002280208220a417f4c0d22200a450d20200a100122110d21101c000b200241003a0008200241086a2004200f4100472205101e1a200141046a2208200f20056b22063602002001200420056a220736020020022d00084108744100200f1b2005724181fe03714101470d05200241f8096a20064120200641204922051b22046a41004100412020046b2004411f4b1b10171a200241f8096a20072004101e1a2008200620046b3602002001200720046a36020020050d04200241086a41186a2205200241f8096a41186a2204290300370300200241086a41106a2206200241f8096a41106a2207290300370300200241086a41086a2208200241f8096a41086a2209290300370300200220022903f809370308200720062903003703002009200829030037030020042005290300370300200241d8116a41086a2209200241870a6a280000360200200220022903083703f809200220022900ff093703d81120042d0000211120022800fb09210520022d008b0a211220022d008c0a211d20022f008d0a211620022d008f0a211720022f00910a210620022d00930a210720022d00940a211820022f00950a210a20022d00970a210820022f01f809210420022d00fa092119200241d8096a41086a22152009280200360200200220022903d8113703d809200241b00e6a41086a2015280200360200200220022903d8093703b00e20042019411074722104410121090c060b200241003a0008200241086a2004200f4100472205101e1a200141046a200f20056b22063602002001200420056a2204360200200f450d3120022d00082205450d0a20054101460d0720054102470d31200241f8096a2006412020064120491b22056a41004100412020056b2005411f4b1b10171a200241f8096a20042005101e1a200141046a200620056b3602002001200420056a3602002006411f4d0d18200241086a41186a2204200241f8096a41186a2203290300370300200241086a41106a2205200241f8096a41106a2206290300370300200241086a41086a2207200241f8096a41086a2208290300370300200220022903f809370308200620052903003703002008200729030037030020032004290300370300200241d8116a41086a2205200241870a6a280000360200200220022903083703f809200220022900ff093703d81120032d0000210720022800fb09210420022d008b0a212b20022d008c0a212020022f008d0a211f20022d008f0a211820022f00910a211720022d00930a211920022d00940a210820022f00950a211620022d00970a211d20022f01f809210320022d00fa092106200241d8096a41086a2005280200360200200220022903d8113703d8092003200641107472210520022902dc09210d20022802d809210f4103211c0c0b0b200241003a0008200241086a2004200f4100472205101e1a200141046a200f20056b22063602002001200420056a2205360200200f450d3020022d00082204450d0b20044101460d0720044102470d33410321060c080b200241003a0008200241086a2004200f4100472205101e1a200141046a2207200f20056b22063602002001200420056a220436020020022d00084108744100200f1b2005724181fe03714101470d2f20024200370308200241086a20042006410820064108491b2203101e1a2007200620036b3602002001200420036a36020041072103200641074d0d2f2002290308210d20024198096a41086a200241d8116a41086a29030037030020024198096a41106a200241d8116a41106a29030037030020024198096a41186a200241d8116a41186a29030037030020024198096a41206a200241d8116a41206a29030037030020024198096a41286a200241d8116a41286a29030037030020024198096a41306a200241d8116a41306a29030037030020024198096a41386a200241d8116a41386a2d00003a0000200220022f0198113b01d609200220022903d8113703980920024188096a41086a200241800b6a41086a280200360200200241c8086a41086a200241086a41086a290000370300200241c8086a41106a200241086a41106a290000370300200241c8086a41186a200241086a41186a290000370300200241c8086a41206a200241086a41206a290000370300200241c8086a41286a200241086a41286a290000370300200241c8086a41306a200241086a41306a290000370300200241c8086a41386a200241086a41386a290000370300200220022903800b37038809200220022900083703c808200241c4086a41026a200241f8096a41026a2d00003a0000200241a0086a41186a200241b00e6a41186a290300370300200241a0086a41106a200241b00e6a41106a290300370300200241a0086a41086a200241b00e6a41086a29030037030020024180086a41186a200241d80c6a41186a29030037030020024180086a41106a200241d80c6a41106a29030037030020024180086a41086a200241d80c6a41086a290300370300200220022f00f8093b01c408200220022903b00e3703a008200220022903d80c37038008410321034201210b0c0e0b200241003a0008200241086a2004200f4100472205101e1a200141046a200f20056b22063602002001200420056a2204360200200f450d2e20022d00082205450d0b20054101460d0a20054102470d2e20024100360208200241086a20042006410420064104491b2205101e1a200141046a2208200620056b22073602002001200420056a2205360200200641034d0d2e20022802082104200241003a0008200241086a200520074100472206101e1a2008200720066b3602002001200520066a3602002007450d2e2002310008420183210b410321030c0c0b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090b410221090b200241870a6a200241b00e6a41086a280200360000200220053600fb09200220123a008b0a2002201d3a008c0a200220163b008d0a200220173a008f0a200220113a00900a200220063b00910a200220073a00930a200220183a00940a2002200a3b00950a200220083a00970a200220022903b00e3700ff09200220043b01f809200220044110763a00fa0920094102460d2b200220022f01f8093b01d609200241940a6a2f0100211720022901fe09210b20022901860a210d200228018e0a212b20024198096a41386a200241d8116a41386a2d00003a000020024198096a41306a200241d8116a41306a29010037030020024198096a41286a200241d8116a41286a29010037030020024198096a41206a200241d8116a41206a29010037030020024198096a41186a200241d8116a41186a29010037030020024198096a41106a200241d8116a41106a29010037030020024198096a41086a200241d8116a41086a29010037030020024188096a41086a200241800b6a41086a280100360200200220022901d81137039809200220022901800b37038809200241c8086a41386a200241086a41386a290000370300200241c8086a41306a200241086a41306a290000370300200241c8086a41286a200241086a41286a290000370300200241c8086a41206a200241086a41206a290000370300200241c8086a41186a200241086a41186a290000370300200241c8086a41106a200241086a41106a290000370300200241c8086a41086a200241086a41086a290000370300200241c4086a41026a200241f8096a41026a2d00003a0000200220022900083703c808200220022f00f8093b01c408200241a0086a41186a200241b00e6a41186a290100370300200241a0086a41106a200241b00e6a41106a290100370300200241a0086a41086a200241b00e6a41086a29010037030020024180086a41186a200241d80c6a41186a29010037030020024180086a41106a200241d80c6a41106a29010037030020024180086a41086a200241d80c6a41086a290100370300200220022901b00e3703a008200220022901d80c37038008202b411076211f202b41087621202004418080fc0771411076211c20064180fe03714108762118200a4180fe03714108762119410121030c2e0b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c260b200241f8096a2006412020064120491b22056a41004100412020056b2005411f4b1b10171a200241f8096a20042005101e1a200141046a220a200620056b22093602002001200420056a22053602002006411f4d0d0f200241086a41186a2206200241f8096a41186a2204290300370300200241086a41106a2207200241f8096a41106a2208290300370300200241086a41086a2211200241f8096a41086a2212290300370300200220022903f809370308200820072903003703002012201129030037030020042006290300370300200241d8116a41086a2206200241870a6a280000360200200220022903083703f809200220022900ff093703d81120042d0000210720022800fb09210420022d008b0a212b20022d008c0a212020022f008d0a211f20022d008f0a211820022f00910a211720022d00930a211920022d00940a210820022f00950a211620022d00970a211d20022f01f809211120022d00fa092112200241d8096a41086a2006280200360200200220022903d8113703d809200241003a0008200241086a200520094100472206101e1a200a200920066b3602002001200520066a3602002009450d292011201241107472210520022d0008410171211e20022902dc09210d20022802d809210f4102211c0c030b410221060b0c220b4101211c200110212204450d290b20024198096a41086a200241d8116a41086a29030037030020024198096a41106a200241d8116a41106a29030037030020024198096a41186a200241d8116a41186a29030037030020024198096a41206a200241d8116a41206a29030037030020024198096a41286a200241d8116a41286a29030037030020024198096a41306a200241d8116a41306a29030037030020024198096a41386a200241d8116a41386a2d00003a0000200220022f0198113b01d609200220022903d8113703980920024188096a41086a200241800b6a41086a280200360200200241c8086a41086a200241086a41086a290000370300200241c8086a41106a200241086a41106a290000370300200241c8086a41186a200241086a41186a290000370300200241c8086a41206a200241086a41206a290000370300200241c8086a41286a200241086a41286a290000370300200241c8086a41306a200241086a41306a290000370300200241c8086a41386a200241086a41386a290000370300200220022903800b37038809200220022900083703c808200241c4086a41026a200241f8096a41026a2d00003a0000200241a0086a41186a200241b00e6a41186a290300370300200241a0086a41106a200241b00e6a41106a290300370300200241a0086a41086a200241b00e6a41086a29030037030020024180086a41186a200241d80c6a41186a29030037030020024180086a41106a200241d80c6a41106a29030037030020024180086a41086a200241d80c6a41086a290300370300200220022f00f8093b01c408200220022903b00e3703a008200220022903d80c37038008200fad4220862004ad84210b410621030c270b200241f8096a2006412020064120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20052004101e1a200141046a2212200620046b22093602002001200520046a22113602002006411f4d0d0c200241086a41186a2204200241f8096a41186a2203290300370300200241086a41106a2205200241f8096a41106a2206290300370300200241086a41086a2207200241f8096a41086a2208290300370300200220022903f809370308200620052903003703002008200729030037030020032004290300370300200241d8116a41086a2206200241870a6a280000360200200220022903083703f809200220022900ff093703d81120032d0000210820022800fb09210520022d008b0a211820022d008c0a210720022f008d0a211720022d008f0a211920022f00910a211620022d00930a211d20022d00940a211e20022f00950a210a20022d00970a210420022f01f809211520022d00fa09211a200241d8096a41086a2006280200360200200220022903d8113703d80920024200370308200241086a20112009410820094108491b2203101e1a2012200920036b3602002001201120036a36020041072103200941074d0d242015201a4110747221092002290308210c20022802e009212b20022903d809210d410121060c1f0b20024100360208200241086a20042006410420064104491b2205101e1a200141046a200620056b3602002001200420056a360200200641034d0d2320022802082104410221034200210b0c010b200110212204450d22200220043602d8104200210b20024200370308200241086a20012802002206200141046a22072802002205410820054108491b2203101e1a2007200520036b3602002001200620036a36020041072103200541074d0d0d2002290308210d410121030b20024198096a41086a200241d8116a41086a29030037030020024198096a41106a200241d8116a41106a29030037030020024198096a41186a200241d8116a41186a29030037030020024198096a41206a200241d8116a41206a29030037030020024198096a41286a200241d8116a41286a29030037030020024198096a41306a200241d8116a41306a29030037030020024198096a41386a200241d8116a41386a2d00003a0000200220022f0198113b01d609200220022903d8113703980920024188096a41086a200241800b6a41086a280200360200200241c8086a41086a200241086a41086a290000370300200241c8086a41106a200241086a41106a290000370300200241c8086a41186a200241086a41186a290000370300200241c8086a41206a200241086a41206a290000370300200241c8086a41286a200241086a41286a290000370300200241c8086a41306a200241086a41306a290000370300200241c8086a41386a200241086a41386a290000370300200220022903800b37038809200220022900083703c808200241c4086a41026a200241f8096a41026a2d00003a0000200241a0086a41186a200241b00e6a41186a290300370300200241a0086a41106a200241b00e6a41106a290300370300200241a0086a41086a200241b00e6a41086a29030037030020024180086a41186a200241d80c6a41186a29030037030020024180086a41106a200241d80c6a41106a29030037030020024180086a41086a200241d80c6a41086a290300370300200220022f00f8093b01c408200220022903b00e3703a008200220022903d80c37038008200b2004ad42188684420886200341ff0171ad84210b410421030b4100211f410021200c210b200241f8096a2005412020054120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20062004101e1a200141046a2212200520046b22093602002001200620046a22043602002005411f4d0d09200241086a41186a2205200241f8096a41186a2203290300370300200241086a41106a2206200241f8096a41106a2207290300370300200241086a41086a2208200241f8096a41086a220a290300370300200220022903f80937030820072006290300370300200a200829030037030020032005290300370300200241d8116a41086a2206200241870a6a280000360200200220022903083703f809200220022900ff093703d81120032d0000210820022800fb09210520022d008b0a211820022d008c0a210720022f008d0a211720022d008f0a211920022f00910a211620022d00930a211d20022d00940a211e20022f00950a210a20022d00970a211120022f01f809211520022d00fa09211a200241d8096a41086a2006280200360200200220022903d8113703d80920024200370308200241086a20042009410820094108491b2203101e1a2012200920036b22063602002001200420036a2203360200200941074d0d002002290308210c20024100360208200241086a20032006410420064104491b2204101e1a200141046a200620046b3602002001200320046a360200200641034d0d002015201a4110747221032002280208211220022802e009212b20022903d809210d410521040c190b410721030c1e0b20024100360208200241086a20062005410420054104491b2204101e1a200141046a200520046b3602002001200620046a36020041032104200541034d0d1d0c010b2002410036020841042104200241086a20062005410420054104491b2207101e1a200141046a200520076b3602002001200620076a360200200541034d0d1c0b200228020821050c150b20024100360208200241086a20062005410420054104491b2204101e1a200141046a2208200520046b22073602002001200620046a2206360200200541034d0d1a20022802082112200241f8096a2007412020074120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20062004101e1a2008200720046b22093602002001200620046a22043602002007411f4d0d06200241086a41186a2206200241f8096a41186a2205290300370300200241086a41106a2207200241f8096a41106a2208290300370300200241086a41086a220a200241f8096a41086a2211290300370300200220022903f809370308200820072903003703002011200a29030037030020052006290300370300200241d8116a41086a2206200241870a6a280000360200200220022903083703f809200220022900ff093703d81120052d0000210820022800fb09210520022d008b0a211820022d008c0a210720022f008d0a211720022d008f0a211920022f00910a211620022d00930a211d20022d00940a211e20022f00950a210a20022d00970a211120022f01f809212420022d00fa092125200241d8096a41086a2006280200360200200220022903d8113703d80920024100360208200241086a20042009410420094104491b2206101e1a200141046a221a200920066b22153602002001200420066a2204360200200941034d0d1a2002350208210b20024100360208200241086a20042015410420154104491b2206101e1a201a201520066b3602002001200420066a360200201541034d0d1a202420254110747221032002350208422086200b84210c20022802e009212b20022903d809210d410221040c140b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c190b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c180b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c170b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c120b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c150b200241d8106a10220c140b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c130b410121110b2002200a36020c20022011360208200241003602100240200a450d00200141046a211d200241106a211241002105410021080340200241003a00d811200241d8116a200620044100472207101e1a201d200420076b22093602002001200620076a2206360200024002402004450d00200841016a210820022d00d81141017121042005200228020c470d01200241086a102320122802002105200228020821110c010b200228020c450d14201110020c140b201120056a20043a00002012200541016a2205360200200921042008200a490d000b200228020821110b2011450d112011410020111b2105200229020c210d20024100360208200241086a20012802002207200141046a22082802002204410420044104491b2206101e1a2008200420066b3602002001200720066a3602000240200441034d0d002002280208212b410121040c0c0b200da7450d11200510020c110b1024000b200241f8096a41386a200241086a41386a290000370300200241f8096a41306a200241086a41306a290000370300200241f8096a41286a200241086a41286a290000370300200241f8096a41206a200241086a41206a290000370300202e202d2900003703002030202f29000037030020322031290000370300200220022900083703f8090c0b0b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c0a0b200241f8096a41386a200241086a41386a290000370300200241f8096a41306a200241086a41306a290000370300200241f8096a41286a200241086a41286a290000370300200241f8096a41206a200241086a41206a2900003703002007201629000037030020182017290000370300201a2019290000370300200220022900083703f8090c090b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c080b20024100360208200241086a20042006410420064104491b2205101e1a200141046a2208200620056b22073602002001200420056a2205360200200641034d0d0720022802082115200241f8096a2007412020074120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20052004101e1a2008200720046b22063602002001200520046a22253602002007411f4d0d01200241086a41186a221b200241f8096a41186a221a290300370300200241086a41106a2223200241f8096a41106a2224290300370300200241086a41086a2226200241f8096a41086a2227290300370300200220022903f80937030820242023290300370300201a201b29030037030020272026290300370300200220022903083703f80920242d00002108201a2d0000210520022800fb09211c20022800ff09212b20022d00830a211820022d00840a210720022f00850a211720022d00870a211920022f00890a211620022d008b0a211d20022d008c0a211e20022f008d0a210a20022d008f0a211120022f00910a210f20022d00930a211220022d00940a211f20022f00950a212020022d00970a211020022f01f809212a20022d00fa092133200241f8096a200641c000200641c0004922281b22046a4100410041c00020046b2004413f4b1b10171a200241f8096a20252004101e1a200141046a2229200620046b22063602002001202520046a222536020020280d02200241086a41386a2204200241f8096a41386a2228290300370300200241086a41306a222e200241f8096a41306a2221290300370300200241086a41286a2222200241f8096a41286a222c290300370300200241086a41206a222d200241f8096a41206a222f290300370300201b201a2903003703002023202429030037030020262027290300370300200220022903f8093703082024202329030037030020272026290300370300201a201b290300370300202f202d290300370300202c20222903003703002021202e2903003703002028200429030037030020024198116a41086a2204200241870a6a29000037030020024198116a41106a221a2002418f0a6a29000037030020024198116a41186a2224200241f8096a411f6a29000037030020024198116a41206a221b2002419f0a6a29000037030020024198116a41286a2223200241a70a6a29000037030020024198116a41306a2226200241af0a6a29000037030020024198116a41386a2227200241f8096a413f6a2d00003a0000200220022903083703f809200220022900ff093703981120023502f809210c20023201fc09211320023100fe092114200241d8106a41386a20272d00003a0000200241d8106a41306a2026290300370300200241d8106a41286a2023290300370300200241d8106a41206a201b290300370300200241d8106a41186a2024290300370300200241d8106a41106a201a290300370300200241d8106a41086a200429030037030020022002290398113703d810200241f8096a2006412020064120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20252004101e1a2029200620046b221a3602002001202520046a22243602002006411f4d0d03200241086a41186a2225200241f8096a41186a222e290300370300200241086a41106a221b200241f8096a41106a2221290300370300200241086a41086a2223200241f8096a41086a2222290300370300200220022903f809370308202e2025290300223a3703002021201b290300223b37030020222023290300223c370300200241b8126a41086a2204203c370300200241b8126a41106a2206203b370300200241b8126a41186a2226203a37030020022002290308223a3703b8122002203a3703f809200241d8096a41186a2026290300370300200241d8096a41106a2006290300370300200241d8096a41086a2004290300370300200220022903b8123703d80941002104200241f8096a201a41c000201a41c000491b22066a4100410041c00020066b2006413f4b1b10171a200241f8096a20242006101e1a200141046a201a20066b3602002001202420066a360200201a413f4d0d04202a2033411074722137200c201320144210868442208684210c200241086a41386a2206200241f8096a41386a222c290300370300200241086a41306a221a200241f8096a41306a222d290300370300200241086a41286a2224200241f8096a41286a222f290300370300200241086a41206a2226200241f8096a41206a22302903003703002025202e290300370300201b202129030037030020232022290300370300200220022903f809370308202c20062903002213370300202d201a2903002214370300202f2024290300223a37030020302026290300223b370300202e2025290300223c3703002021201b290300223d37030020222023290300223e370300200241d8116a41086a2227203e370300200241d8116a41106a2228203d370300200241d8116a41186a2229203c370300200241d8116a41206a222a203b370300200241d8116a41286a2233203a370300200241d8116a41306a22312014370300200241d8116a41386a223220133703002002200229030822133703d811200220133703f809200241e0126a41086a200241e7096a28000036020020232027290300370300201b2028290300370300202520292903003703002026202a29030037030020242033290300370300201a203129030037030020062032290300370300200220022900df093703e012200220022903d81137030820022800db09211a20022d00eb09212420022d00ec09212520022f00ed09211b20022d00ef09212320022d00f009212620022f00f109212720022d00f309212820022d00f409212920022f00f509212a20022d00f709213320022f01d809210620022d00da092131202c200241d8106a41386a2d00003a0000202d200241d8106a41306a290300370300202f200241d8106a41286a2903003703002030200241d8106a41206a290300370300202e200241d8106a41186a2903003703002021200241d8106a41106a2903003703002022200241d8106a41086a290300370300200220022903d8103703f809200620314110747221060b20024198116a41386a200241f8096a41386a2d00003a000020024198116a41306a200241f8096a41306a29030037030020024198116a41286a200241f8096a41286a29030037030020024198116a41206a200241f8096a41206a29030037030020024198116a41186a200241f8096a41186a29030037030020024198116a41106a200241f8096a41106a29030037030020024198116a41086a200241f8096a41086a29030037030020024188106a41086a200241e0126a41086a280200360200200220022903f80937039811200220022903e01237038810200241d8116a41386a200241086a41386a290300370300200241d8116a41306a200241086a41306a290300370300200241d8116a41286a200241086a41286a290300370300200241d8116a41206a200241086a41206a290300370300200241d8116a41186a200241086a41186a290300370300200241d8116a41106a200241086a41106a290300370300200241d8116a41086a200241086a41086a29030037030020024184106a41026a200241d8106a41026a2d00003a0000200220022903083703d811200220022f00d8103b018410200241e00f6a41186a20024198106a41186a290300370300200241e00f6a41106a20024198106a41106a290300370300200241e00f6a41086a20024198106a41086a29030037030020022002290398103703e00f200241c00f6a41186a200241b8106a41186a290300370300200241c00f6a41106a200241b8106a41106a290300370300200241c00f6a41086a200241b8106a41086a290300370300200220022903b8103703c00f0c070b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c050b200241f8096a41386a200241086a41386a290000370300200241f8096a41306a200241086a41306a290000370300200241f8096a41286a200241086a41286a290000370300200241f8096a41206a200241086a41206a290000370300201a201b2900003703002024202329000037030020272026290000370300200220022900083703f8090c040b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c030b200241f8096a41386a200241086a41386a290000370300200241f8096a41306a200241086a41306a290000370300200241f8096a41286a200241086a41286a290000370300200241f8096a41206a200241086a41206a290000370300202e20252900003703002021201b29000037030020222023290000370300200220022900083703f8090c020b20024198096a41086a200241d8116a41086a29030037030020024198096a41106a200241d8116a41106a29030037030020024198096a41186a200241d8116a41186a29030037030020024198096a41206a200241d8116a41206a29030037030020024198096a41286a200241d8116a41286a29030037030020024198096a41306a200241d8116a41306a29030037030020024198096a41386a200241d8116a41386a2d00003a0000200220022f0198113b01d609200220022903d8113703980920024188096a41086a200241800b6a41086a280200360200200241c8086a41086a200241086a41086a290000370300200241c8086a41106a200241086a41106a290000370300200241c8086a41186a200241086a41186a290000370300200241c8086a41206a200241086a41206a290000370300200241c8086a41286a200241086a41286a290000370300200241c8086a41306a200241086a41306a290000370300200241c8086a41386a200241086a41386a290000370300200220022903800b37038809200220022900083703c808200241c4086a41026a200241f8096a41026a2d00003a0000200241a0086a41186a200241b00e6a41186a290300370300200241a0086a41106a200241b00e6a41106a290300370300200241a0086a41086a200241b00e6a41086a29030037030020024180086a41186a200241d80c6a41186a29030037030020024180086a41106a200241d80c6a41106a29030037030020024180086a41086a200241d80c6a41086a290300370300200220022f00f8093b01c408200220022903b00e3703a008200220022903d80c370380082005ad421886200341ffffff0771ad84420886200441ff0171ad84210b202b411076211f202b4108762120410521030c060b20024198096a41086a200241d8116a41086a29030037030020024198096a41106a200241d8116a41106a29030037030020024198096a41186a200241d8116a41186a29030037030020024198096a41206a200241d8116a41206a29030037030020024198096a41286a200241d8116a41286a29030037030020024198096a41306a200241d8116a41306a29030037030020024198096a41386a200241d8116a41386a2d00003a0000200220022f0198113b01d609200220022903d8113703980920024188096a41086a200241800b6a41086a280200360200200241c8086a41086a200241086a41086a290000370300200241c8086a41106a200241086a41106a290000370300200241c8086a41186a200241086a41186a290000370300200241c8086a41206a200241086a41206a290000370300200241c8086a41286a200241086a41286a290000370300200241c8086a41306a200241086a41306a290000370300200241c8086a41386a200241086a41386a290000370300200220022903800b37038809200220022900083703c80841022103200241c4086a41026a200241f8096a41026a2d00003a0000200241a0086a41186a200241b00e6a41186a290300370300200241a0086a41106a200241b00e6a41106a290300370300200241a0086a41086a200241b00e6a41086a29030037030020024180086a41186a200241d80c6a41186a29030037030020024180086a41106a200241d80c6a41106a29030037030020024180086a41086a200241d80c6a41086a290300370300200220022f00f8093b01c408200220022903b00e3703a008200220022903d80c370380082005ad421886200941ffffff0771ad84420886200641ff0171ad84210b202b411076211f202b4108762120200441ff017121110c050b410221040b200241f8096a41386a222e20024198116a41386a2d00003a0000200241f8096a41306a222120024198116a41306a290300370300200241f8096a41286a222220024198116a41286a290300370300200241f8096a41206a222c20024198116a41206a290300370300200241f8096a41186a222d20024198116a41186a290300370300200241f8096a41106a222f20024198116a41106a290300370300200241f8096a41086a223020024198116a41086a290300370300200241e0126a41086a223120024188106a41086a28020036020020022002290398113703f80920022002290388103703e012200241086a41386a2232200241d8116a41386a290300370300200241086a41306a2234200241d8116a41306a290300370300200241086a41286a2235200241d8116a41286a290300370300200241086a41206a2236200241d8116a41206a290300370300200241086a41186a2238200241d8116a41186a290300370300200241086a41106a2239200241d8116a41106a290300370300200241086a41086a223f200241d8116a41086a290300370300200241dc126a41026a20024184106a41026a2d00003a0000200220022903d811370308200220022f0184103b01dc12200241b8126a41186a2240200241e00f6a41186a290300370300200241b8126a41106a2241200241e00f6a41106a290300370300200241b8126a41086a2242200241e00f6a41086a29030037030020024198126a41186a2243200241c00f6a41186a29030037030020024198126a41106a2244200241c00f6a41106a29030037030020024198126a41086a2245200241c00f6a41086a290300370300200220022903e00f3703b812200220022903c00f370398120240024020044102470d004102210441024102470d010c020b200241800f6a41386a202e2d00003a0000200241800f6a41306a2021290300370300200241800f6a41286a2022290300370300200241800f6a41206a202c290300370300200241800f6a41186a202d290300370300200241800f6a41106a202f290300370300200241800f6a41086a2030290300370300200241f00e6a41086a2031280200360200200220022903f8093703800f200220022903e0123703f00e200241b00e6a41386a2032290300370300200241b00e6a41306a2034290300370300200241b00e6a41286a2035290300370300200241b00e6a41206a2036290300370300200241b00e6a41186a2038290300370300200241b00e6a41106a2039290300370300200241b00e6a41086a203f290300370300200241ac0e6a41026a200241dc126a41026a2d00003a0000200220022903083703b00e200220022f01dc123b01ac0e200241880e6a41186a2040290300370300200241880e6a41106a2041290300370300200241880e6a41086a2042290300370300200220022903b8123703880e200241e80d6a41186a2043290300370300200241e80d6a41106a2044290300370300200241e80d6a41086a204529030037030020022002290398123703e80d200c420886201041ff0171ad84210c2020411074201f41ff017141087472201241ff0171722112200f411074200541ff017141087472201141ff017172211120044102460d010b20024198116a41386a200241800f6a41386a2d00003a000020024198116a41306a200241800f6a41306a29030037030020024198116a41286a200241800f6a41286a29030037030020024198116a41206a200241800f6a41206a29030037030020024198116a41186a200241800f6a41186a29030037030020024198116a41106a200241800f6a41106a29030037030020024198116a41086a200241800f6a41086a29030037030020024188106a41086a200241f00e6a41086a280200360200200220022903800f37039811200220022903f00e37038810200241d8116a41386a200241b00e6a41386a290300370300200241d8116a41306a200241b00e6a41306a290300370300200241d8116a41286a200241b00e6a41286a290300370300200241d8116a41206a200241b00e6a41206a290300370300200241d8116a41186a200241b00e6a41186a290300370300200241d8116a41106a200241b00e6a41106a290300370300200241d8116a41086a200241b00e6a41086a29030037030020024184106a41026a200241ac0e6a41026a2d00003a0000200220022903b00e3703d811200220022f01ac0e3b018410200241e00f6a41186a200241880e6a41186a290300370300200241e00f6a41106a200241880e6a41106a290300370300200241e00f6a41086a200241880e6a41086a290300370300200220022903880e3703e00f200241c00f6a41186a200241e80d6a41186a290300370300200241c00f6a41106a200241e80d6a41106a290300370300200241c00f6a41086a200241e80d6a41086a290300370300200220022903e80d3703c00f201cad421886203741ffffff0771ad84420886210d0c010b410321040b200241f8096a41386a220520024198116a41386a2d00003a0000200241f8096a41306a221c20024198116a41306a290300370300200241f8096a41286a220f20024198116a41286a290300370300200241f8096a41206a221f20024198116a41206a290300370300200241f8096a41186a222020024198116a41186a290300370300200241f8096a41106a221020024198116a41106a290300370300200241f8096a41086a20024198116a41086a290300370300200241e0126a41086a20024188106a41086a28020036020020022002290398113703f80920022002290388103703e012200241086a41386a222e200241d8116a41386a290300370300200241086a41306a2221200241d8116a41306a290300370300200241086a41286a2222200241d8116a41286a290300370300200241086a41206a222c200241d8116a41206a290300370300200241086a41186a222d200241d8116a41186a290300370300200241086a41106a222f200241d8116a41106a290300370300200241086a41086a200241d8116a41086a290300370300200241dc126a41026a223020024184106a41026a2d00003a0000200220022903d811370308200220022f0184103b01dc12200241b8126a41186a2231200241e00f6a41186a290300370300200241b8126a41106a2232200241e00f6a41106a290300370300200241b8126a41086a200241e00f6a41086a29030037030020024198126a41186a2234200241c00f6a41186a29030037030020024198126a41106a2235200241c00f6a41106a29030037030020024198126a41086a200241c00f6a41086a290300370300200220022903e00f3703b812200220022903c00f37039812024020044103460d00200241a80d6a41386a20052d00003a0000200241a80d6a41306a201c290300370300200241a80d6a41286a200f290300370300200241a80d6a41206a201f290300370300200241a80d6a41186a2020290300370300200241a80d6a41106a2010290300370300200241a80d6a41086a200241f8096a41086a290300370300200241980d6a41086a200241e0126a41086a280200360200200220022903f8093703a80d200220022903e0123703980d200241d80c6a41386a202e290300370300200241d80c6a41306a2021290300370300200241d80c6a41286a2022290300370300200241d80c6a41206a202c290300370300200241d80c6a41186a202d290300370300200241d80c6a41106a202f290300370300200241d80c6a41086a200241086a41086a290300370300200241d40c6a41026a20302d00003a0000200220022903083703d80c200220022f01dc123b01d40c200241b00c6a41186a2031290300370300200241b00c6a41106a2032290300370300200241b00c6a41086a200241b8126a41086a290300370300200220022903b8123703b00c200241900c6a41186a2034290300370300200241900c6a41106a2035290300370300200241900c6a41086a20024198126a41086a29030037030020022002290398123703900c200421090b20094103460d0020024198096a41086a200241a80d6a41086a29030037030020024198096a41106a200241a80d6a41106a29030037030020024198096a41186a200241a80d6a41186a29030037030020024198096a41206a200241a80d6a41206a29030037030020024198096a41286a200241a80d6a41286a29030037030020024198096a41306a200241a80d6a41306a29030037030020024198096a41386a200241a80d6a41386a2d00003a0000200220022f018e0c3b01d609200220022903a80d3703980920024188096a41086a200241980d6a41086a280200360200200241c8086a41086a200241d80c6a41086a290300370300200241c8086a41106a200241d80c6a41106a290300370300200241c8086a41186a200241d80c6a41186a290300370300200241c8086a41206a200241d80c6a41206a290300370300200241c8086a41286a200241d80c6a41286a290300370300200241c8086a41306a200241d80c6a41306a290300370300200241c8086a41386a200241d80c6a41386a290300370300200220022903980d37038809200220022903d80c3703c808200241c4086a41026a200241d40c6a41026a2d00003a0000200241a0086a41186a200241b00c6a41186a290300370300200241a0086a41106a200241b00c6a41106a290300370300200241a0086a41086a200241b00c6a41086a29030037030020024180086a41186a200241900c6a41186a29030037030020024180086a41106a200241900c6a41106a29030037030020024180086a41086a200241900c6a41086a290300370300200220022f01d40c3b01c408200220022903b00c3703a008200220022903900c37038008202b411076211f202b4108762120200d200941ff0171ad84210d410021030c010b0c020b0b0b200241d00b6a41086a220f20024198096a41086a290300370300200241d00b6a41106a221020024198096a41106a290300370300200241d00b6a41186a222e20024198096a41186a290300370300200241d00b6a41206a222120024198096a41206a290300370300200241d00b6a41286a222220024198096a41286a290300370300200241d00b6a41306a222c20024198096a41306a290300370300200241d00b6a41386a222d20024198096a41386a2d00003a0000200220022f01d6093b018e0c20022002290398093703d00b200241c00b6a41086a222f20024188096a41086a280200360200200241800b6a41086a2230200241c8086a41086a290300370300200241800b6a41106a2231200241c8086a41106a290300370300200241800b6a41186a2232200241c8086a41186a290300370300200241800b6a41206a2234200241c8086a41206a290300370300200241800b6a41286a2235200241c8086a41286a290300370300200241800b6a41306a2236200241c8086a41306a290300370300200241800b6a41386a2238200241c8086a41386a29030037030020022002290388093703c00b200220022903c8083703800b200241fc0a6a41026a2239200241c4086a41026a2d00003a0000200241d80a6a41186a223f200241a0086a41186a290300370300200241d80a6a41106a2240200241a0086a41106a290300370300200241d80a6a41086a2241200241a0086a41086a290300370300200241b80a6a41186a224220024180086a41186a290300370300200241b80a6a41106a224320024180086a41106a290300370300200241b80a6a41086a224420024180086a41086a290300370300200220022f01c4083b01fc0a200220022903a0083703d80a20022002290380083703b80a4107210420034107460d00200241d80c6a41086a200f290300370300200241d80c6a41106a2010290300370300200241d80c6a41186a202e290300370300200241d80c6a41206a2021290300370300200241d80c6a41286a2022290300370300200241d80c6a41306a202c290300370300200241d80c6a41386a202d2d00003a0000200220022f018e0c3b01c00f200220022903d00b3703d80c200241b8126a41086a202f280200360200200241d8116a41086a2030290300370300200241d8116a41106a2031290300370300200241d8116a41186a2032290300370300200241d8116a41206a2034290300370300200241d8116a41286a2035290300370300200241d8116a41306a2036290300370300200241d8116a41386a2038290300370300200220022903c00b3703b812200220022903800b3703d81120024198126a41026a20392d00003a000020024198116a41186a203f29030037030020024198116a41106a204029030037030020024198116a41086a2041290300370300200241800f6a41186a2042290300370300200241800f6a41106a2043290300370300200241800f6a41086a2044290300370300200220022f01fc0a3b019812200220022903d80a37039811200220022903b80a3703800f200241a80d6a41186a200241c0076a41186a290300370300200241a80d6a41106a200241c0076a41106a290300370300200241a80d6a41086a200241c0076a41086a290300370300200220022903c0073703a80d201f411074202041ff017141087472202b41ff017172210f200321040c010b0b200241b00e6a41086a222b200241d80c6a41086a290300370300200241b00e6a41106a221f200241d80c6a41106a290300370300200241b00e6a41186a2220200241d80c6a41186a290300370300200241b00e6a41206a2210200241d80c6a41206a290300370300200241b00e6a41286a222e200241d80c6a41286a290300370300200241b00e6a41306a2221200241d80c6a41306a290300370300200241b00e6a41386a2222200241d80c6a41386a2d00003a0000200220022f01c00f3b01e00f200220022903d80c3703b00e200241d00b6a41086a222c200241b8126a41086a280200360200200241086a41086a222d200241d8116a41086a290300370300200241086a41106a222f200241d8116a41106a290300370300200241086a41186a2230200241d8116a41186a290300370300200241086a41206a2231200241d8116a41206a290300370300200241086a41286a2232200241d8116a41286a290300370300200241086a41306a2234200241d8116a41306a290300370300200241086a41386a2235200241d8116a41386a290300370300200220022903b8123703d00b200220022903d81137030820024198096a41026a223620024198126a41026a2d00003a0000200241800b6a41186a223820024198116a41186a290300370300200241800b6a41106a223920024198116a41106a290300370300200241800b6a41086a223f20024198116a41086a290300370300200241f8096a41186a2240200241800f6a41186a290300370300200241f8096a41106a2241200241800f6a41106a290300370300200241f8096a41086a2242200241800f6a41086a290300370300200220022f0198123b01980920022002290398113703800b200220022903800f3703f809200241c8086a41186a2243200241a80d6a41186a290300370300200241c8086a41106a2244200241a80d6a41106a290300370300200241c8086a41086a2245200241a80d6a41086a290300370300200220022903a80d3703c80841072103024020044107460d0020024180076a41086a202b29030037030020024180076a41106a201f29030037030020024180076a41186a202029030037030020024180076a41206a201029030037030020024180076a41286a202e29030037030020024180076a41306a202129030037030020024180076a41386a20222d00003a0000200220022f01e00f3b01be07200220022903b00e37038007200241f0066a41086a202c280200360200200241b0066a41086a202d290300370300200241b0066a41106a202f290300370300200241b0066a41186a2030290300370300200241b0066a41206a2031290300370300200241b0066a41286a2032290300370300200241b0066a41306a2034290300370300200241b0066a41386a2035290300370300200220022903d00b3703f006200220022903083703b006200241ac066a41026a20362d00003a000020024188066a41186a203829030037030020024188066a41106a203929030037030020024188066a41086a203f290300370300200241e8056a41186a2040290300370300200241e8056a41106a2041290300370300200241e8056a41086a2042290300370300200220022f0198093b01ac06200220022903800b37038806200220022903f8093703e805200241c8056a41186a2043290300370300200241c8056a41106a2044290300370300200241c8056a41086a2045290300370300200220022903c8083703c805200421030b024020034107470d00200041073a0008200241f0126a24000f0b20024197036a20054110763a000020024195036a20053b000020024191036a20093a000020024192036a20022f01be073b010020024194036a201c3a000020024188036a41106a2209200b37030020024188036a41186a200d37030020024188036a41206a200f360200200241ac036a20183a0000200241ad036a20073a0000200241ae036a20173b010020024188036a41286a20193a0000200241b1036a20083a0000200241b2036a20163b0100200241b4036a201d3a0000200241b5036a201e3a0000200241b6036a200a3b0100200220033a0090032002200e37038803200241bc036a201236020020024188036a41306a201136020020024188036a41386a200c37030020024188036a41c0006a200229038007370300200241d0036a20024180076a41086a290300370300200241d8036a20024180076a41106a290300370300200241e0036a20024180076a41186a290300370300200241e8036a20024180076a41206a290300370300200241f0036a20024180076a41286a290300370300200241f8036a20024180076a41306a29030037030020024180046a20024180076a41386a2d00003a000020024183046a20064110763a000020024181046a20063b000020024184046a201a36020020024194046a20243a000020024195046a20253a000020024196046a201b3b010020024198046a20233a000020024199046a20263a00002002419a046a20273b01002002419c046a20283a00002002419d046a20293a00002002419e046a202a3b0100200241a0046a20333a000020024190046a200241f0066a41086a28020036020020024188046a20022903f006370300200241d9046a200241b0066a41386a290300370000200241d1046a200241b0066a41306a290300370000200241c9046a200241b0066a41286a290300370000200241c1046a200241b0066a41206a290300370000200241b9046a200241b0066a41186a290300370000200241b1046a200241b0066a41106a290300370000200241a9046a200241b0066a41086a290300370000200241a1046a20022903b006370000200241e3046a200241ae066a2d00003a0000200241e1046a20022f01ac063b0000200241e4046a201536020020024180056a20024188066a41186a290300370300200241f8046a20024188066a41106a290300370300200241f0046a20024188066a41086a290300370300200241e8046a200229038806370300200241a0056a200241e8056a41186a29030037030020024198056a200241e8056a41106a29030037030020024190056a200241e8056a41086a29030037030020024188056a20022903e805370300200241c0056a200241c8056a41186a290300370300200241b8056a200241c8056a41106a290300370300200241b0056a200241c8056a41086a290300370300200220022903c8053703a80520012802002105200241f8096a200141046a2206280200220441c000200441c000491b22036a4100410041c00020036b2003413f4b1b10171a200241f8096a20052003101e1a2006200420036b3602002001200520036a36020002402004413f4d0d00200241086a41386a2209200241f8096a41386a2201290300370300200241086a41306a220a200241f8096a41306a2203290300370300200241086a41286a2211200241f8096a41286a2204290300370300200241086a41206a2212200241f8096a41206a2205290300370300200241086a41186a221d200241f8096a41186a2206290300370300200241086a41106a2216200241f8096a41106a2207290300370300200241086a41086a2217200241f8096a41086a2208290300370300200220022903f80937030820012009290300220b3703002003200a290300220c37030020042011290300220d37030020052012290300220e3703002006201d290300221337030020072016290300221437030020082017290300223a370300200241d8116a41086a2209203a370300200241d8116a41106a220a2014370300200241d8116a41186a22112013370300200241d8116a41206a2212200e370300200241d8116a41286a221d200d370300200241d8116a41306a2216200c370300200241d8116a41386a2217200b37030020022002290308220b3703d8112002200b3703f809200241b00e6a41386a22182017290300370300200241b00e6a41306a22172016290300370300200241b00e6a41286a2216201d290300370300200241b00e6a41206a221d2012290300370300200241b00e6a41186a22122011290300370300200241b00e6a41106a2211200a290300370300200241b00e6a41086a220a2009290300370300200220022903d8113703b00e20012018290300220b37030020032017290300220c37030020042016290300220d3703002005201d290300220e3703002006201229030022133703002007201129030022143703002008200a290300223a370300200241d80c6a41086a2201203a370300200241d80c6a41106a22032014370300200241d80c6a41186a22042013370300200241d80c6a41206a2205200e370300200241d80c6a41286a2206200d370300200241d80c6a41306a2207200c370300200241d80c6a41386a2208200b370300200220022903b00e220b3703d80c2002200b3703f809200241086a20024188036a41c002101e1a20024180036a2008290300370300200241f8026a2007290300370300200241f0026a2006290300370300200241e8026a2005290300370300200241e0026a2004290300370300200241d8026a2003290300370300200241d0026a2001290300370300200220022903d80c3703c8022000200241086a418003101e1a200241f0126a24000f0b200241f8096a41386a2201200241086a41386a290000370300200241f8096a41306a2203200241086a41306a290000370300200241f8096a41286a2204200241086a41286a290000370300200241f8096a41206a2205200241086a41206a290000370300200241f8096a41186a2206200241086a41186a290000370300200241f8096a41106a2207200241086a41106a290000370300200241f8096a41086a2208200241086a41086a290000370300200220022900083703f8092001200241b00e6a41386a2900003703002003200241b00e6a41306a2900003703002004200241b00e6a41286a2900003703002005200241b00e6a41206a2900003703002006200241b00e6a41186a2900003703002007200241b00e6a41106a2900003703002008200241b00e6a41086a290000370300200220022900b00e3703f809200041073a0008024020024188036a41086a2d00002201411d74411d75417f4a0d000240024020014104460d0020014105470d0120024198036a2d00004101470d02200241a0036a280200450d022002419c036a2802001002200241f0126a24000f0b20024198036a2d00004101470d012002419c036a1025200241f0126a24000f0b20024194036a2d00004101470d0020091025200241f0126a24000f0b200241f0126a24000bd81a05077f017e027f017e017f230041c0016b22012400200141003a00a001200141a0016a20002802002202200028020422034100472204101e1a2000200320046b22053602042000200220046a220236020002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402003450d004106210420012d00a001220341074b0d19024020030e080004021b1b050603000b200141003a00a001200141a0016a200220054100472203101e1a200041046a200520036b22063602002000200220036a22033602002005450d1920012d00a0012205450d0820054101470d19200141003602a001200141a0016a20032006410420064104491b2205101e1a200041046a200620056b3602002000200320056a360200200641034d0d1920012802a0012207ad42187e2208422088a70d152008a72203417f4c0d142003450d112003100122090d120c1b0b410621040c180b200141003a00a001200141a0016a200220054100472203101e1a41042109200041046a200520036b22063602002000200220036a22033602002005450d1720012d00a001220541034b0d17024020050e04000a0b0c000b200142003703a001200141a0016a20032006410820064108491b2205101e1a200041046a200620056b3602002000200320056a360200200641074d0d1720012903a0012108410121090c0b0b200141003a00a001200141a0016a200220054100472203101e1a200041046a200520036b22063602002000200220036a22033602002005450d1620012d00a0012205450d0320054101470d16200142003703a001200141a0016a20032006410820064108491b2205101e1a200041046a200620056b3602002000200320056a360200200641074d0d1620012903a00121084202210b0c040b200141003a00a001200141a0016a200220054100472203101e1a200041046a200520036b22063602002000200220036a22033602002005450d1520012d00a0012205450d054202210b20054101460d060c160b200141a0016a200010a00120012903a001220ba741ff01714103460d1520014180016a41086a200141a0016a41086a29020037030020014180016a41106a200141a0016a41106a290200370300200120012902a001370380012001200b370348410321040c150b200141003a00a001200141a0016a200220054100472206101e1a200041046a200520066b22033602002000200220066a220236020002402005450d004105210520012d00a001220641034b0d11024020060e04000c0a0b000b200141003602a001200141a0016a20022003410420034104491b2206101e1a200041046a200320066b3602002000200220066a360200200341034d0d1120012802a0012100410121050c130b410521050c100b200142003703a001200141a0016a20032006410820064108491b2205101e1a200041046a200620056b3602002000200320056a360200200641074d0d1220012903a00121084201210b0b20014180016a41086a200141a0016a41086a29030037030020014180016a41106a200141a0016a41106a290300370300200120012903a001370380012001200b37024c410521040c120b200141a0016a2000101f20012802a0012209450d1020012902a4012108410121000c0a0b200142003703a001200141a0016a200320064108200641084922021b2205101e1a200041046a200620056b3602002000200320056a36020020020d0f20012903a00121084201210b0b20014180016a41086a200141a0016a41086a29030037030020014180016a41106a200141a0016a41106a290300370300200120012903a001370380012001200b37024c410121040c0f0b200142003703a001200141a0016a20032006410820064108491b2205101e1a200041046a200620056b3602002000200320056a360200200641074d0d0d20012903a0012108410221090c010b200141003602a001200141a0016a20032006410420064104491b2205101e1a200041046a200620056b3602002000200320056a36020041032109200641034d0d0c20012802a00121020b20014180016a41086a200141a0016a41086a29030037030020014180016a41106a200141a0016a41106a290300370300200120023602502001200936024c200120012903a00137038001410221040c0c0b200142003703a001200141a0016a20022003410820034108491b2206101e1a200041046a200320066b3602002000200220066a360200200341074d0d0720012903a0012108410321050c080b200142003703a001200141a0016a20022003410820034108491b2206101e1a200041046a200320066b3602002000200220066a360200200341074d0d0620012903a0012108410421050c080b200141a0016a2003412020034120491b22066a41004100412020066b2006411f4b1b10171a200141a0016a20022006101e1a200041046a200320066b3602002000200220066a36020002402003411f4d0d0020014180016a41186a2200200141a0016a41186a220329030037030020014180016a41106a2205200141a0016a41106a220229030037030020014180016a41086a2206200141a0016a41086a2209290300370300200120012903a0013703800120032000290300370300200220052903003703002009200629030037030020012001290380013703a00141022105200141fc006a41026a220320012d00a2013a0000200141e8006a41086a2202200141b7016a290000370300200141e8006a41106a2206200141a0016a411f6a2d00003a0000200120012f01a0013b017c200120012900af0137036820012800a301210020012900a7012108200141e4006a41026a20032d00003a0000200141c8006a41086a2002290300370300200141c8006a41106a20062d00003a0000200120012f017c3b0164200120012903683703480c080b200141a0016a41186a20014180016a41186a290000370300200141a0016a41106a20014180016a41106a290000370300200141a0016a41086a20014180016a41086a29000037030020012001290080013703a0010c050b410421090b2001200736024c20012009360248410021032001410036025002402007450d00200141d0006a210c41002102034020014180016a2000101f024002402001280280012206450d002001290284012108200141a0016a2000101f024020012802a001220a450d00200241016a210220012902a401210b2003200128024c470d02200141c8006a1076200c2802002103200128024821090c020b2008a7450d00200610020b2001280248210502402003450d00200341186c21032005210003400240200041046a280200450d00200028020010020b0240200041106a280200450d002000410c6a28020010020b200041186a2100200341686a22030d000b0b200128024c450d09200510020c090b2009200341186c6a22052008370204200520063602002005410c6a200a360200200541106a200b370200200c200341016a220336020020022007490d000b200128024821090b2009450d06200129024c2108410221000b20014180016a41086a200141a0016a41086a29020037030020014180016a41106a200141a0016a41106a29020037030020012000360248200120012902a00137038001200120084220862009ad8437024c20084220882108410021040c060b1061000b1060000b0b0b20014180016a41026a2203200141e4006a41026a2d00003a0000200141a0016a41086a2202200141c8006a41086a290300370300200141a0016a41106a2206200141c8006a41106a290300370300200120012f01643b018001200120012903483703a00120054105460d00200141c4006a41026a220420032d00003a0000200141286a41086a22032002290300370300200141286a41106a22022006290300370300200120012f0180013b0144200120012903a00137032820014180016a41086a200329030037030020014180016a41106a2002290300370300200120053a004c20012000360250200120012f01443b004d200120042d00003a004f2001200129032837038001410421040c010b0b200141c4006a41026a220020012d004f3a0000200141286a41086a220520014180016a41086a290300370300200141286a41106a220220014180016a41106a290300370300200120012f004d3b014420012001290380013703282001280250210620012d004c21092001280248210a41062103024020044106460d00200141246a41026a20002d00003a0000200141086a41086a2005290300370300200141086a41106a2002290300370300200120012f01443b012420012001290328370308200421030b024020034106470d00200141c0016a240041000f0b20014180016a41026a2204200141246a41026a2d00003a0000200141a0016a41086a2205200141086a41086a290300370300200141a0016a41106a2202200141086a41106a290300370300200120012f01243b018001200120012903083703a001413010012200450d002000200a36020420002003360200200020093a0008200020012f0180013b00092000200636000c20002008370210200020012903a0013702182000410b6a20042d00003a0000200041206a2005290300370200200041286a2002290300370200200141c0016a240020000f0b101c000be60101037f0240024002402000280200220128020022024103460d0020020d0220012802042202450d0220024101470d012001410c6a280200450d02200141086a2802001002200028020010020f0b20012d00044101470d01200141086a1022200028020010020f0b0240200141106a2802002203450d00200141086a2802002102200341186c210303400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200341686a22030d000b0b2001410c6a280200450d00200141086a28020010020b200028020010020b7901047f0240024002400240200041046a2802002201450d002001418080808004710d03200028020021022001410174220310012204450d022004200220032001200120034b1b101e1a200210020c010b410410012204450d01410421030b20002004360200200041046a20033602000f0b101c000b106e000b05001041000be60101037f0240024002402000280200220128020022024103460d0020020d0220012802042202450d0220024101470d012001410c6a280200450d02200141086a2802001002200028020010020f0b20012d00044101470d01200141086a1025200028020010020f0b0240200141106a2802002203450d00200141086a2802002102200341186c210303400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200341686a22030d000b0b2001410c6a280200450d00200141086a28020010020b200028020010020b890403037f017e027f230041206b22022400200241003602082002420137030020024100410410272002280200200228020822036a41003600002002200341046a220336020820022003412010272002280200200228020822046a220320012900a002370000200341186a200141b8026a290000370000200341106a200141b0026a290000370000200341086a200141a8026a2900003700002002200441206a22033602082001290300210520022003410810272002280200200228020822036a20053700002002200341086a2206360208200241106a200141086a1028200228021021042002200620022802182203102720022003200228020822066a2207360208200620022802006a20042003101e1a02402002280214450d00200410020b2002200741c0001027200241086a22032003280200220441c0006a22063602002004200228020022076a220320012900c002370000200341086a200141c8026a290000370000200341106a200141d0026a290000370000200341186a200141d8026a290000370000200341206a200141e0026a290000370000200341286a200141e8026a290000370000200341306a200141f0026a290000370000200341386a200141f8026a2900003700000240200641034d0d002000200229030037020020072004413c6a360000200041086a200241086a280200360200200241206a24000f0b410420061029000ba10101027f024002400240200041046a280200220320016b20024f0d00200120026a220220014922010d0141000d01200341017422044100200220011b2201200420014b1b22014100480d01024002402003450d0020002802002104200110012202450d042002200420012003200320014b1b101e1a200410020c010b200110012202450d030b20002002360200200041046a20013602000b0f0b1041000b101c000bfb2602077f017e230041306b22022400200241003602082002420137030002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a220341054b0d0002400240024002400240024020030e06000402030105000b2002107e2002280200200241086a22032802006a41013a00002003200328020041016a2204360200200241003602282002420137032020012d0001450d16200241206a107e2002280220200241206a41086a220528020022066a41003a00002005200641016a2206360200200241206a20064120102720052005280200220741206a22063602002007200228022022086a2205200141026a290000370000200541086a2001410a6a290000370000200541106a200141126a290000370000200541186a2001411a6a29000037000020022802242101200220042006102720032003280200220520066a360200200520022802006a20082006101e1a2001450d14200810020c140b2002107e2002280200200241086a22032802006a41063a00002003200328020041016a3602002002410036021820024201370310200141086a2d0000417f6a220341044b0d16024020030e05001210110f000b200241106a107e2002280210200241186a22032802006a41003a00002003200328020041016a2208360200200241206a2001410c6a10b80120022802202106200241106a200820022802282205102720032005200328020022086a360200200820022802106a20062005101e1a02402002280224450d00200610020b200141186a2802002101200241106a20032802004104102720032003280200220541046a360200200520022802106a20013600000c120b2002107e2002280200200241086a22032802006a41033a00002003200328020041016a3602002002410036022820024201370320200141086a2903004200510d16200241206a107e2002280220200241206a41086a220528020022066a41003a00002005200641016a2206360200200141106a2903002109200241206a20064108102720052005280200220641086a22013602002006200228022022056a200937000020022802242106200220032802002001102720032003280200220820016a360200200820022802006a20052001101e1a2006450d12200510020c120b2002107e2002280200200241086a22032802006a41053a00002003200328020041016a3602002002410036021820024201370310200141086a2d000022034103714101460d0520034102460d0320034103470d16200241106a107e2002280210200241186a220528020022036a41023a00002005200341016a22033602002001410c6a2802002106200241106a20034104102720052005280200220341046a2208360200200320022802106a2006360000200241106a20084101102720052005280200220641016a22033602002006200228021022056a200141096a2d00003a00000c060b2002107e2002280200200241086a22032802006a41023a00002003200328020041016a22063602002002410036022820024201370320200141086a2d000022054103714101460d0620054103460d0320054102470d16200241206a107e20022802202205200241286a220328020022016a41013a00002003200141016a22013602000c070b2002107e2002280200200241086a22032802006a41073a00002003200328020041016a22063602002002410036021820024201370310200141046a2d000022034103714101460d0820034102460d0720034103470d16200241106a107e2002280210200241106a41086a220528020022036a41023a00002005200341016a2203360200200241106a20034120102720052005280200220841206a22033602002008200228021022056a2208200141056a290000370000200841086a2001410d6a290000370000200841106a200141156a290000370000200841186a2001411d6a2900003700000c090b2002107e2002280200200241086a22032802006a41003a00002003200328020041016a3602002002410036022820024201370320200141106a2d00004102460d16200241206a107e2002280220200241206a41086a220328020022056a41003a00002003200541016a2207360200412010012203450d0f200341186a2206200141f0016a290000370000200341106a2208200141e8016a290000370000200341086a2204200141e0016a2900003700002003200141d8016a290000370000200141086a290300210941c00010012205450d0f20052003290000370000200541186a2006290000370000200541106a2008290000370000200541086a2004290000370000200310022005200937002041800110012203450d0f20032005290000370000200341386a2206200541386a290000370000200341306a2208200541306a290000370000200341286a2204200541286a290000370000200341206a200541206a290000370000200341186a200541186a290000370000200341106a200541106a290000370000200341086a200541086a29000037000020051002200341c0006a20014190026a290000370000200620014188026a290000370000200820014180026a2900003700002004200141f8016a29000037000020014191016a2105200141f1006a2108200141316a2106200141116a210402400240200141106a2d0000450d00200341c8006a41123a00002003200141d4016a2802003600492003200429000037004d200341d5006a200441086a290000370000200341dd006a200441106a290000370000200341e5006a200441186a29000037000041800210012201450d1120012003418001101e210120031002200141a5016a200641386a2900003700002001419d016a200641306a29000037000020014195016a200641286a2900003700002001418d016a200641206a29000037000020014185016a200641186a290000370000200141fd006a200641106a290000370000200141f5006a200641086a2900003700002001200629000037006d200120082900003700ad01200141b5016a200841086a290000370000200141bd016a200841106a290000370000200141c5016a200841186a29000037000041800410012206450d1120062001418002101e21032001100220034185026a200541386a290000370000200341fd016a200541306a290000370000200341f5016a200541286a290000370000200341ed016a200541206a290000370000200341e5016a200541186a290000370000200341dd016a200541106a290000370000200341d5016a200541086a290000370000200320052900003700cd010c010b200341c8006a41113a00002003200141d4016a2802003600492003200429000037004d200341d5006a200441086a290000370000200341dd006a200441106a290000370000200341e5006a200441186a29000037000041800210012201450d1020012003418001101e210120031002200141a5016a200641386a2900003700002001419d016a200641306a29000037000020014195016a200641286a2900003700002001418d016a200641206a29000037000020014185016a200641186a290000370000200141fd006a200641106a290000370000200141f5006a200641086a2900003700002001200629000037006d200120082900003700ad01200141b5016a200841086a290000370000200141bd016a200841106a290000370000200141c5016a200841186a29000037000041800410012206450d1020062001418002101e21032001100220034185026a200541386a290000370000200341fd016a200541306a290000370000200341f5016a200541286a290000370000200341ed016a200541206a290000370000200341e5016a200541186a290000370000200341dd016a200541106a290000370000200341d5016a200541086a290000370000200320052900003700cd010b200241206a2007418d021027200241206a41086a220120012802002203418d026a22013602002003200228022022056a2006418d02101e1a20061002200228022421062002200241086a22032802002001102720032003280200220820016a360200200820022802006a20052001101e1a2006450d0e200510020c0e0b200241106a107e2002280210200241186a220528020022036a41013a00002005200341016a22033602002001410c6a2802002101200241106a20034104102720052005280200220641046a22033602002006200228021022056a20013600000c020b200241206a107e20022802202205200241286a220328020022016a41023a00002003200141016a22013602000c030b200241106a107e2002280210200241106a41086a220328020022056a41003a00002003200541016a2208360200200241206a2001410c6a28020010d80120022802202106200241106a200820022802282205102720032005200328020022086a2204360200200820022802106a20062005101e1a02402002280224450d00200610020b200141106a2903002109200241106a200441081027200241106a41086a22012001280200220141086a22033602002001200228021022056a20093700000b200228021421062002200241086a22012802002003102720012001280200220820036a360200200820022802006a20052003101e1a2006450d0a200510020c0a0b200241206a107e2002280220200241206a41086a220628020022056a41003a00002006200541016a2205360200200241206a2005412010272002280220200628020022086a2205200141096a290000370000200541186a200141216a290000370000200541106a200141196a290000370000200541086a200141116a2900003700002006200841206a2205360200200141306a2903002109200241206a20054108102720022802202205200628020022016a20093700002006200141086a2201360200200328020021060b200228022421032002200620011027200241086a22062006280200220620016a360200200620022802006a20052001101e1a2003450d08200510020c080b200241106a107e2002280210200241106a41086a220628020022036a41013a00002006200341016a2203360200200241106a20034120102720062006280200220341206a2205360200200320022802106a2203200141056a290000370000200341086a2001410d6a290000370000200341106a200141156a290000370000200341186a2001411d6a290000370000200241106a20054101102720022802102205200628020022036a200141256a2d00003a00002006200341016a2203360200200241086a28020021060c010b200241106a107e2002280210200241106a41086a220528020022036a41003a00002005200341016a2203360200200241206a200141086a28020010d80120022802202108200241106a200320022802282201102720052001200528020022046a22033602002004200228021022056a20082001101e1a2002280224450d00200810020b200228021421012002200620031027200241086a22062006280200220620036a360200200620022802006a20052003101e1a2001450d05200510020c050b200241106a107e2002280210200241106a41086a22032802006a41043a00002003200328020041016a2205360200200241106a20054120102720032003280200220541206a2206360200200520022802106a220541186a200141216a290000370000200541106a200141196a290000370000200541086a200141116a2900003700002005200141096a290000370000200141306a2903002109200241106a20064108102720032003280200220541086a360200200520022802106a20093700002001412c6a2802002101200241106a20032802004104102720032003280200220541046a360200200520022802106a20013600000c030b200241106a107e2002280210200241186a22032802006a41023a00002003200328020041016a22053602002001410c6a2802002101200241106a20054104102720032003280200220541046a360200200520022802106a20013600000c020b200241106a107e2002280210200241186a22032802006a41033a00002003200328020041016a22053602002001410c6a2802002101200241106a20054104102720032003280200220541046a360200200520022802106a20013600000c010b200241106a107e2002280210200241106a41086a22032802006a41013a00002003200328020041016a22053602002001412c6a2802002106200241106a20054104102720032003280200220541046a360200200520022802106a2006360000200241106a20032802004120102720032003280200220541206a2206360200200520022802106a220541186a200141216a290000370000200541106a200141196a290000370000200541086a200141116a2900003700002005200141096a290000370000200141306a2802002105200241106a20064104102720032003280200220641046a360200200620022802106a2005360000200141346a2802002101200241106a20032802004104102720032003280200220541046a360200200520022802106a20013600000b20022802142106200228021021052002200241086a2201280200200241106a41086a2802002203102720012003200128020022086a360200200820022802006a20052003101e1a2006450d00200510020b20002002290300370200200041086a200241086a280200360200200241306a24000f0b101c000b41ec30103b000b419435103b000b41ec34103b000b41ac3f103b000b41943b103b000b41843e103b000b41ecc100103b000b08004194321054000b4b01017f02402002417f4c0d00024002402002450d002002100122030d01101c000b410121030b200320012002101e21012000200236020420002001360200200020023602080f0b102b000b05001041000ba10c03037f027e0c7f23004180016b22002400200041e0006a41086a220142003703002000420037036041c8084107200041e0006a1003200041306a41086a200129030037030020002000290360370330024002400240200041306a411041d02d410041001000417f460d002000420037036002400240200041306a4110200041e0006a41084100100041016a41084d0d002000200029036042017c370340200041e0006a41086a220242003703002000420037036041c8084107200041e0006a1003200041306a41086a2201200229030037030020002000290360370330200041306a4110200041c0006a41081004200142003703002000420037033041dd084107200041306a1003200041106a41086a2001290300370300200020002903303703100240200041106a411041d02d410041001000417f460d0020004200370360200041106a4110200041e0006a41084100100041016a41084d0d0220002903602103200041306a41086a220142003703002000420037033041dd084107200041306a1003200041e0006a41086a200129030037030020002000290330370360200041e0006a411010054201a74101470d050c040b4200a74101460d030c040b41c1214133102d000b41c1214133102d000b41f4214122102d000b102e210420002003370340200041e0006a41086a220142003703002000420037036041cf084107200041e0006a1003200041306a41086a2202200129030037030020002000290360370330200041306a4110200041c0006a4108100420002004370340200142003703002000420037036041d6084107200041e0006a10032002200129030037030020002000290360370330200041306a4110200041c0006a410810040b2000102f2000280200210502400240024020002802082201450d002001410574210620052107410021080340410810012201450d022000200136026020004208370264200041e0006a410041081027200041e0006a41086a22012001280200220241086a360200200220002802606a42f3cacdd3e38d9eba3a370000200041c0006a41086a2202200128020036020020002000290360370340412010012209450d022000200936026020004220370264200041e0006a41004120102720012001280200220a41206a2209360200200a2000280260220b6a220a2007290000370000200a41086a200741086a290000370000200a41106a200741106a290000370000200a41186a200741186a2900003700002000280264210c200041c0006a2002280200200910272000280240220a2002280200220d6a200b2009101e1a2002200d20096a220d3602000240200c450d00200b10020b2000280244210c200041306a41086a2209420037030020004200370330200a200d200041306a1003200041106a41086a220b20092903003703002000200029033037031002400240200041106a411041d02d410041001000417f460d00200041e0006a41186a220e4200370300200041e0006a41106a220f42003703002001420037030020004200370360200041106a4110200041e0006a4120410010002210417f460d052010411f4d0d05200041c0006a41186a200e290300370300200041c0006a41106a200f29030037030020022001290300370300200020002903603703402009420037030020004200370330200a200d200041306a10032001200929030037030020002000290330370360200041e0006a41101005410121090c010b410021090b200041106a41186a220d200041c0006a41186a290300370300200041106a41106a220e200041c0006a41106a290300370300200b2002290300370300200020002903403703100240200c450d00200a10020b02402009450d00200041e0006a41186a200d290300370300200041e0006a41106a200e2903003703002001200b29030037030020002000290310370360200041c0006a10302000280240220920022802001031210102402000280244450d00200910020b200120084d0d00200041c0006a20081032200028024022012002280200200041e0006a412010042000280244450d00200110020b200741206a2107200841016a2108200641606a22060d000b0b02402000280204450d00200510020b20004180016a24000f0b101c000b41c1214133102d000b080041b4321054000b9f0102027f017e230041206b22002400200041106a41086a220142003703002000420037031041d12d4107200041106a1003200041086a20012903003703002000200029031037030002402000411041d02d410041001000417f460d0020004200370310024020004110200041106a41084100100041016a41084d0d0020002903102102200041206a240020020f0b41c1214133102d000b41f4214122102d000bab0101027f230041306b22012400200141206a41086a220242003703002001420037032041e4084107200141206a1003200141086a200229030037030020012001290320370300024002402001411041d02d410041001000417f460d002001421037021420012001360210200141206a200141106a103a20012802202202450d012000200129022437020420002002360200200141306a24000f0b41f4214122102d000b41c1214133102d000bd60101047f230041206b220124000240410610012202450d002001200236021020014206370214200141106a4100410610272001280210200128021822036a220441002800c12d360000200141086a2202200341066a2203360200200441046a41002f00c52d3b0000200120012903103703002001200336021820012002280200410310272000200129030037020020022002280200220341036a2204360200200320012802006a220241002f00ee2e3b0000200041086a2004360200200241026a41002d00f02e3a0000200141206a24000f0b101c000b6001027f230041106b2202240041002103024002402000200141d02d410041001000417f460d002002410036020c200020012002410c6a41044100100041016a41044d0d01200228020c21030b200241106a240020030f0b41eb1a4133102d000bc30101047f230041206b220224000240410610012203450d002002200336021020024206370214200241106a4100410610272002280210200228021822046a220541002800c12d360000200241086a2203200441066a2204360200200541046a41002f00c52d3b00002002200229031037030020022004360218200220032802004104102720032003280200220441046a36020020002002290300370200200420022802006a2001360000200041086a2003280200360200200241206a24000f0b101c000b810301047f230041306b220224000240024002400240024002400240200128020022032001280204460d002001200341186a36020020032802082201417f4c0d06200328020021042001450d012001100122050d020c030b20004100360200200241306a24000f0b410121050b200220013602242002200536022020024100360228200241206a41002001102720022002280228220520016a360228200520022802206a20042001101e1a200241106a20022802283602002002200229032037030820032802142201417f4c0d03200328020c21032001450d012001100122040d020b101c000b410121040b200220013602242002200436022020024100360228200241206a41002001102720022002280228220420016a360228200420022802206a20032001101e1a200241146a220141086a200228022836020020012002290320370200200041106a200241086a41106a290300370200200041086a200241086a41086a29030037020020002002290308370200200241306a24000f0b1019000bd55a09017f017e017f017e067f017e177f047e027f230041f0026b220024001035102e2101200041c8026a41086a22024200370300200042003703c802418a264107200041c8026a100320004198026a41086a2002290300370300200020002903c802370398020240024002400240024002400240024002400240024002400240024020004198026a411041d02d410041001000417f460d00200042003703680240024020004198026a4110200041e8006a41084100100041016a41084d0d00200029036822034200510d0320012003824200520d0a200041f8016a103620002802f80121080240024002402000280280022209450d00200041e8006a2008280230103720002802702207450d072008200941d8006c6a2104200841d8006a2102200041f8006a35020021032000290368210a02402000280274450d00200710020b20022004460d01200a20037e2103200941d8006c41a87f6a210b41002105200041f0006a210c200041f8006a210d200041f4006a210e41012104200821060340200041e8006a200241306a2802001037200c2802002207450d052000290368200d3502007e210a0240200e280200450d00200710020b2003200a2003200a5622071b21032005200420071b21052006200220071b2106200441016a2104200241d8006a2102200b41a87f6a220b0d000b20060d022009450d00200941d8006c210420082102034020021038200241d8006a2102200441a87f6a22040d000b0b20002802fc01450d0c200810020c0c0b410021050b200920054d0d06200041e8006a2008200541d8006c6a220241d800101e1a200220082009417f6a220441d8006c6a220741d80010391a2007200041e8006a41d800101e2102200041f8016a41086a2004360200200041e8006a41086a22042002410c6a290200370300200041e8006a41106a2207200241146a290200370300200041e8006a41186a22052002411c6a290200370300200041e8006a41206a2206200241246a290200370300200041e8006a41286a220b2002412c6a280200360200200020022902043703682002280200220c4106460d07200041c0016a41086a220d2004290300370300200041c0016a41106a22042007290300370300200041c0016a41186a22072005290300370300200041c0016a41206a22052006290300370300200041c0016a41286a2206200b280200360200200020002903683703c001200241046a28022c2102200041386a41286a2006280200360200200041386a41206a2005290300370300200041386a41186a2007290300370300200041386a41106a2004290300370300200041386a41086a200d290300370300200020002903c001370338410810012204450d0b200020043602682000420837026c200041e8006a4100410810272000280268200028027022046a42e4cab5d3c3ac99b83a3700002000200441086a360270200041c0016a41086a2000280270360200200020002903683703c001410410012204450d0b200020043602682000420437026c200041e8006a41004104102720002802682207200028027022046a20023600002000200441046a2202360270200028026c2105200041c0016a20002802c8012002102720002802c001220420002802c80122066a20072002101e1a2000200620026a22023602c80102402005450d00200710020b20002802c401210620004198026a41086a2207420037030020004200370398022004200220004198026a1003200041e8006a41086a20072903003703002000200029039802370368410021070240200041e8006a411041d02d410041001000417f460d002000200041e8006a3602082000411036020c200042003703c00120004100200041e8006a4110200041c0016a41084100100022072007417f461b2207410820074108491b360210200741074d0d0620002903c0012103200041c0016a200041086a103a20002802c0012207450d06200041c0016a41086a280200210520002802c401210b20004198026a41086a220d420037030020004200370398022004200220004198026a1003200041c8026a41086a200d29030037030020002000290398023703c802200041c8026a411010052006450d0a0c090b20060d080c090b41c1214133102d000b4198264132102d000b41f4214122102d000b41c43f103b000b4198264132102d000b41c1214133102d000b41dc3f20052009103c000b41ec3f103b000b200410020b024002402007450d0002402005450d002005410574210420072102034020022003103d200241206a2102200441606a22040d000b0b200041e8006a41086a2202200041f8016a41086a280200360200200020002903f801370368200041e8006a103e20002802682105024020022802002202450d00200241d8006c210420052102034020021038200241d8006a2102200441a87f6a22040d000b0b0240200028026c450d00200510020b200041c8026a41086a22024200370300200042003703c80241f7264107200041c8026a100320004198026a41086a2002290300370300200020002903c8023703980220004198026a411041d02d410041001000417f460d0120004200370368024020004198026a4110200041e8006a41084100100041016a41084d0d0020002903682103200041f4006a200041c0006a290300370200200041fc006a200041c8006a29030037020020004184016a200041d0006a2903003702002000418c016a200041d8006a29030037020020004194016a200041e0006a2802003602002000200c3602682000200029033837026c200320017c200041e8006a4100103f200b450d03200710020c030b41c1214133102d000b41ca26412d102d000b41f4214122102d000b200020013703f801200041c8026a41086a22024200370300200042003703c80241fe264107200041c8026a100320004198026a41086a2002290300370300200020002903c80237039802024002400240024020004198026a411041d02d410041001000417f460d00200041003602680240024020004198026a4110200041e8006a41044100100041016a41044d0d0020002802682104200041c8026a41086a22024200370300200042003703c8024185274107200041c8026a100320004198026a41086a2002290300370300200020002903c8023703980220004198026a411041d02d410041001000417f460d032000410036026820004198026a4110200041e8006a41044100100041016a41044d0d012000200028026822053602cc02200041003a00d402200020043602c8022000200041f8016a3602d0020240200420054f0d002000200441016a22023602c802200041f0006a210602400340200041e8006a20041040200628020022074106470d01200220054f0d022000200241016a22073602c80220022104200721020c000b0b200041386a41086a2205200041fc006a2206290200370300200041386a41106a220b20004184016a220c290200370300200041386a41186a220d2000418c016a220e290200370300200041386a41206a220820004194016a2209290200370300200041386a41286a220f2000419c016a221028020036020020002000290274370338200041a0016a2d0000211120002903682103200041b8026a41026a221220004198026a41026a2d00003a0000200020002f0098023b01b802200041e8006a410c6a2202200029033837020020062005290300370200200c200b290300370200200e200d290300370200200920082903003702002010200f280200360200200041a7016a20122d00003a00002000200736027020002003370368200020043602a001200020113a00a401200020002f01b8023b00a5010240200320002903f801520d00200041c0016a41306a200241306a280200360200200041c0016a41286a200241286a290200370300200041c0016a41206a200241206a290200370300200041c0016a41186a200241186a290200370300200041c0016a41106a200241106a290200370300200041c0016a41086a200241086a290200370300200020022902003703c00120074106460d010c060b200041c8026a410c6a41013a0000200041e8006a41086a10384106210741064106470d050b4108211341002102410021140c050b41c1214133102d000b41c1214133102d000b41f4214122102d000b41f4214122102d000b200041e8006a41306a2202200041c0016a41306a280200360200200041e8006a41286a2204200041c0016a41286a290300370300200041e8006a41206a2205200041c0016a41206a290300370300200041e8006a41186a2206200041c0016a41186a290300370300200041e8006a41106a220b200041c0016a41106a290300370300200041e8006a41086a220c200041c0016a41086a290300370300200020002903c00137036841c00010012213450d0120132007360208201320033703002013200029036837020c201341146a200c2903003702002013411c6a200b290300370200201341246a20062903003702002013412c6a2005290300370200201341346a20042903003702002013413c6a2002280200360200200041086a41086a200041c8026a41086a290300370300200020002903c802370308024020002d00140d0020002802082202200028020c4f0d002000200241016a360208200041f0006a210402400340200041e8006a20021040200428020022074106470d0120002802082202200028020c4f0d022000200241016a3602080c000b0b200041386a41086a2205200041fc006a2206290200370300200041386a41106a220b20004184016a220c290200370300200041386a41186a220d2000418c016a220e290200370300200041386a41206a220820004194016a2209290200370300200041386a41286a220f2000419c016a221028020036020020002000290274370338200041a0016a2d0000211120002903682103200041b8026a41026a221220004198026a41026a2d00003a0000200020002f0098023b01b802200041e8006a410c6a2204200029033837020020062005290300370200200c200b290300370200200e200d290300370200200920082903003702002010200f280200360200200041a7016a20122d00003a00002000200736027020002003370368200020023602a001200020113a00a401200020002f01b8023b00a5010240024020032000280210290300520d00200041c0016a41306a200441306a280200360200200041c0016a41286a200441286a290200370300200041c0016a41206a200441206a290200370300200041c0016a41186a200441186a290200370300200041c0016a41106a200441106a290200370300200041c0016a41086a200441086a290200370300200020042902003703c0014106210b20074106470d010c020b200041086a410c6a41013a0000200041e8006a41086a1038410621074106210b41064106460d010b200041e8006a41086a2106200041a5016a2111200041e8006a410c6a210d410121144101210202400340200041e8006a41306a2205200041c0016a41306a2212280200360200200041e8006a41286a220c200041c0016a41286a221c290300370300200041e8006a41206a2209200041c0016a41206a221e290300370300200041e8006a41186a220f200041c0016a41186a221d290300370300200041e8006a41106a2210200041c0016a41106a22202903003703002006200041c0016a41086a2215290300370300200020002903c001370368024020022014470d00201441016a2204201449221b0d02200e2014410174221f20082004201b1b22082008201f491b2204ad420686220aa7200a422088a7221b1b220e4100480d02201b4100470d02024002402014450d00200e1001221b450d07201b2013200e2014200b74221f201f200e4b1b101e211b20131002201b21130c010b200e10012213450d060b200421140b20132002200b746a22042007360208200420033703002004413c6a2005280200360200200441346a200c2903003702002004412c6a2009290300370200200441246a200f2903003702002004411c6a2010290300370200200441146a20062903003702002004410c6a2000290368370200200241016a2102200041086a410c6a22092d00000d0320002802082205200028020c220c4f0d032000200541016a220436020802400340200041e8006a2005104020062802002207200b470d012004200c4f0d052000200441016a220736020820042105200721040c000b0b200041386a41086a221f200d41086a2204290200370300200041386a41106a2221200d41106a220c290200370300200041386a41186a2219200d41186a220f290200370300200041386a41206a2216200d41206a2210290200370300200041386a41286a221a200d41286a221b2802003602002000200d290200370338200041a0016a22172d000021182000290368210a200041b8026a41026a222720004198026a41026a2d00003a0000200020002f0098023b01b8022006200736020020172005360200200041e8006a413c6a20183a0000200d20002903383702002004201f290300370200200c2021290300370200200f201929030037020020102016290300370200201b201a280200360200201120002f01b8023b0000201141026a20272d00003a00002000200a3703680240200a200041086a41086a280200290300520d002012200d41306a280200360200201c201b290200370300201e2010290200370300201d200f2902003703002020200c290200370300201520042902003703002000200d2902003703c001200a21032007200b470d010c040b200941013a000020061038410621074106200b470d000c030b0b1041000b41012114410121020b201320024106746a21152002450d01200041386a41086a2116200041386a4104722110200041a7026a2117200041f8016a4104722118200041c0016a41186a2119200041c9016a211a200041c0016a41086a2107200041e8006a4104722105200041e8006a41286a211b200041e8006a41206a2112200041e8006a41106a211c2013210f0340200f22022802082111201b200241346a28020036020020122002412c6a290200370300200041e8006a41186a221d200241246a290200370300201c2002411c6a290200370300200041e8006a41086a221e200241146a29020037030020002002410c6a290200370368200241c0006a210f20114106460d0320022802382109200041086a41086a2204201e290300370300200041086a41106a2206201c290300370300200041086a41186a220b201d290300370300200041086a41206a220c2012290300370300200041086a41286a220d201b2802003602002000200029036837030820022d003c211f20102000290308370200201041086a2004290300370200201041106a2006290300370200201041186a200b290300370200201041206a200c290300370200201041286a200d28020036020020002011360238200041f8016a2009104220002802f801212002400240024002400240200041f8016a41086a22212802002202450d002002410574210d420021034200210a20202102034020021043210120021044212220052002290000370000200541086a200241086a290000370000200541106a200241106a290000370000200541186a200241186a29000037000020002009360268410810012204450d07200020043602c001200042083702c401200041c0016a41004108102720072007280200220441086a360200200420002802c0016a42e4cab5d3e3ee9bba3a370000200041c8026a41086a22042007280200360200200020002903c0013703c802200041c0016a200041e8006a104520002802c401210e20002802c001210c200041c8026a200428020020072802002206102720002802c802220b200428020022086a200c2006101e1a2004200820066a22083602000240200e450d00200c10020b20002802cc02210620044200370300200042003703c802200b2008200041c8026a100320004198026a41086a2004290300370300200020002903c8023703980202400240024020004198026a411041d02d410041001000417f470d004102210420060d010c020b200041003a00c00120004198026a4110200041c0016a41014100100041016a41014d0d0520002d00c00121042006450d010b200b10020b200441ff01714102460d02200241206a21024200202220017c2201200441017122041b200a7c210a2001420020041b20037c2103200d41606a220d0d000b20002802fc01450d040c030b4200210a4200210320002802fc010d020c030b41f90941e000102d000b41c1214133102d000b202010020b0240200041c8026a41086a22064200370300200042003703c80241f9204107200041c8026a100320004198026a41086a220b2006290300370300200020002903c802370398020240024002400240024020004198026a411041d02d410041001000417f460d0020004200370368024020004198026a4110200041e8006a41084100100041016a41084d0d0020002903682101200910460240200a20037c22224202882223500d0020232022510d004100210402400340200441026a21022022200441046a413e71ad882223500d012002210420232022520d000b0b20222002413e71ad88420052ad212302402002450d0003402023420186222320234201842223202320237e202241002002417e6a2204200420024b1b2202413f71ad88561b212320020d000b0b20014202882222500d040c030b2022420052ad21232001420288222250450d020c030b41c1214133102d000b41f4214122102d000b20222001510d004100210402400340200441026a21022001200441046a413e71ad882222500d012002210420222001520d000b0b20012002413e71ad88420052ad212202402002450d0003402022420186222220224201842222202220227e200141002002417e6a2204200420024b1b2202413f71ad88561b212220020d000b0b2023500d020c010b2001420052ad21222023500d010b02400240024002400240201f41037122024101460d0020024102470d012003200a580d050c040b2022500d01200a202280222420032023802225540d0303402023210120252024540d05200a202282212320032001822224500d052023500d042022202380212520222103202421222001210a2001202480222420255a0d000c040b0b2022500d01200a202380222420032022802225540d0203402023210120252024540d04200a200182212520032022822223500d042025500d03202220238021242022210a20012103202521222024200120258022255a0d000c030b0b419c31103b000b419c31103b000b200041c0016a41286a200041386a41286a290300370300200041c0016a41206a200041386a41206a2903003703002019200041386a41186a290300370300200041c0016a41106a220c200041386a41106a29030037030020072016290300370300200020002903383703c00102400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002802c001220e417f6a220241044b0d000240024002400240024020020e050004020301000b200728020022024101460d0720024102470d13102c0c210b200c2903002103200728020022024101460d0420024102470d132000200337036820064200370300200042003703c80241e122410a200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410810040c200b200020002902c40122033703f8012003422088a721022003a72204410371220c4101460d04200c4102470d1320021046200441ff01714101470d1f201810220c1f0b20004194026a41026a220d201a41026a2d00003a00002021201941086a290300370300200041f8016a41106a2208201941106a2903003703002000201a2f00003b019402200020192903003703f80120072d0000410771417f6a220241034b0d13200c2903002103200041c0016a410c6a2802002104024020020e04000a0709000b2000200436026820064200370300200042003703c802419b164107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410410040c1a0b2007280200410771417f6a220241034b0d13200c2903002103024020020e04000b070a000b2000200337036820064200370300200042003703c80241cf1d4107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410810040c1d0b200c2802002111200041c0016a410c6a280200211e2007280200210820002802c401410371221d4101460d03201d4102470d1302402011450d002008201141186c22046a210d2008210203402002280200200241086a2802002002410c6a280200200241146a2802001004200241186a2202200d470d000b2011450d002008210203400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200441686a22040d000b0b0240201e450d00200810020b41002104201d4101470d194100210441000d19201e450d1920081002200e41077122024103470d1a0c1b0b2000200337036820064200370300200042003703c802418d23410b200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410810040c1b0b102e210a20064200370300200042003703c80241f7264107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a411041d02d410041001000417f460d122000420037036820004198026a4110200041e8006a41084100100041016a41084d0d0b20002903682101201b200241286a2903003703002012200241206a290300370300201d200241186a290300370300201c200241106a290300370300201e200241086a290300370300200020022903003703682001200a7c200041e8006a2003420888a7103f200210020c1a0b2000200c29030037036820064200370300200042003703c80241dd084107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410810040c190b41942f4105200820111004201e450d18200810020c180b2000200337036820064200370300200042003703c80241a2164107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410810040c130b2000200041c0016a410c6a28020036026820064200370300200042003703c80241de1d4107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410410040c160b2000200337036820064200370300200042003703c80241a9164107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410810040c110b20004198026a41036a200436000020004198026a41076a2003370000201720002903f80137000020004198026a41026a200d2d00003a0000201741086a2021290300370000201741106a20082d00003a0000200020002f0194023b019802200041e8006a1047200028026c2126200028026821270240201e2802002202450d00200241286c220241b07f6a2104200241586a210d202721020340200241086a2903002103200241106a290300210a200241186a2903002101200229030021222012200241206a290300370300201d2001370300201c200a370300201e200337030020002022370368200041e8006a20004198026a412010060d04200241286a2102200441586a2104200d41586a220d4158470d000b0b41002102410821112026450d03202710024100210d0c0f0b1048102c0c130b2000200337036820064200370300200042003703c80241d21e4107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410810040c120b200041c8026a41206a22202012290300370300200041c8026a41186a221f201d290300370300200041c8026a41106a2221201c2903003703002006201e290300370300200020002903683703c802412810012211450d15201120002903c802370300201141206a2020290300370300201141186a201f290300370300201141106a2021290300370300201141086a2006290300370300200020113602b80220004281808080103702bc02200d450d01200241286a21024101210d03402012200241206a290300370300201d200241186a290300370300201c200241106a290300370300201e200241086a290300370300200020022903003703680240200041e8006a20004198026a41201006450d0020202012290300370300201f201d2903003703002021201c2903003703002006201e290300370300200020002903683703c80220122020290300370300201d201f290300370300201c2021290300370300201e2006290300370300200020002903c8023703680240200d20002802bc02470d00200041b8026a200d4101104920002802b80221110b2011200d41286c6a22082000290368370300200841206a2012290300370300200841186a201d290300370300200841106a201c290300370300200841086a201e290300370300200041b8026a41086a200d41016a220d3602000b02402004450d00200241286a2102200441586a21040c010b0b2026450d0b0c0a0b4100210d0c0b0b4101210d20260d080c090b41c1214133102d000b418431103b000b419c3e103b000b419cc000103b000b41ac35103b000b41f43b103b000b419cc200103b000b41f4214122102d000b202710020b20002802bc0221020b201e200d3602002000200236026c20002011360268200041e8006a104a2002450d00201110020b410121040b200e41077122024103460d010b20020d012004450d0120002802c4012202450d01024020024101470d00200041c0016a410c6a280200450d02200728020010020c020b2007280200210d0240200c2802002202450d00200241186c2104200d210203400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200441686a22040d000b0b200041c0016a410c6a280200450d01200d10020c010b41000d0020002d00c40141ff01714101470d002007104b0b2000200941016a36026820064200370300200042003703c80241fe264107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a41041004200f2015470d020c010b2000200941016a36026820064200370300200042003703c80241fe264107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a41041004024002400240201141077122024103460d0020020d02200028023c2202450d0220024101470d01200041386a410c6a280200450d0220162802001002200f2015470d040c030b20002d003c4101470d0120161022200f2015470d030c020b201628020021060240200041386a41106a2802002202450d00200241186c21042006210203400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200441686a22040d000b0b200041386a410c6a280200450d00200610020b200f2015470d010b0b2015220f2015460d040c030b101c000b2013210f0b200f2015460d010b200041e8006a41086a211c200041e8006a410c6a2102200041e8006a41306a2105200041e8006a41286a2106200041e8006a41206a210b200041e8006a41186a210c200041e8006a41106a210d0340200f41086a2802002104200f29030021032005200f413c6a2802003602002006200f41346a290200370300200b200f412c6a290200370300200c200f41246a290200370300200d200f411c6a290200370300200041e8006a41086a2207200f41146a2902003703002000200f410c6a29020037036820044106460d01200041c0016a41306a220e2005280200360200200041c0016a41286a22082006290300370300200041c0016a41206a2209200b290300370300200041c0016a41186a2210200c290300370300200041c0016a41106a2211200d290300370300200041c0016a41086a22122007290300370300200020002903683703c00120072004360200200220002903c001370200200241086a2012290300370200200241106a2011290300370200200241186a2010290300370200200241206a2009290300370200200241286a2008290300370200200241306a200e28020036020020002003370368201c1038200f41c0006a220f2015470d000b0b02402014450d00201310020b102e2101200041e8006a41086a220242003703002000420037036841ba1d4107200041e8006a1003200041c8026a41086a22042002290300370300200020002903683703c802420021030240024002400240024002400240024002400240200041c8026a411041d02d410041001000417f460d0020004200370368200041c8026a4110200041e8006a41084100100041016a41084d0d01200029036821030b200242003703002000420037036841c11d4107200041e8006a100320042002290300370300200020002903683703c802200041c8026a411041d02d410041001000417f460d0320004200370368024002400240200041c8026a4110200041e8006a41084100100041016a41084d0d002000290368210a200041e8006a41086a220242003703002000420037036841cf084107200041e8006a1003200041c8026a41086a2002290300370300200020002903683703c802200041c8026a411041d02d410041001000417f460d0720004200370368200041c8026a4110200041e8006a41084100100041016a41084d0d012000290368200a7e22224200510d084200210a0240200120037d2022824200520d0010480b102e2103200041e8006a41086a220242003703002000420037036841d6084107200041e8006a1003200041c8026a41086a22042002290300370300200020002903683703c80202400240200041c8026a411041d02d410041001000417f460d0020004200370368200041c8026a4110200041e8006a41084100100041016a41084d0d06200029036821014201210a0c010b0b200242003703002000420037036841cf084107200041e8006a100320042002290300370300200020002903683703c802200041c8026a411041d02d410041001000417f460d0920004200370368200041c8026a4110200041e8006a41084100100041016a41084d0d02200029036822224200510d0a0240200342002001200a501b7d2022824200520d00102c0b200041c8026a41086a22024200370300200042003703c80241ad0b4107200041c8026a100320004198026a41086a2002290300370300200020002903c8023703980220004198026a411041d02d410041001000417f460d05200041003a006820004198026a4110200041e8006a41014100100041016a41014d0d0b20002d00682102200041c8026a41086a22044200370300200042003703c80241ad0b4107200041c8026a1003200041e8006a41086a2004290300370300200020002903c802370368200041e8006a411010052002450d05200041f0026a24000f0b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c432103b000b41f4214122102d000b41f4214122102d000b41ac3b103b000b41f4214122102d000b41b431103b000b41c1214133102d000bdd91010b017f017e017f017e057f017e047f017e187f027e027f230041f0026b22002400102e2101200041286a41086a220242003703002000420037032841b0164107200041286a1003200041086a41086a200229030037030020002000290328370308024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200041086a411041d02d410041001000417f460d00200042003703900202400240200041086a411020004190026a41084100100041016a41084d0d0020002903900222034200510d0320012003824200520d1d200041286a41086a2202420037030020004200370328419b164107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411041d02d410041001000417f460d052000410036029002200041086a411020004190026a41044100100041016a41044d0d012000280290022202450d1d200041e0016a1047200041286a41086a220442003703002000420037032841b00f4107200041286a1003200041086a41086a200429030037030020002000290328370308410021040240200041086a411041d02d410041001000417f460d002000200041086a360290012000411036029401200042003703900220004100200041086a411020004190026a41084100100022042004417f461b2204410820044108491b220d36029801200441074d0d05200029039002210e200041003602900220004198016a4100200041086a411020004190026a4104200d100022042004417f461b2204410420044104491b200d6a360200200441034d0d05200028029002210420004190026a20004190016a103a200028029002220f450d0520002802e801220d20046a2000290294022203422088a76b211002402003a7450d00200f10020b20102002490d080c070b102e210e20002802e801220d20024f0d060c070b41c1214133102d000b41c1214133102d000b41f4214122102d000b41ac39103b000b41c1214133102d000b41f4214122102d000b0240200420024f0d00200d200420026b6a2202200d4f0d0820002802e001200241286c6a290320210e0c010b200041286a41086a220242003703002000420037032841a9164107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411041d02d410041001000417f460d082000420037039002200041086a411020004190026a41084100100041016a41084d0d01200029039002200e7c210e0b200041286a41086a220242003703002000420037032841b0164107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411041d02d410041001000417f460d03200042003703900202400240200041086a411020004190026a41084100100041016a41084d0d0020002903900222034200510d06200e20037c427f7c220e200e2003827d2103024020002802e401450d0020002802e00110020b20032001520d17200041e8006a1047200041286a41086a2202420037030020004200370328419b164107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411041d02d410041001000417f460d072000410036029002200041086a411020004190026a41044100100041016a41044d0d012000280290022115102e21030240024020002802702214450d002000280268220241206a2903002003520d0020004190026a41186a2204200241186a29000037030020004190026a41106a220d200241106a29000037030020004190026a41086a2210200241086a290000370300200020022900003703900241201001220f450d12200241286a2102200f200029039002370000200f41186a2004290300370000200f41106a200d290300370000200f41086a20102903003700002000200f3602e00120004281808080103702e401412021104101210d0240201441286c41586a2211450d000340200241206a2903002003520d01200041c8006a41186a200241186a2204290000370300200041c8006a41106a200241106a2216290000370300200041c8006a41086a200241086a22172900003703002000200229000037034820004190016a41186a2218200429000037030020004190016a41106a2219201629000037030020004190016a41086a2216201729000037030020002002290000370390010240200d20002802e401470d00200041e0016a200d410110860120002802e001210f0b200241286a2102200f20106a2204200029039001370000200441186a2018290300370000200441106a2019290300370000200441086a2016290300370000200041e0016a41086a200d41016a220d360200201041206a2110201141586a22110d000b0b20002802e40121022014200d6b2015490d010c160b410021024101210f4100210d201441006b20154f0d150b200041286a41086a220442003703002000420037032841a2164107200041286a1003200041086a41086a200429030037030020002000290328370308200041086a411041d02d410041001000417f460d0a2000420037039002200041086a411020004190026a41084100100041016a41084d0d03200029039002210e20004190026a41106a2002360200200041a4026a200d3602002000200d20146b20156a2219360298022000200e20037c2203370390022000200f36029c02200041003602e801200042013703e001200041e0016a41004108102720002802e00120002802e80122046a20033700002000200441086a22043602e801200041e0016a20044104102720002802e00120002802e80122046a20193600002000200441046a22103602e80120004190016a2000419c026a10a201200028029001210d200041e0016a2010200028029801220410272000200420002802e80122116a22163602e801201120002802e00122106a200d2004101e1a0240200028029401450d00200d10020b200041286a41086a220442003703002000420037032841b00f4107200041286a1003200041086a41086a200429030037030020002000290328370308200041086a4110201020161004024020002802e401450d00201010020b02402002450d00200f10020b41082118200041286a41086a220242003703002000420037032841c50f4107200041286a1003200041086a41086a200229030037030020002000290328370308410021140240024002400240200041086a411041d02d410041001000417f460d0020004210370294012000200041086a3602900120004190026a20004190016a103a2000280290022215450d1341082118200028029402211b20004190026a41086a2802002202450d0120024105744105752214ad4203862203a722044100480d122003422088a74100470d12200410012218450d152002410574220d41606a410576211020182104201521020340200420021043200210447c370300200441086a2104200241206a2102200d41606a220d0d000b201041016a21020c030b410121154100211b0c010b410021140b410021020b2000410036029802200042013703900220004190026a41004104102720002802900220002802980222046a20023600002000200441046a3602980220004190016a41086a2204200028029802360200200020002903900237039001024002402002450d002002410374210f2018210d0340200d2903002103410810012202450d152000200236029002200042083702940220004190026a41004108102720004190026a41086a22022002280200221141086a2202360200201120002802900222106a2003370000200028029402211120004190016a2004280200200210272000280290012217200428020022166a20102002101e1a2004201620026a220236020002402011450d00201010020b200d41086a210d200f41786a220f0d000c020b0b200028029801210220002802900121170b2000280294012104200041286a41086a220d4200370300200042003703284181114107200041286a1003200041086a41086a200d29030037030020002000290328370308200041086a411020172002100402402004450d00201710020b02402014450d00201810020b200041286a41086a220242003703002000420037032841b7164107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411041d02d410041001000417f460d0b2000410036029002200041086a411020004190026a41044100100041016a41044d0d042000280290022102200041a8016a4200370300200041a0016a420037030020004198016a42003703002000420037039001200220196a220dad42287e2203422088a70d0c2003a72202417f4c0d0d4108210402402002450d00200210012204450d140b2000200d3602e401200020043602e001200041003602e80120004190026a41186a221020004190016a41186a29030037030020004190026a41106a220f20004190016a41106a29030037030020004190026a41086a20004190016a41086a290300370300200020002903900137039002200041e0016a200d10850120002802e00120002802e801221141286c6a2102024002400240200d4102490d0041012104034020024200370300200241206a2010290300370300200241186a200f290300370300200241106a20004190026a41086a290300370300200241086a200029039002370300200241286a2102200441016a2204200d490d000b201120046a417f6a21110c010b200d450d010b200220002903900237030820024200370300200241106a20004198026a290300370300200241186a20004190026a41106a290300370300200241206a20004190026a41186a290300370300201141016a21110b200041e0016a41086a2202201136020020004190026a41086a2002280200360200200020002903e0013703900220004190026a10b7010240200028029402450d0020002802900210020b201b450d15201510020c150b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41f4214122102d000b41c439103b000b41f4214122102d000b41cc362002200d103c000b41f4214122102d000b41f4214122102d000b41f4214122102d000b105e000b105f000b1041000b41c1214133102d000b41d900212a0c070b41d900212a0c060b41d900212a0c050b41d900212a0c040b2002450d00200f1002200028026c0d010c020b200028026c450d010b200028026810020b200041286a41086a220242003703002000420037032841b00f4107200041286a1003200041086a41086a20022903003703002000200029032837030802400240200041086a411041d02d410041001000417f460d002000200041086a360290012000411036029401200042003703900220004100200041086a411020004190026a41084100100022022002417f461b2202410820024108491b220436029801200241074d0d0b2000290390022103200041003602900220004198016a4100200041086a411020004190026a41042004100022022002417f461b22024104200241044922021b20046a36020020020d0b20004190026a20004190016a103a2000280290022205450d0b200028029402210620032001520d01200041286a41086a22024200370300200042003703284181114107200041286a1003200041086a41086a2204200229030037030020002000290328370308200041086a41101005200442003703002000420037030841b00f4107200041086a10032002200429030037030020002000290308370328200041286a411041d02d410041001000417f460d082000200041286a360290012000411036029401200042003703900220004100200041286a411020004190026a41084100100022022002417f461b22024108200241084922041b22023602980120040d09200041003602900220004198016a4100200041286a411020004190026a41042002100022042004417f461b2204410420044104491b20026a360200200441034d0d09200028029002210720004190026a20004190016a103a2000280290022208450d0920002902940221094108210a200041086a41086a220242003703002000420037030841b00f4107200041086a1003200041286a41086a2204200229030037030020002000290308370328200041286a411010052002420037030020004200370308418f114107200041086a100320042002290300370300200020002903083703284100210b02400240200041286a411041d02d410041001000417f460d0020004210370294012000200041286a3602900120004190026a20004190016a10b601200028029002220a450d052000290294022103200041086a41086a2202420037030020004200370308418f114107200041086a1003200041286a41086a200229030037030020002000290308370328200041286a411010052003422088a7210b2003a7210c0c010b4100210c0b102e2103200041286a41086a220242003703002000420037032841a9164107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411041d02d410041001000417f460d072000420037039002200041086a411020004190026a41084100100041016a41084d0d0d200020002903900220037c3703e002200041286a41086a220242003703002000420037032841c6104107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411041d02d410041001000417f460d062000420037039002200041086a411020004190026a41084100100041016a41084d0d0c2009422088a72111200a200b41286c22026a210f02402007450d0020002903900221034100200a6b20026b21042007210d200f210203402002200a460d01200241586a22102903004200510d01200241606a2003103d200441286a210420102102200d417f6a220d0d000b0b20004190026a104720002802980221042000280290022102200028029402210d200041f8016a200f360200200041fc016a41003a000020004180026a20073602002000200d3602e401200020023602e001200020023602e80120002002200441286c6a3602ec01200020113602f0012000200a3602f40120004184026a200041e0026a360200200041003a00880220004190026a200041e0016a10b90102400240024002400240024002400240024002400240024002400240024002400240024002400240024002402000290390024200510d00417f4100200041ec016a280200200041e0016a41086a2802006b41286d2202200041f0016a2802006b2204200420024b1b220241016a220420042002491b2204ad42287e2203422088a70d1b2003a72202417f4c0d1a4108211202402002450d00200210012212450d160b201220004190026a41086a2202290300370300201241206a200241206a290300370300201241186a200241186a290300370300201241106a200241106a290300370300201241086a200241086a290300370300200020123602482000200436024c410121132000410136025020004190016a41286a200041e0016a41286a28020036020020004190016a41206a200041e0016a41206a29030037030020004190016a41186a200041e0016a41186a29030037030020004190016a41106a2214200041e0016a41106a29030037030020004190016a41086a200041e0016a41086a290300370300200020002903e0013703900120004190026a20004190016a10b90102402000290390024201520d0020004190026a41086a21022000419c016a2115412821104101210d0340200041e8006a41206a220f200241206a290300370300200041e8006a41186a2211200241186a290300370300200041e8006a41106a2216200241106a290300370300200041e8006a41086a2217200241086a290300370300200020022903003703680240200d2004470d00200041c8006a2004417f4100201528020020004190016a41086a2802006b41286d221820142802006b2219201920184b1b221841016a221920192018491b1049200028024821120b0240201220106a22042000290368370300200441206a200f290300370300200441186a2011290300370300200441106a2016290300370300200441086a2017290300370300200041c8006a41086a200d41016a220f36020020004190026a20004190016a10b9012000290390024201520d00201041286a2110200028024c2104200f210d0c010b0b200d41016a21130b024020004198016a220428020022022000419c016a280200220d460d0020042002200d20026b41586a41286e41286c6a41286a3602000b0240200028029401450d0020002802900110020b200028024c211a201341144b0d01201341014d0d022013417f6a210f2012201341286c6a41586a211103402013200f2202417f6a220f490d2102402013200f6b220d4102490d002012200241286c6a221041206a22042903002012200f41286c6a220241206a221629030022035a0d0020004190026a41186a2217200241186a221829030037030020004190026a41106a2219200241106a221429030037030020004190026a41086a2215200241086a221b290300370300200020022903003703900220022010290300370300201b201041086a2903003703002014201041106a2903003703002018201041186a290300370300201620042903003703000240200d4103490d00410221042011210203402004200d4f0d290240200241c8006a221029030020035a0d002004417f6a200d4f0d29200241206a2010290300370300200241186a200241c0006a290300370300200241106a200241386a290300370300200241086a200241306a2903003703002002200241286a221029030037030020102102200441016a2204200d490d010c020b0b200221100b2010200029039002370300201041186a2017290300370300201041106a2019290300370300201041086a2015290300370300201020033703200b201141586a2111200f0d000c030b0b0240200041e8016a22042802002202200041ec016a280200220d460d0020042002200d20026b41586a41286e41286c6a41286a3602000b024020002802e401450d0020002802e00110020b4100211a41082112410021130c010b2013410176221cad42287e2203422088a70d192003a72202417f4c0d184108211d02402002450d0020021001221d450d130b4100210420004100360298012000420437039001201241586a211e201241a87f6a211f4104210d20004190016a41086a21202013212103402021211641002121410121100240024002402016417f6a2202450d0002400240024002400240024002402012200241286c6a41206a29030020122016417e6a221041286c6a41206a29030022035a0d00410021112010450d02201f201641286c6a2102034020032002290300220e5a0d02200241586a2102200e21032010417f6a22100d000c030b0b02402010450d00201f201641286c6a210241022110034020032002290300220e540d04200241586a2102200e21032016201041016a2210470d000b41002121201621102004200028029401470d090c080b41022110410021212004200028029401470d080c070b201021110b024020162011490d00201620134b0d140240201620116b22104101762217450d00201e201641286c6a21022012201141286c6a210f034020004190026a41206a2218200f41206a221929030037030020004190026a41186a2214200f41186a221529030037030020004190026a41106a221b200f41106a222129030037030020004190026a41086a2222200f41086a22232903003703002000200f29030037039002200241086a22242903002103200241106a2225290300210e200241186a22262903002127200229030021282019200241206a2229290300370300201520273703002021200e37030020232003370300200f202837030020292018290300370300202620142903003703002025201b290300370300202420222903003703002002200029039002370300200241586a2102200f41286a210f2017417f6a22170d000b0b2011450d030c020b201120161055000b201620106b2211450d010b201041094d0d010b201121212004200028029401470d030c020b201620134b0d0d2012201141286c6a2117034020162011417f6a2221490d0f0240201620216b22104102490d002012201141286c6a221141206a220f2903002012202141286c6a220241206a221829030022035a0d0020004190026a41186a2219200241186a221429030037030020004190026a41106a2215200241106a221b29030037030020004190026a41086a2222200241086a22232903003703002000200229030037039002200220112903003703002023201141086a290300370300201b201141106a2903003703002014201141186a2903003703002018200f290300370300024020104103490d004102210f201721020340200f20104f0d090240200241c8006a221129030020035a0d00200f417f6a20104f0d0b200241206a2011290300370300200241186a200241c0006a290300370300200241106a200241386a290300370300200241086a200241306a2903003703002002200241286a221129030037030020112102200f41016a220f2010490d010c020b0b200221110b2011200029039002370300201141186a2019290300370300201141106a2015290300370300201141086a2022290300370300201120033703200b2021450d01201741586a2117202121112010410a490d000b0b2004200028029401470d010b20004190016a107a20202802002104200028029001210d0b200d20044103746a22022010360204200220213602002020200441016a2204360200024020044102490d00200028029001210d03400240024002400240200d2004417f6a4103746a2202280200450d00200d20044103746a221141746a280200220f200228020422104d0d00200441024d0d05200d2004417d6a22144103746a28020422022010200f6a4d0d01200441034d0d05201141646a2802002002200f6a4d0d010c050b20044103490d0120022802042110200d2004417d6a22144103746a28020421020b20022010490d010b2004417e6a21140b2004201441016a22154d0d06200420144d0d07200d201441037422226a2202280204222320022802006a2202200d201541037422246a2204280200221b490d08200220134b0d092012201b41286c6a22182004280204221941286c22046a210f200241286c210d024002400240024002402002201b6b221120196b220220194f0d00201d200f200241286c2204101e221120046a211020194101480d0120024101480d01201e200d6a210d200f21020340200d200241586a2216201041586a2217201041786a290300200241786a29030054220f1b2204290300370300200d41206a200441206a290300370300200d41186a200441186a290300370300200d41106a200441106a290300370300200d41086a200441086a29030037030020102017200f1b2110201820162002200f1b22024f0d04200d41586a210d2011210420112010490d000c050b0b201d20182004101e220220046a211020194101480d01201120194c0d012012200d6a2116200221042018210203402002200f2004200f41206a290300200441206a2903005422111b220d290300370300200241206a200d41206a290300370300200241186a200d41186a290300370300200241106a200d41106a290300370300200241086a200d41086a2903003703002004200441286a20111b2104200241286a2102200f41286a200f20111b220f20164f0d04201020044b0d000c040b0b200f21020c010b201821020b201d21040b20022004201020046b220d200d4128706b101e1a2020280200220220144d0d0a200028029001220d20226a2204202320196a3602042004201b360200200220154d0d0b200d20246a2204200441086a200220156b41037441786a10391a20202002417f6a2204360200200441014b0d000b0b20210d000b0240200028029401450d0020002802900110020b201c450d00201d10020b2000201a360294022000201236029002200020133602980220004190026a104a0240201a450d00201210020b200041286a41086a2202420037030020004200370328418d104107200041286a1003200041086a41086a2002290300370300200020002903283703084100211102400240200041086a411041d02d410041001000417f460d0020004210370294012000200041086a3602900120004190026a20004190016a103a2000280290022217450d0f20004198026a2802002111200028029402211e0c010b410121174100211e0b200041a8026a4200370300200041a0026a420037030020004198026a420037030020004200370390022011ad2203421b88a70d0b2003420586a72202417f4c0d0c024002402002450d002002100122020d010c120b410121020b200020113602940120002002360290012000410036029801200041c8006a41186a220d20004190026a41186a290300370300200041c8006a41106a220f20004190026a41106a290300370300200041c8006a41086a221620004190026a41086a290300370300200020002903900237034820004190016a41002011108601200028029001221020002802980122244105746a210202400240024020114102490d0041012104034020022000290348370000200241186a200d290300370000200241106a200f290300370000200241086a2016290300370000200241206a2102200441016a22042011490d000b202420046a417f6a21240c010b2011450d010b20022000290348370000200241186a200041c8006a41186a290300370000200241106a200041c8006a41106a290300370000200241086a200041c8006a41086a290300370000202441016a21240b2009a7211f20004190016a41086a22232024360200200a200b41286c6a2118200028029401212941002113410021164100212620070d0f0c0e0b41ccc100200f2010103c000b41dcc100200f417f6a2010103c000b41acc10020152004103c000b41acc10020142004103c000b201b20021055000b200220131029000b41bcc10020142002103c000b41b4c300103b000b20162011417f6a22214f0d010b202120161055000b201620131029000b1066000b1067000b41c1214133102d000b419201212a0c060b4106212a0c050b41d900212a0c040b41d900212a0c030b41d900212a0c020b4128212a0c010b4126212a0b0340024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240202a0e9601080d94010e95010f101112131415161718191a1b1c1d1e292a2b2c88012f3031323334353638393a3b3c3d3e404155565758595b5c5d5e5f8e0160616263646566676c757677787e7f8001810182018301840185018601797a7c7d6d6e6f707172733f748d0168696a6b5a7b87014243900144454748494a4b4c4d4e4f515253549101920150468f019301372d2e1f2021890122238a0124258b0126278c01280001020405060703090a0b0c0c0b2018200a460d9f01418b01212a0c8a020b201841586a2202290300210320004190026a41186a2204201841786a221929030037030020004190026a41106a220d201841706a221429030037030020004190026a41086a220f201841686a22152903003703002000201841606a22182903003703900220004190016a41186a221d201929030037030020004190016a41106a22252014290300370300202320152903003703002000201829030037039001200041c8006a41186a22182004290300370300200041c8006a41106a2219200d290300370300200041c8006a41086a2214200f290300370300200020002903900237034820034200510d9f01418c01212a0c89020b200041e0016a41186a22152018290300370300200041e0016a41106a221b2019290300370300200041e0016a41086a22212014290300370300200020002903483703e0010c87020b2007417f6a210720152018290300370300201b201929030037030020212014290300370300200020002903483703e0014100211620222102418d01212a0c87020b200041e8006a41186a22122015290300370300200041e8006a41106a2220201b290300370300200041e8006a41086a22222021290300370300200020002903e00137036820042012290300370300200d2020290300370300200f202229030037030020002000290368370390022007450d9301418e01212a0c86020b201641ff01710d9901418f01212a0c85020b200a2002460d9b01419001212a0c84020b200241586a222229030021032004200241786a2216290300370300200d200241706a2212290300370300200f200241686a22202903003703002000200241606a220229030037039002201d201629030037030020252012290300370300202320202903003703002000200229030037039001201820042903003703002019200d2903003703002014200f290300370300200020002903900237034820034200520d9c010c9b010b200041286a41186a2004290300370300200041286a41106a200d290300370300200041286a41086a200f29030037030020002000290390023703280c8e010b201341ff01710d9101419301212a0c81020b2018200a460d9101419401212a0c80020b201841586a22022903002103200041e0016a41186a2204201841786a220d290300370300200041e0016a41106a220f201841706a2216290300370300200041e0016a41086a2219201841686a22142903003703002000201841606a22182903003703e00120004190016a41186a200d29030037030020004190016a41106a201629030037030020232014290300370300200020182903003703900120004190026a41186a220d200429030037030020004190026a41106a2204200f29030037030020004190026a41086a220f2019290300370300200020002903e001370390022003500d9101419501212a0cff010b200041286a41186a200d290300370300200041286a41106a2004290300370300200041286a41086a200f290300370300200020002903900237032841002113410021164101212a0cfe010b20004190026a41186a2204200041286a41186a29030037030020004190026a41106a220d200041286a41106a29030037030020004190026a41086a220f200041286a41086a2903003703002000200029032837039002200041e0016a20004190026a10b50120002802e0014101470d8b014103212a0cfd010b200041e0016a41086a280200211820004190016a41186a2219200429030037030020004190016a41106a2214200d2903003703002023200f290300370300200020002903900237039001200041086a41186a22152019290300370300200041086a41106a22192014290300370300200041086a41086a22142023290300370300200020002903900137030820042015290300370300200d2019290300370300200f20142903003703002000200029030837039002202420184d0d8b014105212a0cfc010b201020184105746a2218200029039002370000201841186a2004290300370000201841106a200d290300370000201841086a200f290300370000202641016a212641002107200221184100450d86014106212a0cfb010b4100450d8d014107212a0cfa010b200c450d93014108212a0cf9010b200a10024109212a0cf8010b20244105742221410575221b201141057441057522022002201b4b1b2218450d9201410a212a0cf7010b20172102201021044100210d410b212a0cf6010b20102017460d9201410c212a0cf5010b2002200441201006450d9201410d212a0cf4010b41071001220f450d9201410e212a0cf3010b2000200f36029002200042073702940220004190026a41004107102720004190026a41086a220f200f280200221141076a221936020020112000280290026a221641002800bf1036000020004190016a41086a22112019360200201641046a41002f00c3103b0000201641066a41002d00c5103a0000200020002903900237039001412010012216450d9201410f212a0cf2010b2000201636029002200042203702940220004190026a410041201027200f200f280200221941206a22163602002019200028029002220f6a20024120101e1a200028029402211420004190016a2011280200201610272000280290012219201128020022156a200f2016101e1a2011201520166a22163602002014450d92014110212a0cf1010b200f10024111212a0cf0010b200028029401210f200041286a41086a221142003703002000420037032820192016200041286a1003200041086a41086a201129030037030020002000290328370308200041086a41101005200f450d91014112212a0cef010b201910024113212a0cee010b200241206a2102200441206a2104200d41016a220d2018490d89014114212a0ced010b201020216a21022024210d201b4104490d8f0141fc00212a0cec010b20004190026a41206a2118200041d0026a2119200041f0026a211420004190036a2115200041a8026a210f200041a0026a211120004198026a21162024210d41fd00212a0ceb010b200f420037030020114200370300201642003703002000420037039002201820022204460de10141fe00212a0cea010b200441606a20004190026a412010060de101418001212a0ce9010b200f42003703002011420037030020164200370300200042003703900220192004460de101418101212a0ce8010b200441406a20004190026a412010060de101418301212a0ce7010b200f42003703002011420037030020164200370300200042003703900220142004460de101418401212a0ce6010b200441a07f6a20004190026a412010060de101418601212a0ce5010b200f420037030020114200370300201642003703002000420037039002200441807f6a210220152004460de101418701212a0ce4010b200220004190026a412010060de101418901212a0ce3010b200d417c6a210d200220106b41057541034b0d86014115212a0ce2010b20102002460d86014116212a0ce1010b20004190026a41206a2104200041a8026a210f200041a0026a211120004198026a21164117212a0ce0010b200f42003703002011420037030020164200370300200042003703900220042002460d86014118212a0cdf010b200241606a20004190026a412010060d860141fa00212a0cde010b200d417f6a210d2010200241606a2202470d830141fb00212a0cdd010b4100450d8f01411a212a0cdc010b200d41016a22022024202420024b1b2124411b212a0cdb010b20002029360294012000201036029001200020243602980120004190026a20004190016a10a20120002802980221042000280290022102200041286a41086a220d420037030020004200370328418d104107200041286a1003200041086a41086a200d29030037030020002000290328370308200041086a4110200220041004200028029402450d8e01411c212a0cda010b20021002411d212a0cd9010b2029450d8d01411e212a0cd8010b20101002411f212a0cd7010b2000202636029002200041286a41086a220242003703002000420037032841cd104107200041286a1003200041086a41086a2204200229030037030020002000290328370308200041086a411020004190026a41041004200242003703002000420037032841b70f4107200041286a10032004200229030037030020002000290328370308200041086a411041d02d410041001000417f460d8c014120212a0cd6010b2000410036029002200041086a411020004190026a41044100100041016a41044d0d8c014121212a0cd5010b20002802900241016a21020c8c010b410121024122212a0cd3010b2000200236029002200041286a41086a220242003703002000420037032841b70f4107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411020004190026a41041004201e450d8b014123212a0cd2010b201710024124212a0cd1010b201f450d8a014125212a0cd0010b200810024126212a0ccf010b2006450d89014127212a0cce010b200510024128212a0ccd010b20004190026a412c6a212520004190026a410472212620004190026a41206a210d20004190016a412c6a2122200041e0016a41086a2123200041e0016a4104722120200041e0016a410c6a21290c88010b20004190026a41286a200041e0016a41286a290300370300200d200041e0016a41206a29030037030020004190026a41186a200041e0016a41186a29030037030020004190026a41106a200041e0016a41106a29030037030020042023290300370300200020002903e0013703900220004190026a410210ba014129212a0ccb010b200041e0026a10bb0120002802e002210241062112200041e0026a41086a2210280200220f450d9001412a212a0cca010b20022903002103200041c8006a41186a2211200241206a290000370300200041c8006a41106a2216200241186a290000370300200041c8006a41086a2217200241106a290000370300200020022900083703484106211220032001520d900141e100212a0cc9010b200f417f6a2218ad42287e2203422088a70db50141e200212a0cc8010b2003a72204417f4c0db50141e400212a0cc7010b2004450db50141e500212a0cc6010b2004100122190daf010cae010b4108211941e600212a0cc4010b20004190026a41086a220441003602002000201836029402200020193602900220004190026a4100200f41286c41586a41286e220f108201200420042802002218200f6a360200200028029002201841286c6a200241286a200f41286c101e1a2023200428020036020020002000290390023703e001200041e0016a10bc0120002802e401450db30141e700212a0cc3010b20002802e001100241e800212a0cc2010b200041e8006a41186a22142011290300370300200041e8006a41106a22152016290300370300200041e8006a41086a221b20172903003703002000200029034837036841071001220f450dac0141e900212a0cc1010b2000200f36029002200042073702940220004190026a41004107102720042004280200220f41076a2218360200200f2000280290026a220f41002800eb2236000020232018360200200f41046a41002f00ef223b0000200f41066a41002d00f1223a000020002000290390023703e00141201001220f450dac0141ea00212a0cc0010b2000200f36029002200042203702940220004190026a41004120102720042004280200221841206a220f360200201820002802900222196a22182000290368370000201841086a201b290300370000201841106a2015290300370000201841186a20142903003700002000280294022115200041e0016a2023280200200f102720002802e0012218202328020022146a2019200f101e1a20232014200f6a22143602002015450db00141eb00212a0cbf010b2019100241ec00212a0cbe010b20002802e401211d200041086a41086a220f42003703002000420037030820182014200041086a1003200041286a41086a2219200f29030037030020002000290308370328200041286a411041d02d410041001000417f460daf0141ed00212a0cbd010b2000421037020c2000200041286a36020820004190026a200041086a10bd0120002802900222124106460daf0141ee00212a0cbc010b200041e0016a41286a202641286a280200360200200041e0016a41206a202641206a290200370300200041e0016a41186a202641186a290200370300200041e0016a41106a202641106a2902003703002023202641086a290200370300200020262902003703e001200f42003703002000420037030820182014200041086a10032019200f29030037030020002000290308370328200041286a411010050caf010b4106211241ef00212a0cba010b20004190026a41286a220f200041e0016a41286a2219280200360200200d200041e0016a41206a221429030037030020004190026a41186a2215200041e0016a41186a221b29030037030020004190026a41106a2221200041e0016a41106a222429030037030020042023290300370300200020002903e00137039002201d450dae0141f000212a0cb9010b2018100241f100212a0cb8010b20124106460dad0141f200212a0cb7010b2019200f2802003602002014200d290300370300201b2015290300370300202420212903003703002023200429030037030020002000290390023703e001200f2019280200360200200d20142903003703002015201b290300370300202120242903003703002004202329030037030020252000290348370200202541086a2017290300370200202541106a2016290300370200202541186a2011290300370200200020002903e0013703900220004190016a20004190026a41cc00101e1a412b212a0cb6010b20002802e402450d7d412c212a0cb5010b20021002412d212a0cb4010b20124106460d7c412e212a0cb3010b2020200029029001370200202041086a20004190016a41086a290200370200202041106a20004190016a41106a290200370200202041186a20004190016a41186a290200370200202041206a20004190016a41206a290200370200202041286a20004190016a41286a280200360200200020123602e001200041e8006a41186a2215202241186a290000370300200041e8006a41106a221b202241106a290000370300200041e8006a41086a2221202241086a29000037030020002022290000370368200041e0026a104720002802e00221242010280200221d41286c2217450d7c412f212a0cb2010b4100211441002119202421020c7c0b4102211120180d82010c81010b200d200229000037000020004190026a41186a201529030037030020004190026a41106a201b29030037030020004190026a41086a2021290300370300200d41086a200241086a290000370000200d41106a200241106a290000370000200d41186a200241186a2900003700002000200029036837039002410910012204450d7c4131212a0caf010b200020043602482000420937024c200041c8006a410041091027200041c8006a41086a22102010280200220441096a220f360200200420002802486a221141002900f922370000200041286a41086a2204200f360200201141086a41002d0081233a000020002000290348370328200041c8006a20004190026a10be01200028024c211820002802482111200041286a20042802002010280200220f102720002802282210200428020022166a2011200f101e1a20042016200f6a22163602002018450d7c4132212a0cae010b201110024133212a0cad010b200028022c2118200041086a41086a220f42003703002000420037030820102016200041086a10032004200f29030037030020002000290308370328200041286a411041d02d410041001000417f460d7b4134212a0cac010b200041003a0048200041286a4110200041c8006a41014100100041016a41014d0d7b4136212a0cab010b20002d00482111200f42003703002000420037030820102016200041086a10032004200f29030037030020002000290308370328200041286a411010052018450d7d4137212a0caa010b201010024138212a0ca9010b201141ff01714102460d7c4139212a0ca8010b201420114101716a211420192011417f734101716a2119413a212a0ca7010b200241286a2102201741586a22170d72413b212a0ca6010b201920146a210220002802e402450d7a413c212a0ca5010b20241002413d212a0ca4010b201d20026b210220124103470d7b41da00212a0ca3010b20002d00e40141ff01714102470d7b41db00212a0ca2010b20190d7e41dc00212a0ca1010b20020d7c41dd00212a0ca0010b202328020010460c790b2014200220196a4d0d7941d000212a0c9e010b410910012204450d810141d100212a0c9d010b2000200436029002200042093702940220004190026a41004109102720004190026a41086a22042004280200221041096a220f36020020102000280290026a2211410029009823370000200041c8006a41086a2210200f360200201141086a41002d00a0233a0000200020002903900237034841201001220f450d810141d200212a0c9c010b2000200f36029002200042203702940220004190026a41004120102720042004280200221141206a220f360200201120002802900222166a22112000290368370000201141086a2021290300370000201141106a201b290300370000201141186a20152903003700002000280294022117200041c8006a2010280200200f102720002802482211201028020022186a2016200f101e1a20102018200f6a220f3602002017450d810141d300212a0c9b010b2016100241d400212a0c9a010b200028024c2110200041286a41086a22164200370300200042003703282011200f200041286a1003200041086a41086a201629030037030020002000290328370308200041086a411010052010450d800141d500212a0c99010b2011100241d600212a0c98010b20022019720d7f41d800212a0c97010b20004190026a41286a200041e0016a41286a290300370300200d200041e0016a41206a29030037030020004190026a41186a200041e0016a41186a29030037030020004190026a41106a200041e0016a41106a29030037030020042023290300370300200020002903e0013703900220004190026a410110ba010c530b201241077122024103460d7341c000212a0c95010b20020d5241c100212a0c94010b20002802e4012202450d5441c200212a0c93010b20024101470d7141cc00212a0c92010b2029280200450d5341cd00212a0c91010b202328020010020c530b4100211941002114410041006a210220002802e4020d660c650b20002d00e4014101470d4d41cf00212a0c8e010b202310bf010c4d0b20232802002110200041e0016a41106a2802002202450d6c41c400212a0c8c010b200241186c21042010210241c500212a0c8b010b200241046a280200450d6c41c600212a0c8a010b2002280200100241c700212a0c89010b200241106a280200450d6b41c800212a0c88010b2002410c6a280200100241c900212a0c87010b200241186a2102200441686a22040d6741ca00212a0c86010b2029280200450d4941cb00212a0c85010b201010020c490b200041f0026a24000f0b200d417f6a210d41010d340c330b200d417f6a210d41010d310c300b200d417e6a210d41010d2e0c2d0b200d417d6a210d41010d2b0c2a0b200d417c6a210d41010d280c270b101c000b41c1214133102d000b1064000b1065000b4187254139102d000b41c1214133102d000b41c1214133102d000b41f316411c102d000b41b43820182024103c000b419201212a0c740b4101212a0c730b4100212a0c720b4102212a0c710b4104212a0c700b4107212a0c6f0b4107212a0c6e0b4107212a0c6d0b418a01212a0c6c0b4107212a0c6b0b4107212a0c6a0b4107212a0c690b4107212a0c680b4107212a0c670b419101212a0c660b4109212a0c650b4114212a0c640b410b212a0c630b4113212a0c620b4113212a0c610b41d900212a0c600b41d900212a0c5f0b4111212a0c5e0b4113212a0c5d0b4115212a0c5c0b41fd00212a0c5b0b41fb00212a0c5a0b4117212a0c590b41fa00212a0c580b4119212a0c570b411b212a0c560b411a212a0c550b411b212a0c540b411a212a0c530b411b212a0c520b411a212a0c510b411b212a0c500b411a212a0c4f0b411b212a0c4e0b411a212a0c4d0b411b212a0c4c0b411d212a0c4b0b411f212a0c4a0b41f900212a0c490b41f800212a0c480b4122212a0c470b4124212a0c460b4126212a0c450b4128212a0c440b4129212a0c430b4129212a0c420b4129212a0c410b4129212a0c400b4129212a0c3f0b4129212a0c3e0b4129212a0c3d0b4129212a0c3c0b4129212a0c3b0b4129212a0c3a0b412b212a0c390b412b212a0c380b412d212a0c370b41e000212a0c360b41df00212a0c350b4130212a0c340b4130212a0c330b41d900212a0c320b4133212a0c310b41de00212a0c300b4135212a0c2f0b4138212a0c2e0b4137212a0c2d0b4138212a0c2c0b413a212a0c2b0b413d212a0c2a0b413d212a0c290b413c212a0c280b413e212a0c270b413e212a0c260b413f212a0c250b413f212a0c240b413f212a0c230b413f212a0c220b41ce00212a0c210b41c300212a0c200b41ca00212a0c1f0b41c500212a0c1e0b41c700212a0c1d0b41c900212a0c1c0b41d900212a0c1b0b41d900212a0c1a0b41d400212a0c190b41d600212a0c180b41d700212a0c170b41d900212a0c160b41e600212a0c150b41d900212a0c140b41d900212a0c130b41f700212a0c120b41e300212a0c110b41f600212a0c100b41e800212a0c0f0b41ec00212a0c0e0b41f500212a0c0d0b41f400212a0c0c0b41ef00212a0c0b0b41f100212a0c0a0b41f300212a0c090b418001212a0c080b41ff00212a0c070b418301212a0c060b418201212a0c050b418601212a0c040b418501212a0c030b418901212a0c020b418801212a0c010b418d01212a0c000b0b41c1214133102d000b1057000b1056000b41f4214122102d000b41f4214122102d000b41be164135102d000b41c1214133102d000b200f20131055000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41dcc1002004417f6a200d103c000b41ccc1002004200d103c000ba50c03047f017e177f23004180026b22012400200141b0016a41086a22024200370300200142003703b0014191264107200141b0016a1003200141086a2002290300370300200120012903b0013703000240024002400240024002402001411041d02d410041001000417f460d002001200136021020014110360214200141003602b0012001410020014110200141b0016a41044100100022022002417f461b2202410420024104491b2203360218200241034d0d0320012802b0012204ad42d8007e2205422088a70d052005a72202417f4c0d042002450d012002100122060d02101c000b200041003602082000420837020020014180026a24000f0b410821060b20012004360224200120063602202001410036022802402004450d0020014180016a41086a210720014180016a4104722108200121094100210a4110210b4100210c0340200141003602b001200141106a41086a220d41002009200b200141b0016a41042003100022022002417f461b2202410420024104491b20036a3602000240024002400240200241034d0d0020012802b001210e200141b0016a200141106a10bd0120012802b0014106460d0020014180016a41286a200141b0016a41286a220f29030037030020014180016a41206a200141b0016a41206a221029030037030020014180016a41186a2211200141b0016a41186a221229030037030020014180016a41106a2213200141b0016a41106a22142903003703002007200141b0016a41086a2215290300370300200120012903b00137038001200141e0016a41186a22164200370300200141e0016a41106a22174200370300200141e0016a41086a22184200370300200142003703e001200d200d28020022024100200128021022092001280214220b200141e0016a41202002100022022002417f461b2202412020024120491b6a220336020002402002411f4d0d00200141306a41186a22022016290300370300200141306a41106a220d2017290300370300200141306a41086a22162018290300370300200120012903e001370330200141d0006a41086a2217200841086a290200370300200141d0006a41106a2218200841106a290200370300200141d0006a41186a2219200841186a290200370300200141d0006a41206a221a200841206a290200370300200141d0006a41286a221b200841286a28020036020020012008290200370350200128028001221c4106460d01200c41016a210c200f201b2802003602002010201a290300370300201220192903003703002014201829030037030020152017290300370300200720162903003703002013200d29030037030020112002290300370300200120012903503703b0012001200129033037038001200a2001280224470d04200141206a1074200141206a41086a280200210a200128022021060c040b0240024020012802800122024103460d0020020d022001280284012202450d0220024101470d012001418c016a280200450d0220014188016a280200100220012802202103200a0d030c040b20012d0084014101470d012007104b20012802202103200a0d020c030b20014188016a2802002103024020014180016a41106a2802002202450d00200241186c21082003210203400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200841686a22080d000b0b2001418c016a280200450d00200310020b20012802202103200a450d010b200a41d8006c210820032102034020021038200241d8006a2102200841a87f6a22080d000b0b2001280224450d03200310020c030b2006200a41d8006c6a2202201c3602002002411c6a2012290300370200200241146a20142903003702002002410c6a2015290300370200200220012903b001370204200241246a20102903003702002002412c6a200f2802003602002002200e36023020022001290380013702342002413c6a2007290300370200200241c4006a2013290300370200200241cc006a2011290300370200200141206a41086a200a41016a220a360200200c2004490d000b200128022021060b2006450d00200020012902243702042000200636020020014180026a24000f0b41c1214133102d000b1059000b1058000b8d0402057f017e230041c0006b220224000240024002400240410810012203450d002002200336023020024208370234200241306a4100410810272002280230200228023822036a42e4cab5d3c3ac99b83a3700002002200341086a360238200241086a200228023836020020022002290330370300410410012203450d002002200336023020024204370234200241306a41004104102720022802302203200228023822046a20013600002002200441046a220136023820022802342105200220022802082001102720022802002204200228020822066a20032001101e1a2002200620016a220136020802402005450d00200310020b20022802042103200241306a41086a220542003703002002420037033020042001200241306a1003200241086a20052903003703002002200229033037030002402002411041d02d410041001000417f460d002002200236021020024110360214200242003703302002410020024110200241306a41084100100022012001417f461b2201410820014108491b360218200141074d0d0220022903302107200241306a200241106a103a20022802302201450d022002200229023437032020002001360208200020073703002000200229032037020c200041146a200241286a2802003602002003450d040c030b2000410036020820030d020c030b101c000b41c1214133102d000b200410020b200241c0006a24000bda0101027f0240024020002802002201450d0020014103470d0120002d00044101470d01200041086a22012802001038200128020010020f0b20002802042201450d00024020014101470d002000410c6a280200450d01200041086a28020010020f0b0240200041106a2802002202450d00200041086a2802002101200241186c210203400240200141046a280200450d00200128020010020b0240200141106a280200450d002001410c6a28020010020b200141186a2101200241686a22020d000b0b2000410c6a280200450d00200041086a28020010020f0b0b0a00200020012002100b0bc80403067f017e097f230041d0006b220224002002410036023020012001280208220341002001280200220420012802042205200241306a41042003100022032003417f461b2203410420034104491b6a220636020802400240024002400240200341034d0d0020022802302207ad2208421b88a70d042008420586a72203417f4c0d032003450d012003100122090d02101c000b20004100360200200241d0006a24000f0b410121090b20022007360204200220093602002002410036020802402007450d00200241306a41186a210a200241306a41106a210b410021034100210c0340200a4200370300200b4200370300200241306a41086a220d420037030020024200370330200141086a410020042005200241306a412020061000220e200e417f461b220e4120200e4120491b20066a220636020002400240200e411f4d0d00200c41016a210c200241106a41186a220f200a290300370300200241106a41106a2210200b290300370300200241106a41086a2211200d2903003703002002200229033037031020032002280204470d012002107c200241086a2802002103200228020021090c010b2000410036020002402002280204450d00200910020b200241d0006a24000f0b200920034105746a220e2002290310370000200e41186a200f290300370000200e41106a2010290300370000200e41086a2011290300370000200241086a200341016a2203360200200c2007490d000b0b20002002290300370200200041086a200241086a280200360200200241d0006a24000f0b1067000b1066000b2c02017f017e230041106b2201240020002902102102200120002902083703002001200237030820011054000b070020001054000bab0303017f017e047f230041306b220224002000104321030240410810012204450d002002200436022020024208370224200241206a4100410810272002280220200228022822046a42f3e885d3a3ac98b63a3700002002200441086a360228200241106a41086a200228022836020020022002290320370310412010012204450d00200320017c21012002200436022020024220370224200241206a41004120102720022802202205200228022822066a22042000290000370000200441086a200041086a290000370000200441106a200041106a290000370000200441186a200041186a2900003700002002200641206a220036022820022802242106200241106a20022802182000102720022802102204200228021822076a20052000101e1a2002200720006a220036021802402006450d00200510020b2002280214210520022001370308200241206a41086a220642003703002002420037032020042000200241206a1003200241106a41086a200629030037030020022002290320370310200241106a4110200241086a4108100402402005450d00200410020b200241306a24000f0b101c000bcb0501097f230041306b22012400200041086a28020021022001410036022820014201370320200141206a4100410410272001280220200128022822036a20023600002001200341046a360228200141086a220420012802283602002001200129032037030002400240024002402002450d0020002802002100200241d8006c21050340200141106a41086a2203410036020020014201370310200041306a2802002102200141106a41004104102720032003280200220641046a2207360200200620012802106a2002360000200141206a200010d80120012802202108200141106a2007200141206a41086a22062802002202102720032002200328020022076a2209360200200720012802106a20082002101e1a02402001280224450d00200810020b200141106a20094120102720032003280200220741206a22023602002007200128021022086a220341086a2000413c6a290000370000200341106a200041c4006a290000370000200341186a200041cc006a2900003700002003200041346a2900003700002002417f4c0d03024002402002450d002002100122030d010c060b410121030b200641003602002001200236022420012003360220200141206a41002002102720062006280200220720026a22033602002007200128022022066a20082002101e1a2001280224210202402001280214450d00200810020b200120042802002003102720012802002207200428020022086a20062003101e1a2004200820036a220336020002402002450d00200610020b200041d8006a2100200541a87f6a22050d000c020b0b20012802082103200128020021070b20012802042100200141206a41086a22024200370300200142003703204191264107200141206a1003200141106a41086a200229030037030020012001290320370310200141106a411020072003100402402000450d00200710020b200141306a24000f0b1019000b101c000be50c03037f017e047f230041a0016b22032400200341086a220442003703002003420037030041852741072003100320034180016a41086a200429030037030020032003290300370380010240024020034180016a411041d02d410041001000417f460d00200341003602400240024020034180016a4110200341c0006a41044100100041016a41044d0d00024020032802402205450d0020032005417f6a104020032802084106460d00200341c0006a41086a2204200341086a290300370300200341c0006a41386a200341386a290300370300200341c0006a41306a200341306a290300370300200341c0006a41286a200341286a290300370300200341c0006a41206a200341206a290300370300200341c0006a41186a200341186a290300370300200341c0006a41106a200341106a290300370300200320032903002206370340024002400240200428020022044103460d0020040d02200341cc006a2802002204450d0220044101470d01200341d4006a280200450d02200341d0006a280200100220062000580d030c070b200341cc006a2d00004101470d01200341d0006a102220062000580d020c060b200341c0006a41106a28020021070240200341c0006a41186a2802002204450d00200441186c21082007210403400240200441046a280200450d00200428020010020b0240200441106a280200450d002004410c6a28020010020b200441186a2104200841686a22080d000b0b200341d4006a280200450d00200710020b20062000560d040b2003200541016a360240200341086a220442003703002003420037030041852741072003100320034180016a41086a22082004290300370300200320032903003703800120034180016a4110200341c0006a41041004200341c0006a41106a200141086a290300370300200341c0006a41186a200141106a290300370300200341c0006a41206a200141186a290300370300200341c0006a41286a200141206a290300370300200341f0006a200141286a29030037030020032000370340200320023a007820032001290300370348410810012201450d01200320013602002003420837020420034100410810272003280200200328020822016a42e4cab5d383cedcb73a3700002003200141086a360208200820032802083602002003200329030037038001410410012201450d01200341c0006a41086a21022003200136020020034204370204200341004104102720032802002204200328020822016a20053600002003200141046a22013602082003280204210820034180016a20032802880120011027200328028001220520032802880122076a20042001101e1a2003200720016a22073602880102402008450d00200410020b200328028401210841002104200341003602980120034201370390012003290340210020034190016a41004108102720032802900120032802980122016a20003700002003200141086a2209360298012003200210d8012003280200210220034190016a20092003280208220110272003200120032802980122096a220a3602980120092003280290016a20022001101e1a02402003280204450d00200210020b02400240200341f8006a2d000022014103714102460d0020014101470d01410121040c010b410221040b20034190016a200a4101102720034190016a41086a22012001280200220241016a2209360200200220032802900122016a20043a0000200341086a2204420037030020034200370300200520072003100320034180016a41086a2004290300370300200320032903003703800120034180016a41102001200910040240200328029401450d00200110020b02402008450d00200510020b024002400240200328024822014103460d0020010d02200341cc006a2802002201450d0220014101470d01200341d4006a280200450d02200341d0006a2802001002200341a0016a24000f0b200341cc006a2d00004101470d01200341d0006a1022200341a0016a24000f0b0240200341c0006a41186a2802002204450d00200341c0006a41106a2802002101200441186c210403400240200141046a280200450d00200128020010020b0240200141106a280200450d002001410c6a28020010020b200141186a2101200441686a22040d000b0b200341d4006a280200450d00200341d0006a28020010020b200341a0016a24000f0b41c1214133102d000b101c000b41f4214122102d000b4184c000103b000b810a03057f017e067f230041c0016b220224000240024002400240410810012203450d002002200336029001200242083702940120024190016a41004108102720022802900120022802980122036a42e4cab5d383cedcb73a3700002002200341086a36029801200241e0006a41086a2002280298013602002002200229039001370360410410012203450d002002200336029001200242043702940120024190016a410041041027200228029001220320022802980122046a20013600002002200441046a2201360298012002280294012105200241e0006a20022802682001102720022802602204200228026822066a20032001101e1a2002200620016a220136026802402005450d00200310020b2002280264210520024190016a41086a2203420037030020024200370390012004200120024190016a1003200241086a41086a20032903003703002002200229039001370308024002400240200241086a411041d02d410041001000417f460d002002200241086a3602182002411036021c200242003703900120024100200241086a411020024190016a41084100100022012001417f461b2201410820014108491b360220200141074d0d06200229039001210720024190016a200241186a10bd012002280290014106460d06200241e0006a41286a20024190016a41286a290300370300200241e0006a41206a20024190016a41206a290300370300200241e0006a41186a20024190016a41186a290300370300200241e0006a41106a20024190016a41106a290300370300200241e0006a41086a20024190016a41086a2903003703002002200229039001370360200241003a0030200241186a41086a2201200128020022012002280218200228021c200241306a41012001100041016a220141014b6a360200024020014102490d0020022d0030220141034f0d00200241386a2206200241ec006a290200370300200241c0006a2208200241e0006a41146a290200370300200241c8006a2209200241e0006a411c6a290200370300200241d0006a220a200241e0006a41246a290200370300200241d8006a220b200241e0006a412c6a2802003602002002200229026437033020022802602103200241286a41066a220c200241e0006a41066a2d00003a0000200241286a41046a220d200241e0006a41046a2f00003b01002002200228006036022820034106460d0720002003360208200020073703002000200229033037020c20002002280228360039200041386a20013a0000200041146a20062903003702002000411c6a2008290300370200200041246a20092903003702002000412c6a200a290300370200200041346a200b2802003602002000413d6a200d2f01003b00002000413f6a200c2d00003a000020050d020c030b200228026022010d0420022802642201450d0620014101460d05200241e8006a28020021030240200241e0006a41106a2802002201450d00200141186c21002003210103400240200141046a280200450d00200128020010020b0240200141106a280200450d002001410c6a28020010020b200141186a2101200041686a22000d000b0b200241ec006a280200450d06200310020c060b200041063602082005450d010b200410020b200241c0016a24000f0b101c000b20014103470d0120022d00644101470d01200241e8006a104b41c1214133102d000b200241ec006a280200450d00200241e8006a280200100241c1214133102d000b41c1214133102d000b080041fc31103b000b960201057f230041206b220224000240410810012203450d002002200336021020024208370214200241106a4100410810272002280210200228021822036a42e4cab5d3e38e9db93a3700002002200341086a360218200241086a200228021836020020022002290310370300410410012203450d002002200336021020024204370214200241106a41004104102720022802102203200228021822046a20013600002002200441046a220136021820022802142105200220022802082001102720022802002204200228020822066a20032001101e1a2002200620016a220136020802402005450d00200310020b2002280204210320002004200110da0102402003450d00200410020b200241206a24000f0b101c000bc70302057f017e230041206b220124000240410810012202450d002001200236021020014208370214200141106a4100410810272001280210200128021822026a42f3e885d3a3ac98b63a3700002001200241086a360218200141086a200128021836020020012001290310370300412010012202450d002001200236021020014220370214200141106a41004120102720012802102203200128021822046a22022000290000370000200241086a200041086a290000370000200241106a200041106a290000370000200241186a200041186a2900003700002001200441206a220036021820012802142104200120012802082000102720012802002202200128020822056a20032000101e1a2001200520006a220036020802402004450d00200310020b2001280204210342002106200141106a41086a220442003703002001420037031020022000200141106a1003200141086a200429030037030020012001290310370300024002402001411041d02d410041001000417f460d002001420037031020014110200141106a41084100100041016a41084d0d01200129031021060b02402003450d00200210020b200141206a240020060f0b41c1214133102d000b101c000bc70302057f017e230041206b220124000240410810012202450d002001200236021020014208370214200141106a4100410810272001280210200128021822026a42f3e885d3c3cdd8b73a3700002001200241086a360218200141086a200128021836020020012001290310370300412010012202450d002001200236021020014220370214200141106a41004120102720012802102203200128021822046a22022000290000370000200241086a200041086a290000370000200241106a200041106a290000370000200241186a200041186a2900003700002001200441206a220036021820012802142104200120012802082000102720012802002202200128020822056a20032000101e1a2001200520006a220036020802402004450d00200310020b2001280204210342002106200141106a41086a220442003703002001420037031020022000200141106a1003200141086a200429030037030020012001290310370300024002402001411041d02d410041001000417f460d002001420037031020014110200141106a41084100100041016a41084d0d01200129031021060b02402003450d00200210020b200141206a240020060f0b41c1214133102d000b101c000bb80201047f230041206b2202240020024100360208200242013703002001280200210320024100410410272002280200200228020822046a20033600002002200441046a2203360208200220034120102720022802002204200228020822056a22032001290004370000200341086a2001410c6a290000370000200341106a200141146a290000370000200341186a2001411c6a2900003700002002200541206a220136020802402001417f4c0d00024002402001450d002001100122030d01101c000b410121030b200220013602142002200336021020024100360218200241106a41002001102720022002280218220320016a360218200320022802106a20042001101e1a200041086a20022802183602002000200229031037020002402002280204450d00200410020b200241206a24000f0b1019000bc808010d7f230041d0006b220124000240410810012202450d00200120023602082001420837020c200141086a4100410810272001280208200128021022026a42e4cab5d383cedcb73a3700002001200241086a360210200141c0006a41086a200128021036020020012001290308370340410410012202450d00200120023602082001420437020c200141086a41004104102720012802082203200128021022026a20003600002001200241046a2202360210200128020c2104200141c0006a20012802482002102720012802402205200128024822066a20032002101e1a2001200620026a220236024802402004450d00200310020b20012802442103200141c0006a41086a220442003703002001420037034020052002200141c0006a1003200141306a41086a200429030037030020012001290340370330200141306a4110100502402003450d00200510020b410810012202450d00200120023602082001420837020c200141086a4100410810272001280208200128021022026a42e4cab5d3e38e9db93a3700002001200241086a360210200141c0006a41086a200128021036020020012001290308370340410410012202450d00200120023602082001420437020c200141086a41004104102720012802082203200128021022026a20003600002001200241046a2202360210200128020c2104200141c0006a20012802482002102720012802402205200128024822066a20032002101e1a2001200620026a220236024802402004450d00200310020b20012802442103200141c0006a41086a220442003703002001420037034020052002200141c0006a1003200141306a41086a200429030037030020012001290340370330200141306a4110100502402003450d00200510020b200141086a20001042200128020c210720012802082108024020012802102202450d0020024105742109200141086a410472210420082102034020042002290000370000200441186a200241186a290000370000200441106a200241106a290000370000200441086a200241086a29000037000020012000360208410810012203450d022001200336024020014208370244200141c0006a410041081027200141c0006a41086a22032003280200220541086a360200200520012802406a42e4cab5d3e3ee9bba3a370000200141306a41086a2205200328020036020020012001290340370330200141c0006a200141086a10452001280244210a2001280240210b200141306a20052802002003280200220610272001280230220c2005280200220d6a200b2006101e1a2005200d20066a22063602000240200a450d00200b10020b2001280234210b2003420037030020014200370340200c2006200141c0006a10032005200329030037030020012001290340370330200141306a411010050240200b450d00200c10020b200241206a2102200941606a22090d000b0b02402007450d00200810020b200141d0006a24000f0b101c000b810604047f017e097f037e230041e0006b22012400200141c0006a41086a220242003703002001420037034041c7114107200141c0006a1003200141086a2002290300370300200120012903403703000240024002400240024002402001411041d02d410041001000417f460d0020014100360240410020014110200141c0006a41044100100022022002417f461b220341034d0d0320012802402204ad42287e2205422088a70d042005a72202417f4c0d052002450d012002100122060d02101c000b2000410036020820004208370200200141e0006a24000f0b410821060b200120043602142001200636021020014100360218024002402004450d002003410420034104491b2107200141c0006a41186a2108200141c0006a41086a2109410021034100210a034020084200370300200141c0006a41106a220b42003703002009420037030020014200370340410020014110200141c0006a41202007100022022002417f461b2202411f4d0d02200141206a41186a220c2008290300370300200141206a41106a220d200b290300370300200141206a41086a220e20092903003703002001200129034037032020014200370340410020014110200141c0006a41082002412020024120491b20076a2207100022022002417f461b220241074d0d02200a41016a210a2002410820024108491b2102200129034021052008200c290300370300200b200d2903003703002009200e29030037030020012001290320370340024020032001280214470d00200141106a1078200141106a41086a2802002103200128021021060b200220076a21072006200341286c6a220220012903403703002009290300210f200b29030021102008290300211120022005370320200241186a2011370300200241106a2010370300200241086a200f370300200141106a41086a200341016a2203360200200a2004490d000b200128021021060b2006450d012000200129021437020420002006360200200141e0006a24000f0b2001280214450d00200610020b41c1214133102d000b1056000b1057000bf81505037f017e087f017e047f230041f0006b22002400200041086a41086a220142003703002000420037030841c81d4107200041086a1003200041d0006a41086a200129030037030020002000290308370350024002400240024002400240200041d0006a411041d02d410041001000417f460d00200042003703080240024002400240200041d0006a4110200041086a41084100100041016a41084d0d002000200029030842017c370340200041086a41086a220142003703002000420037030841c81d4107200041086a1003200041d0006a41086a2202200129030037030020002000290308370350200041d0006a4110200041c0006a41081004200142003703002000420037030841cf1d4107200041086a100320022001290300370300200020002903083703500240200041d0006a411041d02d410041001000417f460d0020004200370308200041d0006a4110200041086a41084100100041016a41084d0d02200020002903082203370330200041086a41086a220142003703002000420037030841c11d4107200041086a1003200041d0006a41086a200129030037030020002000290308370350200041d0006a411041d02d410041001000417f460d0920004200370308200041d0006a4110200041086a41084100100041016a41084d0d0320032000290308510d0020002003370340200041086a41086a220142003703002000420037030841c11d4107200041086a1003200041d0006a41086a2202200129030037030020002000290308370350200041d0006a4110200041c0006a410810042000102e370340200142003703002000420037030841ba1d4107200041086a10032002200129030037030020002000290308370350200041d0006a4110200041c0006a410810040b200041086a41086a220142003703002000420037030841d61d4108200041086a1003200041d0006a41086a2001290300370300200020002903083703504100210102400240200041d0006a411041d02d410041001000417f460d00200042103702442000200041d0006a360240200041086a200041c0006a103a20002802082204450d0b200041106a2802002101200028020c21050c010b41012104410021050b2000410036024820004208370340200041c0006a20014105742206410575108501200028024821022000280240210702402006450d002007200241286c6a21012002200641606a4105766a2108200421020340200041086a41186a2209200241186a290000370300200041086a41106a220a200241106a290000370300200041086a41086a220b200241086a29000037030020002002290000370308200041086a10432103200041086a1044210c200041d0006a41186a220d2009290300370300200041d0006a41106a2209200a290300370300200041d0006a41086a220a200b290300370300200020002903083703502001200c20037c370300200141206a200d290300370300200141186a2009290300370300200141106a200a290300370300200141086a2000290350370300200141286a2101200241206a2102200641606a22060d000b200841016a21020b02402005450d00200410020b200041c0006a41086a20023602002000280244210820072002410041202002676b10c401200041086a41086a220142003703002000420037030841de1d4107200041086a1003200041d0006a41086a200129030037030020002000290308370350200041d0006a411041d02d410041001000417f460d0520004100360208200041d0006a4110200041086a41044100100041016a41044d0d032000280208210b2000410036024820004201370340200041c0006a4100200241286c220941286d2201200b2001200b491b1086012000280248210a2000280240210e0240200b450d00200e200a4105746a2102200041086a41086a21062007210103402009450d01200041086a41206a200141206a290300370300200041086a41186a200141186a290300370300200041086a41106a200141106a2903003703002006200141086a290300370300200041d0006a41086a220d200641086a290000370300200041d0006a41106a2204200641106a290000370300200041d0006a41186a2205200641186a2900003703002000200129030037030820002006290000370350200241186a2005290300370000200241106a2004290300370000200241086a200d29030037000020022000290350370000200941586a2109200a41016a210a200241206a2102200141286a2101200b417f6a220b0d000b0b02402008450d00200710020b200041c8006a200a360200200aad2203421b88a70d062003420586a72201417f4c0d072000280244210f024002402001450d002001100122010d01101c000b410121010b2000200a36020c2000200136020820004100360210200041086a4100200a108601200020002802102201200a6a360210200028020820014105746a200e200a4105742202101e1a200041306a41086a200028021036020020002000290308370330200041c0006a200041306a10a2012000280248210620002802402101200041086a41086a220942003703002000420037030841e4084107200041086a1003200041d0006a41086a200929030037030020002000290308370350200041d0006a411020012006100402402000280244450d00200110020b02402000280234450d00200028023010020b410021062000410036024820004201370340200041c0006a4100200241057510860120002802482101200028024021100240200a4105742209450d00200041086a41186a220a200e41186a290000370300200041086a41106a220b200e41106a290000370300200041086a41086a220d200e41086a2900003703002000200e290000370308200141016a2104200e41206a2102200941606a2109201020014105746a210102400340200041d0006a41186a2205200a290300370300200041d0006a41106a2207200b290300370300200041d0006a41086a2208200d29030037030020002000290308370350200141186a2005290300370000200141106a2007290300370000200141086a2008290300370000200120002903503700002009450d01200a200241186a290000370300200b200241106a290000370300200d200241086a29000037030020002002290000370308200441016a2104200241206a2102200941606a2109200141206a21010c000b0b200421010b200041c0006a41086a20013602002000280244210d02402001450d002001410574210241002106200041086a41086a210a201021010340200041086a2006103220002802082209200a2802002001412010040240200028020c450d00200910020b200141206a2101200641016a2106200241606a22020d000b0b200041086a10302000280208220120002802101031210b0240200028020c450d00200110020b0240200b20064d0d00200041106a210a200621010340200041086a103020002802082202200a280200103121090240200028020c450d00200210020b200141016a21020240200920014d0d00200041086a2001103220002802082201200a2802001005200028020c450d00200110020b20022101200b2002470d000b0b200041086a103020002802102102200028020821012000200636025020012002200041d0006a410410040240200028020c450d00200110020b0240200d450d00201010020b0240200f450d00200e10020b200041f0006a24000f0b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41f4214122102d000b41f4214122102d000b1066000b1067000b41f4214122102d000b41c1214133102d000bba0103027f017e017f024002400240200041046a280200220320016b20024f0d00200120026a220220014922010d01200341017422044100200220011b2201200420014b1b2204ad42287e2205a722014100480d012005422088a74100470d01024002402003450d0020002802002106200110012202450d04200220062001200341286c2203200320014b1b101e1a200610020c010b200110012202450d030b20002002360200200041046a20043602000b0f0b1041000b101c000bf40403067f017e027f230041306b22012400200041086a28020021022001410036022820014201370320200141206a4100410410272001280220200128022822036a20023600002001200341046a360228200141086a220420012802283602002001200129032037030002400240024002402002450d0020002802002200200241286c6a21050340200141106a41086a2203410036020020014201370310200141106a41004120102720032003280200220241206a2206360200200220012802106a220241186a200041186a290000370000200241106a200041106a290000370000200241086a200041086a29000037000020022000290000370000200041206a2903002107200141106a20064108102720032003280200220641086a22023602002006200128021022086a20073700002002417f4c0d03024002402002450d002002100122030d010c060b410121030b200141206a41086a220641003602002001200236022420012003360220200141206a41002002102720062006280200220920026a22033602002009200128022022066a20082002101e1a2001280224210202402001280214450d00200810020b200120042802002003102720012802002209200428020022086a20062003101e1a2004200820036a220336020002402002450d00200610020b200041286a22002005470d000c020b0b20012802082103200128020021090b20012802042102200141206a41086a220042003703002001420037032041c7114107200141206a1003200141106a41086a200029030037030020012001290320370310200141106a411020092003100402402002450d00200910020b200141306a24000f0b1019000b101c000be60101037f0240024002402000280200220128020022024103460d0020020d0220012802042202450d0220024101470d012001410c6a280200450d02200141086a2802001002200028020010020f0b20012d00044101470d01200141086a104b200028020010020f0b0240200141106a2802002203450d00200141086a2802002102200341186c210303400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200341686a22030d000b0b2001410c6a280200450d00200141086a28020010020b200028020010020bd60403047f017e087f230041c0006b2203240020024103742104410021050240024002400240024002402002450d0020044103752206ad4202862207a722084100480d042007422088a74100470d04200810012209450d05200120046a220a2001460d010c020b4104210941002106200120046a220a2001470d010b4101210c410021040c010b20024103742108200a41786a210b410021022009210403402004200120026a41046a280200360200200441046a21042008200241086a2202470d000b200b20016b41037641016a21054101210c410021044100210803402001280200210d0240024002402004200822026b200141046a280200220b4f0d002002200b6a22082002490d052004410174220e20082008200e491b220e4100480d052004450d01200e1001220f450d06200f200c200e20042004200e4b1b101e210f200c1002200e2104200f210c0c020b2002200b6a21080c010b200e2104200e1001220c450d040b200c20026a200d200b101e1a200141086a2201200a470d000b0b200341206a41186a22014200370300200341206a41106a22024200370300200341206a41086a2208420037030020034200370320200c20092005200341206a1007200341186a2001290300370300200341106a2002290300370300200341086a20082903003703002003200329032037030002402004450d00200c10020b02402006450d00200910020b20002003290300370000200041186a200341186a290300370000200041106a200341106a290300370000200041086a200341086a290300370000200341c0006a24000f0b1041000b101c000b14002006200710082008ad10092009ad100900000b0b0041e70a4122100800000b7901047f0240024002400240200041046a2802002201450d002001418080808004710d03200028020021022001410174220310012204450d022004200220032001200120034b1b101e1a200210020c010b410410012204450d01410421030b20002004360200200041046a20033602000f0b101c000b1050000b05001041000ba60101047f200141086a28020021024104210302400240410410012204450d002004200236000020012802002105024002402002450d00200241046a22032002490d0320034108200341084b1b22034100480d03200310012201450d02200120042003410420034104491b101e1a200410020c010b200421010b200141046a20052002101e1a20002003360204200020013602002000200241046a3602080f0b101c000b1041000b0600200010010b0600200010020b2500200020002000200020002000200028020020002802042000280208200028020c104d000b080041a4321054000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b830101057f410421010240024002400240200041046a2802002202450d00200241d0006c2201417f4c0d0320002802002103200110012204450d02200420032001200241286c2205200520014b1b101e1a20031002200241017421010c010b41a00110012204450d010b20002004360200200041046a20013602000f0b101c000b1069000b05001041000b850101057f410421010240024002400240200041046a2802002202450d0020024180808010710d03200028020021012002410674220310012204450d0220042001200320024105742205200520034b1b101e1a20011002200241017421010c010b41800110012204450d010b20002004360200200041046a20013602000f0b101c000b106b000b05001041000b840101057f410421010240024002400240200041046a2802002202450d0020024180066c2201417f4c0d0320002802002103200110012204450d0220042003200120024180036c2205200520014b1b101e1a20031002200241017421010c010b41800c10012204450d010b20002004360200200041046a20013602000f0b101c000b106d000b05001041000b05001041000b830101057f410421010240024002400240200041046a2802002202450d00200241d0006c2201417f4c0d0320002802002103200110012204450d02200420032001200241286c2205200520014b1b101e1a20031002200241017421010c010b41a00110012204450d010b20002004360200200041046a20013602000f0b101c000b1070000b05001041000b850101057f410421010240024002400240200041046a2802002202450d00200241808080c000710d03200028020021012002410474220310012204450d0220042001200320024103742205200520034b1b101e1a20011002200241017421010c010b412010012204450d010b20002004360200200041046a20013602000f0b101c000b1072000b05001041000b05001041000b840101057f410421010240024002400240200041046a2802002202450d00200241b0016c2201417f4c0d0320002802002103200110012204450d02200420032001200241d8006c2205200520014b1b101e1a20031002200241017421010c010b41e00210012204450d010b20002004360200200041046a20013602000f0b101c000b1075000b05001041000b820101057f410421010240024002400240200041046a2802002202450d00200241306c2201417f4c0d0320002802002103200110012204450d02200420032001200241186c2205200520014b1b101e1a20031002200241017421010c010b41e00010012204450d010b20002004360200200041046a20013602000f0b101c000b1077000b05001041000b830101057f410421010240024002400240200041046a2802002202450d00200241d0006c2201417f4c0d0320002802002103200110012204450d02200420032001200241286c2205200520014b1b101e1a20031002200241017421010c010b41a00110012204450d010b20002004360200200041046a20013602000f0b101c000b1079000b05001041000b850101057f410421010240024002400240200041046a2802002202450d00200241808080c000710d03200028020021012002410474220310012204450d0220042001200320024103742205200520034b1b101e1a20011002200241017421010c010b412010012204450d010b20002004360200200041046a20013602000f0b101c000b107b000b05001041000b850101057f0240024002400240200041046a2802002201450d0020014180808010710d03200028020021022001410674220310012204450d0220042002200320014105742205200520034b1b101e1a20021002200141017421010c010b41800110012204450d01410421010b20002004360200200041046a20013602000f0b101c000b107d000b05001041000b7901047f0240024002400240200041046a2802002201450d002001418080808004710d03200028020021022001410174220310012204450d022004200220032001200120034b1b101e1a200210020c010b410410012204450d01410421030b20002004360200200041046a20033602000f0b101c000b107f000b05001041000b860101057f410421010240024002400240200041046a2802002202450d0020024180808020710d03200028020021012002410574220310012204450d0220042001200320024104742205200520034b1b101e1a20011002200241017421010c010b41c00010012204450d010b20002004360200200041046a20013602000f0b101c000b108101000b05001041000bba0103027f017e017f024002400240200041046a280200220320016b20024f0d00200120026a220220014922010d01200341017422044100200220011b2201200420014b1b2204ad42287e2205a722014100480d012005422088a74100470d01024002402003450d0020002802002106200110012202450d04200220062001200341286c2203200320014b1b101e1a200610020c010b200110012202450d030b20002002360200200041046a20043602000b0f0b1041000b101c000bba0103027f017e017f024002400240200041046a280200220320016b20024f0d00200120026a220220014922010d01200341017422044100200220011b2201200420014b1b2204ad42187e2205a722014100480d012005422088a74100470d01024002402003450d0020002802002106200110012202450d04200220062001200341186c2203200320014b1b101e1a200610020c010b200110012202450d030b20002002360200200041046a20043602000b0f0b1041000b101c000ba20103037f017e017f024002400240200041046a280200220220014f0d00200241017422032001200320014b1b2204ad420c7e2205a722014100480d012005422088a74100470d01024002402002450d0020002802002106200110012203450d042003200620012002410c6c2202200220014b1b101e1a200610020c010b200110012203450d030b20002003360200200041046a20043602000b0f0b1041000b101c000ba20103037f017e017f024002400240200041046a280200220220014f0d00200241017422032001200320014b1b2204ad42287e2205a722014100480d012005422088a74100470d01024002402002450d0020002802002106200110012203450d04200320062001200241286c2202200220014b1b101e1a200610020c010b200110012203450d030b20002003360200200041046a20043602000b0f0b1041000b101c000bba0103027f017e017f024002400240200041046a280200220320016b20024f0d00200120026a220220014922010d01200341017422044100200220011b2201200420014b1b2204ad4205862205a722014100480d012005422088a74100470d01024002402003450d0020002802002106200110012202450d0420022006200120034105742203200320014b1b101e1a200610020c010b200110012202450d030b20002002360200200041046a20043602000b0f0b1041000b101c000b0e0002402001450d00200010020b0bc00d010f7f230041e0066b220424000240200128020422052f01be032206410a4b0d00200441a8036a41206a2207200341206a290300370300200441a8036a41186a2208200341186a290300370300200441a8036a41106a2209200341106a290300370300200441a8036a41086a220a200341086a290300370300200420032903003703a8032005200128020c220b4105746a220341e0036a200341c0036a220c2006200b6b41057410391a200341d8036a200241186a290000370000200341d0036a200241106a290000370000200341c8036a200241086a290000370000200c20022900003700002005200b41286c6a220341286a2003200541be036a22052f0100200b6b41286c10391a200341206a2007290300370300200341186a2008290300370300200341106a2009290300370300200341086a200a290300370300200320042903a803370300200520052f010041016a3b0100200441b3036a200141086a280000360000200041003a000020002003360260200041106a200128020c360000200420012900003700ab03200020042900a803370001200041086a200441af036a290000370000200441e0066a24000f0b2001280208210d2001280200210e024041a0061001220b450d00200b200441a8036a41b803101e220b41003b01be03200b41003602b803200b41c0036a200441c8006a41e002101e210f200441286a41186a220c20054198056a290200370300200441286a41106a221020054190056a290200370300200441286a41086a221120054188056a290200370300200441a8036a41086a2206200541f8016a290300370300200441a8036a41106a220720054180026a290300370300200441a8036a41186a220820054188026a290300370300200441a8036a41206a220920054190026a290300370300200420054180056a290200370328200420052903f0013703a803200f200541a0056a200541be036a220a2f010041796a2212410574101e210f200b20054198026a201241286c101e210b200a41063b0100200b20123b01be03200441186a200c290300370300200441106a2010290300370300200441086a201129030037030020042004290328370300200441c8006a41206a2009290300370300200441c8006a41186a2008290300370300200441c8006a41106a2007290300370300200441c8006a41086a2006290300370300200420042903a803370348200441003602242004200b36022002400240200128020c220141064b0d002009200341206a2903003703002008200341186a2903003703002007200341106a2903003703002006200341086a290300370300200420032903003703a803200520014105746a220341e0036a200341c0036a220b200a2f010020016b41057410391a200341d8036a200241186a290000370000200341d0036a200241106a290000370000200341c8036a200241086a290000370000200b20022900003700002005200141286c6a220341286a2003200a2f010020016b41286c10391a200341206a2009290300370300200341186a2008290300370300200341106a2007290300370300200341086a2006290300370300200320042903a803370300200a200a2f010041016a3b01000c010b200c200241186a2900003703002010200241106a2900003703002011200241086a290000370300200420022900003703282009200341206a2903003703002008200341186a2903003703002007200341106a2903003703002006200341086a290300370300200420032903003703a803200f20014105746a41c07e6a200f200141796a22024105746a2203200b2f01be0320026b41057410391a200341186a200c290300370000200341106a2010290300370000200341086a201129030037000020032004290328370000200b200141286c6a220141907e6a200141e87d6a2203200b2f01be0320026b41286c10391a200141887e6a2009290300370300200141807e6a2008290300370300200141f87d6a2007290300370300200141f07d6a2006290300370300200320042903a803370300200b200b2f01be0341016a3b01be030b200041013a000020002004290300370001200041246a200e360000200041286a20053600002000412c6a200d360000200041306a2004290320370300200041386a2004290348370300200041096a200441086a290300370000200041116a200441106a290300370000200041196a200441186a290300370000200041d0006a200441c8006a41186a290300370300200041c8006a200441c8006a41106a290300370300200041c0006a200441c8006a41086a290300370300200041d8006a200441e8006a29030037030020002003360260200441e0066a24000f0b101c000ba108010a7f230041c0026b220424000240200128020422052f018e022206410a4b0d00200441286a41086a2207200241086a28020036020020042002290200370328200441386a41086a2208200341086a280200360200200420032902003703382005200128020c2202410c6c2203410c6a22096a200520036a220a200620026b410c6c10391a200a41086a2007280200360200200a200429032837020020054184016a220620096a200620036a22032005418e026a22052f010020026b410c6c10391a200341086a200828020036020020032004290338370200200520052f010041016a3b0100200128020c210520004100360200200041106a2005360200200020062005410c6c6a360230200020012902003702042000410c6a200141086a280200360200200441c0026a24000f0b2001280208210b2001280200210c024041900210012206450d002006200441386a418802101e220641003b018e022006410036028802200441386a41086a220a200541d0006a280200360200200441286a41086a2207200541d4016a280200360200200420052902483703382004200541cc016a2902003703282006200541d4006a2005418e026a22082f010041796a2209410c6c220d101e22064184016a200541d8016a200d101e210d200841063b0100200620093b018e02200441086a200a28020036020020042004290338370300200441106a41086a200728020036020020042004290328370310200441003602242004200636022002400240200128020c220941064b0d002007200241086a28020036020020042002290200370328200a200341086a2802003602002004200329020037033820052009410c6c2201410c6a22036a200520016a220220082f010020096b410c6c10391a200241086a20072802003602002002200429032837020020054184016a220220036a200220016a220120082f010020096b410c6c10391a200141086a200a28020036020020012004290338370200200820082f010041016a3b01000c010b2007200241086a28020036020020042002290200370328200a200341086a2802003602002004200329020037033820062009410c6c220141b87f6a22026a2006200141ac7f6a22036a220120062f018e02200941796a22086b410c6c10391a200141086a200728020036020020012004290328370200200d20026a200d20036a220120062f018e0220086b410c6c10391a200141086a200a28020036020020012004290338370200200620062f018e0241016a3b018e020b200041013602002000200c36020420002001360230200041086a20053602002000410c6a200b360200200041106a20042903003702002000411c6a2004290310370200200041286a2004290320370200200041186a200441086a280200360200200041246a200441106a41086a280200360200200441c0026a24000f0b101c000bf307010d7f23004180036b220624000240200128020422072f018e02410a4b0d00200641c8006a41086a200241086a28020036020020062002290200370348200641f8006a41086a200341086a280200360200200620032902003703782001200641c8006a200641f8006a2004108b0120004100360200200020012902003702042000410c6a200141086a29020037020020064180036a24000f0b2001280208210820012802002109024041c0021001220a450d004100210b200a200641f8006a418802101e220a41003b018e02200a410036028802200a200629024837029002200a4198026a200641c8006a41086a220c290200370200200a41a0026a200641d8006a290200370200200a41a8026a200641e0006a290200370200200a41b0026a200641e8006a290200370200200a41b8026a200641f0006a290200370200200c200741d0006a28020036020020062007290248370348200641f8006a41086a220d200741d4016a2802003602002006200741cc016a290200370378200a200741d4006a2007418e026a220e2f0100220f41796a2210410c6c2211101e22124184016a200741d8016a2011101e1a20124190026a220a200741ac026a200f417a6a220f410274101e1a200e41063b0100201220103b018e020240200f450d000340200a280200220e200b3b018c02200e201236028802200a41046a210a200b41016a220b200f490d000b0b200641386a41086a220b200c280200360200200641286a41086a220a200d2802003602002006200629034837033820062006290378370328200641086a200b28020036020020062006290338370300200641106a41086a200a28020036020020062006290328370310200620093602242006201236022002400240200128020c220b41064b0d002006200736027c2006200936027820062008360280012006200b36028401200641386a41086a200241086a28020036020020062002290200370338200641c8006a41086a200341086a28020036020020062003290200370348200641f8006a200641386a200641c8006a2004108b010c010b2006201236027c200620093602782006200b41796a360284012006200641206a36028001200641386a41086a200241086a28020036020020062002290200370338200641c8006a41086a200341086a28020036020020062003290200370348200641f8006a200641386a200641c8006a2004108b010b2000200936020420004101360200200041086a20073602002000410c6a2008360200200041106a20062903003702002000411c6a2006290310370200200041286a2006290320370200200041186a200641086a280200360200200041246a200641106a41086a28020036020020064180036a24000f0b101c000b890301077f230041206b22042400200041046a22052802002106200028020c2107200441086a2208200141086a28020036020020042001290200370300200441106a41086a2209200241086a2802003602002004200229020037031020062007410c6c2202410c6a220a6a200620026a220120062f018e0220076b410c6c10391a200141086a20082802003602002001200429030037020020064184016a2201200a6a200120026a220220062f018e0220076b410c6c10391a200241086a200928020036020020022004290310370200200620062f018e0241016a3b018e0220064190026a2206200028020c22074102746a41086a2006200741016a22074102746a220620052802002f018e0220076b41027410391a200620033602000240200028020c220041016a220620052802002f018e0222034b0d0020004102744194026a21000340200641016a22072006490d012005280200220220006a2802002201200236028802200120063b018c02200041046a210020072106200720034d0d000b0b200441206a24000bd40c02117f017e230041c0076b220624000240200128020422072f01be03410a4b0d00200641f8006a41186a200241186a290000370300200641f8006a41106a200241106a290000370300200641f8006a41086a200241086a2900003703002006200229000037037820064188046a41206a200341206a29030037030020064188046a41186a200341186a29030037030020064188046a41106a200341106a29030037030020064188046a41086a200341086a29030037030020062003290300370388042001200641f8006a20064188046a2004108d01200041003a0000200041046a20012902003702002000410c6a200141086a290200370200200641c0076a24000f0b2001280208210820012802002109024041d0061001220a450d004100210b200a20064188046a41b803101e220a41003b01be03200a41003602b803200a41c0036a200641f8006a419003101e210c200641286a41186a220d20074198056a290000370300200641286a41106a220e20074190056a290000370300200641286a41086a220f20074188056a290000370300200620074180056a29000037032820064188046a41206a221020074190026a29030037030020064188046a41186a221120074188026a29030037030020064188046a41106a221220074180026a29030037030020064188046a41086a2213200741f8016a290300370300200620072903f00137038804200c200741a0056a200741be036a22142f0100221541796a2216410574101e1a200a20074198026a201641286c101e220c41a0066a220a200741bc066a2015417a6a2215410274101e1a201441063b0100200c20163b01be0302402015450d000340200a2802002216200b3b01bc032016200c3602b803200a41046a210a200b41016a220b2015490d000b0b200641f8006a41206a220b2010290300370300200641f8006a41186a220a2011290300370300200641f8006a41106a22162012290300370300200641f8006a41086a22152013290300370300200641d8006a41086a2210200f290300370300200641d8006a41106a2211200e290300370300200641d8006a41186a2212200d290300370300200620062903880437037820062006290328370358200641086a41186a2012290300370300200641086a41106a2011290300370300200641086a41086a201029030037030020062006290358370308200641286a41206a200b290300370300200d200a290300370300200e2016290300370300200f201529030037030020062006290378370328200620093602542006200c36025002400240200128020c220b41064b0d002006200736025c20062009360258200620083602602006200b360264200641f8006a41186a200241186a290000370300200641f8006a41106a200241106a290000370300200641f8006a41086a200241086a2900003703002006200229000037037820064188046a41206a200341206a29030037030020064188046a41186a200341186a29030037030020064188046a41106a200341106a29030037030020064188046a41086a200341086a2903003703002006200329030037038804200641d8006a200641f8006a20064188046a2004108d010c010b2006200c36025c200620093602582006200b41796a3602642006200641d0006a360260200641f8006a41186a200241186a290000370300200641f8006a41106a200241106a290000370300200641f8006a41086a200241086a2900003703002006200229000037037820064188046a41206a200341206a29030037030020064188046a41186a200341186a29030037030020064188046a41106a200341106a29030037030020064188046a41086a200341086a2903003703002006200329030037038804200641d8006a200641f8006a20064188046a2004108d010b20002006290308370001200041246a2009360200200041286a20073602002000412c6a2008360200200041386a2006290328370300200041096a200641086a41086a290300370000200041116a200641086a41106a290300370000200041196a200641086a41186a290300370000200041c0006a200641286a41086a290300370300200041c8006a200641286a41106a290300370300200041d0006a200641286a41186a290300370300200041d8006a200641c8006a29030037030020062903502117200041013a0000200041306a2017370200200641c0076a24000f0b101c000bb804010b7f230041d0006b22042400200041046a22052802002106200028020c2107200441086a41186a2208200141186a290000370300200441086a41106a2209200141106a290000370300200441086a41086a220a200141086a29000037030020042001290000370308200441286a41206a2201200241206a290300370300200441286a41186a220b200241186a290300370300200441286a41106a220c200241106a290300370300200441286a41086a220d200241086a29030037030020042002290300370328200620074105746a220241e0036a200241c0036a220e20062f01be0320076b41057410391a200241d8036a2008290300370000200241d0036a2009290300370000200241c8036a200a290300370000200e20042903083700002006200741286c6a220241286a200220062f01be0320076b41286c10391a200241206a2001290300370300200241186a200b290300370300200241106a200c290300370300200241086a200d29030037030020022004290328370300200620062f01be0341016a3b01be03200641a0066a2206200028020c22024102746a41086a2006200241016a22024102746a220620052802002f01be0320026b41027410391a200620033602000240200028020c220241016a220620052802002f01be0322034b0d00200241027441a4066a21020340200641016a22012006490d012005280200220020026a280200220720003602b803200720063b01bc03200241046a210220012106200120034d0d000b0b200441d0006a24000b8614010e7f230041d0006b220424004100210502404101417f100d2206417f460d002004410036020820044204370300200441386a41ae0d4103102a200441106a41b10d410f102a200441cc006a2207200441106a41086a220528020036020020042004290310370244200441106a41106a2208200441386a41106a22092903003703002005200441386a41086a220a290300370300200420042903383703102004106a2004280204210b2004280200220c2004280208220d4105746a220e2004290310370200200e4100360218200e41086a2005290300370200200e41106a2008290300370200200e411c6a41013602002004200d41016a220d360208200441386a41ae0d4103102a200441106a41c00d410f102a2007200528020036020020042004290310370244200820092903003703002005200a290300370300200420042903383703100240200d200b470d002004106a200441086a280200210d2004280200210c2004280204210b0b200c200d4105746a220e2004290310370200200e4100360218200e41106a2008290300370200200e41086a2005290300370200200e411c6a4102360200200441086a200d41016a220e360200200441386a41ae0d4103102a200441106a41cf0d410c102a2007200528020036020020042004290310370244200820092903003703002005200a290300370300200420042903383703100240200e200b470d002004106a200441086a280200210e2004280204210b2004280200210c0b200c200e4105746a2208200429031037020020084100360218200841106a200441106a41106a220d290300370200200841086a200441106a41086a22052903003702002008411c6a4103360200200441086a2207200e41016a220e360200200441386a41ae0d4103102a200441106a41db0d410a102a200441cc006a2209200528020036020020042004290310370244200d200441386a41106a220a2903003703002005200441386a41086a220f290300370300200420042903383703100240200e200b470d002004106a2007280200210e2004280200210c2004280204210b0b200c200e4105746a2208200429031037020020084100360218200841106a200d290300370200200841086a20052903003702002008411c6a41043602002007200e41016a2208360200200441386a41ae0d4103102a200441106a41e50d4106102a2009200528020036020020042004290310370244200d200a2903003703002005200f2903003703002004200429033837031002402008200b470d002004106a200441086a28020021082004280200210c0b200c20084105746a2205200429031037020020054101360218200541106a200441106a41106a220b290300370200200541086a200441106a41086a2903003702002005411c6a2006360200200441086a200841016a2205360200200b200241086a290000370300200441106a41186a200241106a290000370300200441306a200241186a2900003703002004200336021020042006360214200420022900003703184104210702400240410410012210450d00201020053600000240024002402005450d00200c20054105746a2111200441c0006a210341042107410421080340200441386a200c105120042802382105410121064100210b024020032802002202450d0020024100480d042002210b200210012206450d050b200620052002101e210a0240200428023c450d00200510020b200441386a200c410c6a220f105120042802382109024002400240200b20026b2003280200220d490d002002200d6a2105200b2106200a220e20026a2009200d101e1a200428023c0d010c020b2002200d6a22052002490d05200b4101742206200520052006491b22064100480d0520061001210e0240200b450d00200e450d07200e200a2006200b200b20064b1b101e210b200a1002200b20026a2009200d101e1a200428023c0d010c020b200e450d06200e20026a2009200d101e1a200428023c450d010b200910020b2003410036020020044201370338200c41186a2802002102200441386a104f2004280238220d2003280200220b6a21090240024002400240024002400240024020024101470d00200941023a00002003200b41016a2202360200200c411c6a280200210c200428023c220920026b41034b0d01200241046a220b2002490d0b2009410174220a200b200b200a491b220a4100480d0b200a1001210b2009450d02200b450d0c200b200d200a20092009200a4b1b101e1a200d10020c030b200941013a00002003200b41016a2202360200200c411c6a280200210c200428023c220920026b41034b0d00200241046a220b2002490d0a2009410174220a200b200b200a491b220a4100480d0a200a1001210b2009450d03200b450d0b200b200d200a20092009200a4b1b101e1a200d10020c040b200d210b0c050b200b450d090b2004200a36023c0c020b200b450d070b2004200a36023c0b2004200b3602380b200b20026a200c3600002003200241046a220c360200200428023c210a0240024002400240200620056b200c4f0d002005200c6a22022005490d072006410174220d20022002200d491b22094100480d0720091001210d2006450d01200d450d08200d200e20092006200620094b1b101e2106200e1002200620056a200b200c101e1a200a0d020c030b2005200c6a210220062109200e220d20056a200b200c101e1a200a0d010c020b200d450d06200d20056a200b200c101e1a200a450d010b200b10020b0240024002400240200720086b20024f0d00200820026a22052008490d0720074101742206200520052006491b22064100480d072007450d0120061001220b450d08200b201020062007200720064b1b101e210b2010100220062107200b221020086a200d2002101e1a20090d020c030b200820026a2105201020086a200d2002101e1a20090d010c020b20062107200610012210450d06201020086a200d2002101e1a2009450d010b200d10020b20052108200f41146a220c2011470d000c020b0b410421050b41052000200120102005200441106a100e210202402007450d00201010020b02402002417f460d00410121050240200241eb0d4104200441106a100f2202450d002002417d470d04410021050b200428020021030240200441086a2802002202450d00200241057421062003210203400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241206a2102200641606a22060d000b0b2004280204450d0420031002200441d0006a240020050f0b200428020021060240200441086a2802002202450d00200241057421052006210203400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241206a2102200541606a22050d000b0b02402004280204450d00200610020b200441d0006a240041000f0b1041000b101c000b41fc3a103b000b200441d0006a240020050bbe0701047f23004190016b220424000240024002400240024002400240024002402003450d0020022802000d0120034101460d0220022802100d0320034103490d0420022802200d0520022802042103200241146a2802002105200241246a2802002106200441186a4200370300200441106a4200370300200441086a42003703002004420037030002400240024002402001280204220720032004412010102202417e460d0020020d0a200441206a41186a200141206a290000370300200441206a41106a200141186a290000370300200441206a41086a200141106a290000370300200420012900083703202005450d01200441c0006a41186a4200370300200441c0006a41106a4200370300200441c0006a41086a42003703002004420037034020072006200441c0006a412010102202417e460d0320020d0c20012802002101412010012202450d0b2004200236028001200442203702840120044180016a41004120102720042802800120042802880122036a22022004290300370000200441e0006a41086a200341206a2203360200200241086a200441086a290300370000200241106a200441106a290300370000200241186a200441186a29030037000020042004290380013703602004200336028801412010012202450d0b2004200236028001200442203702840120044180016a41004120102720042802800120042802880122036a22022004290340370000200441f0006a41086a200341206a2203360200200241086a200441c0006a41086a290300370000200241106a200441c0006a41106a290300370000200241186a200441c0006a41186a290300370000200420042903800137037020042003360288012001200441206a200441e0006a200441f0006a1094010c020b2000410536020020044190016a24000f0b20012802002101412010012202450d092004200236024020044220370244200441c0006a4100412010272004280240200428024822036a2202200429030037000020044180016a41086a200341206a2203360200200241086a200441086a290300370000200241106a200441106a290300370000200241186a200441186a290300370000200420042903403703800120042003360248200441003602402001200441206a20044180016a200441c0006a1094010b2000410436020020044190016a24000f0b2000410536020020044190016a24000f0b41bc3441004100103c000b41ec3f103b000b41cc3441014101103c000b41ec3f103b000b41dc3441022003103c000b41ec3f103b000b41cc31103b000b101c000b41cc31103b000bc50301027f230041d0006b2204240002400240024002400240024002402003450d0020022802000d0120034101460d0220022802100d0320022802042103200241146a2802002102200441186a4200370300200441106a4200370300200441086a420037030020044200370300024002400240024002402001280204220520032004412010102203417e460d0020030d09200441206a41186a200141206a290000370300200441206a41106a200141186a290000370300200441206a41086a200141106a29000037030020042001290008370320200441c0006a2001280200200441206a2004412010950120042802402201450d0120042802442103200520022001200441c0006a41086a28020010112202417e460d0320020d0a2003450d02200110020c020b20004105360200200441d0006a24000f0b2005200241bd0e412010112202417e460d0220020d090b20004104360200200441d0006a24000f0b2000410536020002402003450d00200110020b200441d0006a24000f0b20004105360200200441d0006a24000f0b419c3441004100103c000b41ec3f103b000b41ac3441014101103c000b41ec3f103b000b41cc31103b000b41e431103b000b41e431103b000b861a05037f017e047f047e027f230041a0076b22042400024002400240024002400240024002400240024002400240024002402003450d0020022802000d0120034101460d0220022802100d0320034103490d0420022802200d0520022802042105200241146a2802002106200241246a3502002107410021022004410036020820044201370300024002402006450d0020044100200610272004280200200441086a220828020022096a210a024020064101460d00410021020340200a20026a41003a0000200241026a2103200241016a220b210220032006490d000b2009200b6a2109200a200b6a210a0b200a41003a00002008200941016a2202360200200428020021030c010b410121030b024002400240200128020420052003200210102206417e460d0020060d09200441e8036a2002412020024120491b22066a41004100412020066b2006411f4b1b10171a200441e8036a20032006101e1a2002411f4d0d0b200441106a41186a200441e8036a41186a290000370300200441106a41106a200441e8036a41106a290000370300200441106a41086a200441e8036a41086a290000370300200420042900e803370310200441306a41186a200141206a290000370300200441306a41106a200141186a290000370300200441306a41086a200141106a29000037030020042001290008370330200128020022022802002206417f460d0a2002200641016a360000200241046a220a200441306a1096012206450d012006280200450d01200641086a290300210c0c020b200041053602002004280204450d0f0c0e0b2002280210200441306a200241146a280200280214111400210c0b200220022802002206417f6a360000200c2007540d092006450d072002200636000002400240200a200441106a1096012206450d002006280200450d00200641086a290300210d0c010b2002280210200441106a200241146a280200280214111400210d0b20022002280200417f6a360000024002400240410810012206450d00200420063602e803200442083702ec03200441e8036a41004108102720042802e80320042802f00322066a42f3e885d3a3ec9bb73a3700002004200641086a3602f00320044188016a41086a20042802f003360200200420042903e80337038801412010012206450d00200420063602e803200442203702ec03200441e8036a41004120102720042802e803220a20042802f003220b6a22062004290330370000200641086a200441306a41086a290300370000200641106a200441306a41106a290300370000200641186a200441306a41186a2903003700002004200b41206a22063602f00320042802ec03210520044188016a20042802900120061027200428028801220b20042802900122096a200a2006101e1a2004200920066a22063602900102402005450d00200a10020b200428028c01210a4200210e200441e8036a41086a22054200370300200442003703e803200b2006200441e8036a100320044188016a41086a2005290300370300200420042903e80337038801024020044188016a411041d02d410041001000417f460d00200442003703e80320044188016a4110200441e8036a41084100100041016a41084d0d0220042903e803210e0b0240200a450d00200b10020b410810012206450d00200420063602e803200442083702ec03200441e8036a41004108102720042802e80320042802f00322066a42f3e885d3a3ec9bb73a3700002004200641086a3602f00320044188016a41086a20042802f003360200200420042903e80337038801412010012206450d00200420063602e803200442203702ec03200441e8036a41004120102720042802e803220a20042802f003220b6a22062004290310370000200641086a200441106a41086a290300370000200641106a200441106a41106a290300370000200641186a200441106a41186a2903003700002004200b41206a22063602f00320042802ec03210520044188016a20042802900120061027200428028801220b20042802900122096a200a2006101e1a2004200920066a22063602900102402005450d00200a10020b200428028c01210a4200210f200441e8036a41086a22054200370300200442003703e803200b2006200441e8036a100320044188016a41086a2005290300370300200420042903e80337038801024020044188016a411041d02d410041001000417f460d00200442003703e80320044188016a4110200441e8036a41084100100041016a41084d0d0320042903e803210f0b0240200a450d00200b10020b200e200f560d0d200d20077c220e200d580d0e41a00610012206450d002006200441e8036a41b803101e220641003b01be03200641003602b803200641c0036a20044188016a41e002101e1a200441d0006a41086a220a4200370300200441e4006a41c43d360200200420063602542004410036025020042002360260200441d0006a41047221020240200441306a200441106a41201006450d002004417f360250200441e8036a41186a2206200441306a41186a290300370300200441e8036a41106a2209200441306a41106a290300370300200441e8036a41086a200441306a41086a290300370300200420042903303703e803200420023602702004200a2802003602682004200428025436026c20044188016a200441e8006a200441e8036a1097014101210a20044188016a41106a280200210b20044188016a410c6a280200210820044188016a41086a2802002105200428028c01211002402004280288014101470d00200441e8006a41186a2006290300370300200441e8006a41106a2009290300370300200441e8006a41086a200441e8036a41086a290300370300200420042903e8033703684100210a0b41900210012206450d01200c20077d21072006200441e8036a418802101e220641003b018e02200641003602880202400240200a450d0020042006360288012004420037028c012005200b41286c6a2106200441e8036a20044188016a109801200441e8036a1099010c010b20044184046a200441f0006a2903003702002004418c046a200441f8006a29030037020020044194046a20044180016a290300370200200420053602ec03200420103602e803200420083602f0032004200b3602f4032004200441d0006a410c6a3602f803200420042903683702fc03200441a8016a420037030020044100360298012004420037038801200420063602a401200441e8036a20044188016a109a0121060b20064201370300200620073703082004417f360250200441e8036a41186a2206200441106a41186a290300370300200441e8036a41106a2209200441106a41106a290300370300200441e8036a41086a2208200441106a41086a290300370300200420042903103703e803200420023602702004200441d0006a41086a2802003602682004200428025436026c20044188016a200441e8006a200441e8036a1097014101210a20044188016a41106a280200210b20044188016a410c6a280200211020044188016a41086a2802002105200428028c01211102402004280288014101470d00200441e8006a41186a2006290300370300200441e8006a41106a2009290300370300200441e8006a41086a2008290300370300200420042903e8033703684100210a0b41900210012206450d012006200441e8036a418802101e220641003b018e02200641003602880202400240200a450d0020042006360288012004420037028c012005200b41286c6a2106200441e8036a20044188016a109801200441e8036a1099010c010b20044184046a200441f0006a2903003702002004418c046a200441f8006a29030037020020044194046a20044180016a290300370200200420053602ec03200420113602e803200420103602f0032004200b3602f4032004200441d0006a410c6a3602f803200420042903683702fc03200441a8016a420037030020044100360298012004420037038801200420063602a401200441e8036a20044188016a109a0121060b200642013703002006200e370308200441003602500b200441e8036a200441d0006a200441106a109b0102400240024020042802f0032206450d0020042802e803220a2006200441106a200441d0006a108e01450d010b200441d8006a290300210720042802542102024020042802ec03450d0020042802e80310020b2002450d0120012802002106200420073702ec03200420023602e8032006200441e8036a109c010c010b024020042802ec03450d00200a10020b20044188016a41086a200241086a2802003602002004200229020037038801200441e8036a20044188016a109d01200441e8036a109e010b2000410436020020042802040d0f0c100b101c000b41c1214133102d000b41c1214133102d000b41ec3341004100103c000b41ec3f103b000b41fc3341014101103c000b41ec3f103b000b418c3441022003103c000b41ec3f103b000b41cc31103b000b109f01000b41ec3f103b000b418c3c103b000b41a43c103b000b41bc3c103b000b200310020b200441a0076a24000b811a06047f017e047f017e037f057e230022042105200441c0086b4160712204240002400240024002400240024002400240024002400240024002400240024002400240024002402003450d0020022802000d0120034101460d0220022802100d0320034103490d0420022802200d0520022802042106200241146a2802002107200241246a3502002108410021022004410036020820044201370300024002402007450d0020044100200710272004280200200441086a2209280200220a6a210b024020074101460d00410021020340200b20026a41003a0000200241026a2103200241016a220c210220032007490d000b200a200c6a210a200b200c6a210b0b200b41003a00002009200a41016a2202360200200428020021030c010b410121030b024002400240200128020420062003200210102207417e460d0020070d09200441106a41186a200141206a290000370300200441106a41106a200141186a290000370300200441186a200141106a2900003703002004200129000837031020012802002207280200220b417f460d0a2007200b41016a360000200741046a200441106a109601220b450d01200b280200450d01200b41086a290300210d0c020b200041053602002004280204450d140c130b2007280210200441106a200741146a280200280214111400210d0b20072007280200417f6a360000200d2008540d08200441c8046a41186a220b4200370300200441c8046a41106a220c4200370300200441c8046a41086a22014200370300200442003703c80420032002200441c8046a1012200441e8016a41186a2206200b290300370300200441e8016a41106a220a200c290300370300200441e8016a41086a22092001290300370300200420042903c8043703e801200b2006290300370300200c200a29030037030020012009290300370300200420042903e8013703c80441201001220e450d0d2004200e3602e801200442203702ec01200441e8016a41004120102720042802e80120042802f001220f6a220e20042903c80437000020044180086a41086a2210200f41206a220f360200200e41086a2001290300370000200e41106a200c290300370000200e41186a200b290300370000200420042903e801370380082004200f3602f00120044180086a20102802004120102720102010280200220e41206a220f360200200e20042802800822106a220e2004290310370000200e41086a200441106a41086a290300370000200e41106a200441106a41106a290300370000200e41186a200441106a41186a290300370000200b4200370300200c420037030020014200370300200442003703c8042010200f200441c8046a10122006200b290300370300200a200c29030037030020092001290300370300200420042903c8043703e801200441306a41186a2006290300370300200441306a41106a200a290300370300200441306a41086a2009290300370300200420042903e8013703300240200428028408450d00201010020b200441306a200441106a41201006450d1041a0061001220b450d0d200b200441c8046a41b803101e220b41003b01be03200b41003602b803200b41c0036a200441e8016a41e002101e1a2004200b36025020044200370254200441306a200441106a41201006450d09200441a0016a41186a200441306a41186a290300370300200441a0016a41106a200441306a41106a290300370300200441a0016a41086a200441306a41086a290300370300200420042903303703a0012002417f4c0d0a024002402002450d0020021001220b0d010c0f0b4101210b0b200420023602cc042004200b3602c804200441003602d004200441c8046a410020021027200420042802d004220b20026a3602d004200b20042802c8046a20032002101e1a200441e8016a41086a220c20042802d004360200200420042903c8043703e80141900210012202450d0d200441d0006a41086a210b2002200441c8046a418802101e220241003b018e022002410036028802200420083703c801200442013703c001200420023602dc01200420042903e8013703d0012004200c2802003602d801200441c8046a41186a2202200441a0016a41186a290300370300200441c8046a41106a220c200441a0016a41106a290300370300200441c8046a41086a200441a0016a41086a290300370300200420042903a0013703c804200420042802543602b008200420042802503602b4082004200441d0006a3602b808200441e8016a200441b0086a200441c8046a109701200441a0086a41086a200441f4016a290200370300200420042902ec013703a008024020042802e8014101470d0020044180086a41186a2201200229030037030020044180086a41106a2202200c29030037030020044180086a41086a220c200441c8046a41086a2206290300370300200420042903c80437038008200441b0086a41086a200441a0086a41086a220a290300370300200420042903a0083703b0082006200a290300370300200441e4046a200c290300370200200441ec046a2002290300370200200441f4046a20012903003702002004200b3602d804200420042903a0083703c80420042004290380083702dc0420044188026a4200370300200441e8016a41186a20042903d801370300200420042903d0013703f801200420042903c8013703f001200420042903c0013703e801200441c8046a200441e8016a109a011a2004420237036041010d0d0c0c0b200441c8046a41086a200441a0086a41086a290300370300200420042903a0083703c80420042802cc0420042802d40441286c6a22022900102112200220042903d00137001020022900082113200220042903c80137000820022900002114200220042903c0013700002002290020211120024200370020200241186a22022900002115200220042903d8013700002004200b3602d8042004201237037020042013370368200420143703602004201537037820144202520d0b0c0c0b41bc3341004100103c000b41ec3f103b000b41cc3341014101103c000b41ec3f103b000b41dc3341022003103c000b41ec3f103b000b41cc31103b000b109f01000b41943d103b000b41ac3d103b000b1019000b024020042802702202450d002004280274450d00200210020b200420113702ec012004200428027c3602e801200441c8046a200441e8016a109801200441c8046a1099010b200441a0016a41186a220c200441106a41186a290300370300200441a0016a41106a2201200441106a41106a290300370300200441a0016a41086a2206200441106a41086a290300370300200420042903103703a00141900210012202450d002002200441c8046a418802101e220241003b018e0220024100360288022004200d20087d3703c801200442013703c001200441003602d001200420023602dc01200441c8046a41186a200c290300370300200441c8046a41106a2001290300370300200441c8046a41086a2006290300370300200420042903a0013703c804200420042802543602b008200420042802503602b4082004200441d0006a3602b808200441e8016a200441b0086a200441c8046a109701200441a0086a41086a200441f4016a290200370300200420042902ec013703a0080240024020042802e8014101470d0020044180086a41186a2202200441c8046a41186a29030037030020044180086a41106a220c200441c8046a41106a29030037030020044180086a41086a2201200441c8046a41086a2206290300370300200420042903c80437038008200441b0086a41086a200441a0086a41086a220a290300370300200420042903a0083703b0082006200a290300370300200441e4046a2001290300370200200441ec046a200c290300370200200441f4046a20022903003702002004200b3602d804200420042903a0083703c80420042004290380083702dc0420044188026a4200370300200441e8016a41186a20042903d801370300200420042903d0013703f801200420042903c8013703f001200420042903c0013703e801200441c8046a200441e8016a109a011a200442023703800141010d010c030b200441c8046a41086a200441a0086a41086a290300370300200420042903a0083703c80420042802cc0420042802d40441286c6a22022900102111200220042903d00137001020022900082114200220042903c8013700082002290000210d200220042903c0013700002002290020210820024200370020200241186a22022900002112200220042903d8013700002004200b3602d804200420113703900120042014370388012004200d370380012004201237039801200d4202520d020b20042802502202450d030c020b101c000b02402004280290012202450d00200428029401450d00200210020b200420083702ec012004200428029c013602e801200441c8046a200441e8016a109801200441c8046a10990120042802502202450d010b200420042902543702cc04200420023602c8042007200441c8046a109c010b200041043602002004280204450d010b200310020b200524000bd41003027f017e077f230041c0006b22042400024020010d0041d02d2100410021010b20044100360200024002400240024002400240200141034d0d002004200028000022053602002005ad2206421c88a70d012006420486a72207417f4c0d02024002402007450d002007100122080d010c070b410821080b20042005360204200420083602002004410036020802400240024002402005450d002001417c6a2101200041046a2107200441086a2109410021004100210a0340200441003a0030200441306a20072001410047220b101e1a2001450d0320042d0030417f6a220c41034b0d032001200b6b21012007200b6a210702400240024002400240024002400240200c0e0403010400030b20044200370330200441306a20072001410820014108491b220b101e1a200141074d0d0a2007200b6a2107200429033021064103210c0c010b20044200370330200441306a20072001410820014108491b220b101e1a200141074d0d092007200b6a2107200429033021064101210c0b200a41016a210a20002004280204470d040c030b20044100360230200441306a20072001410420014104491b220b101e1a200141034d0d072007200b6a21072004280230210d4100210c0c010b20044100360230200441306a20072001410420014104491b220b101e1a200141034d0d062007200b6a21072004280230210d4102210c0b200a41016a210a20002004280204470d010b200410800120092802002100200428020021080b2001200b6b2101200820004104746a220b200d360204200b200c360200200b41086a20063703002009200041016a2200360200200a2005490d000b20042802042107200428020022080d010c030b41002100410021072008450d020b20042002200820002003110700200441003602182004420137031020042802002101200441106a107e2004280210200428021822006a210a024020014105470d00200a41013a0000200441186a2201200041016a2200360200200441106a20004100102720012802002101200428021021000c070b200a41003a0000200441106a41086a200041016a22003602002004410036022820044201370320200441206a104f2004280220220b2004280228220a6a210c0240024020014104470d00200c41003a0000200441206a41086a200a41016a220a3602000c010b200c41013a0000200441206a41086a200a41016a36020020044100360238200442013703300240024002400240024002400240024002400240024002400240024002400240024002400240200141037122014101460d00024020014102460d0020014103470d02200441086a2903002106200441306a104f20042802302205200441306a41086a220b280200220c6a41043a0000200b200c41016a22013602002004280234220d20016b41074b0d03200141086a220a2001490d1a200d4101742209200a200a2009491b22094100480d1a20091001210a200d450d07200a450d1c200a20052009200d200d20094b1b101e1a200510020c080b20042802042102200441306a104f20042802302205200441386a220b280200220c6a41033a0000200b200c41016a22013602002004280234220d20016b41034b0d03200141046a220a2001490d19200d4101742209200a200a2009491b22094100480d1920091001210a200d450d09200a450d1b200a20052009200d200d20094b1b101e1a200510020c0a0b200441086a2903002106200441306a104f20042802302205200441306a41086a220b280200220c6a41023a0000200b200c41016a22013602002004280234220d20016b41074b0d03200141086a220a2001490d18200d4101742209200a200a2009491b22094100480d1820091001210a200d450d0b200a450d1a200a20052009200d200d20094b1b101e1a200510020c0c0b20042802042102200441306a104f20042802302205200441386a220b280200220c6a41013a0000200b200c41016a22013602002004280234220d20016b41034b0d03200141046a220a2001490d17200d4101742209200a200a2009491b22094100480d1720091001210a200d450d0d200a450d19200a20052009200d200d20094b1b101e1a200510020c0e0b2005210a0c050b2005210a0c070b2005210a0c090b2005210a0c0b0b200a450d140b200420093602342004200a3602300b200b200c41096a360200200a20016a20063700000c090b200a450d110b200420093602342004200a3602300b200b200c41056a360200200a20016a20023600000c060b200a450d0e0b200420093602342004200a3602300b200b200c41096a360200200a20016a20063700000c030b200a450d0b0b200420093602342004200a3602300b200b200c41056a360200200a20016a20023600000b200428023421092004280230210c02400240024002402004280224220d200441206a41086a28020022016b200441306a41086a280200220a4f0d002001200a6a220b2001490d0a200d4101742205200b200b2005491b22054100480d0a200d450d012004280220210220051001220b450d0c200b20022005200d200d20054b1b101e1a200210020c020b2004280220210b0c020b20051001220b450d0a0b200420053602242004200b3602200b200441286a220d2001200a6a360200200b20016a200c200a101e1a02402009450d00200c10020b200d280200210a2004280220210b0b2004280224210c200441106a2000200a1027200441186a22012001280200220d200a6a2201360200200d200428021022006a200b200a101e1a200c450d06200b10020c060b2004280204450d00200428020010020b41af1b41f000102d000b200420002001101e1a41af1b41f000102d000b105a000b105b000b1041000b2000ad4220862001ad84210602402007450d00200810020b200441c0006a240020060f0b101c000ba30501097f230041e0026b220424000240024020002802000d002000417f360000200441306a41186a2205200141186a290000370300200441306a41106a2206200141106a290000370300200441306a41086a2207200141086a290000370300200420012900003703302004200041046a3602182004200041086a28020036021020042000280204360214200441b8026a200441106a200441306a10970141012108200441b8026a41106a2802002109200441c4026a280200210a200441b8026a41086a280200210b20042802bc02210c024020042802b8024101470d00200441106a41186a2005290300370300200441106a41106a2006290300370300200441106a41086a200729030037030020042004290330370310410021080b41900210012201450d012001200441306a418802101e220141003b018e022001410036028802024002402008450d00200420013602b802200442003702bc02200b200941286c6a2101200441306a200441b8026a109801200441306a1099010c010b200441cc006a200441186a290300370200200441d4006a200441206a290300370200200441dc006a200441286a2903003702002004200b3602342004200c3602302004200a3602382004200936023c20042000410c6a36024020042004290310370244200441d8026a4200370300200441003602c802200442003703b802200420013602d402200441306a200441b8026a109a0121010b200441b8026a41086a200241086a280200360200200420022902003703b802200441306a41086a200341086a2802003602002004200329020037033020042001411c6a200441b8026a200441306a10d20102402004280200450d0020042802042201450d00200441086a280200450d00200110020b20004100360000200441e0026a24000f0b10c301000b101c000be60602097f017e230041206b22052400024002400240024020012802002206417f460d002001200641016a360000200141046a20021096012206450d02200628022021072006411c6a28020022082f018e022209450d01410f210a0c030b109f01000b4101210a0c010b4116210a0b034002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200a0e170a090c0d160e0f1314151012110708000102030406050b0b0b20082009410c6c6a210b41002109200821064110210a0c280b20032006280200200641086a280200220c2004200c2004491b1006220d450d174111210a0c270b200d411e76417f73410271417f6a220c450d254112210a0c260b200c4101470d194113210a0c250b200941016a21092006410c6a2206200b470d170c160b4100417f4101200c20044b1b200c2004461b220c0d214114210a0c230b200541013a000c20052d000c4101710d11410d210a0c220b2007450d1e410e210a0c210b2007417f6a2107200820094102746a4190026a28020022082f018e0222090d0e4101210a0c200b200541003a000c20052d000c410171450d140c150b2008418e026a2f010021090c0f0b20002001280210200220032004200141146a28020028020c1113000c190b20082009410c6c6a22064184016a2802002204450d134103210a0c1c0b2006418c016a2802002206417f4c0d134105210a0c1b0b2006450d134106210a0c1a0b2006100122090d13410a210a0c190b101c000b410021090c120b410121094107210a0c160b200520063602142005200936021020054100360218200541106a41002006102720052005280218220c20066a360218200c200528021022096a20042006101e1a2005290214210e4108210a0c150b2000200e370204200020093602004109210a0c140b20012001280200417f6a360000200541206a24000f0b1019000b410f210a0c110b4102210a0c100b4115210a0c0f0b4101210a0c0e0b4100210a0c0d0b4110210a0c0c0b4101210a0c0b0b410d210a0c0a0b4102210a0c090b410c210a0c080b4104210a0c070b410b210a0c060b4107210a0c050b4108210a0c040b4109210a0c030b4116210a0c020b4112210a0c010b4114210a0c000b0bbe0301087f230041106b220224002000280204210302400240200028020022042f01be0322050d00410a21060c010b410421060b037f024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020060e0c050a0800010203040709060b0b0b2003417f6a2103200420054102746a41a0066a28020022042f01be032205450d0b410421060c150b20054105742107200441c0036a210041002105410521060c140b20012000412010062208450d0b410621060c130b4100210920084100480d11410721060c120b200041206a2100200541016a2105200741606a22070d0c410021060c110b200441be036a2f01002105200241003a000c20022d000c410171450d090c0a0b41002109410821060c0f0b200220093a000c20022d000c4101710d0a410221060c0e0b20030d0b0c0a0b200241013a000c20022d000c410171450d03410121060c0c0b200241106a24002004200541286c6a0f0b200241106a240041000f0b410a21060c090b410221060c080b410921060c070b410221060c060b410121060c050b410521060c040b410121060c030b410b21060c020b410321060c010b410821060c000b0bad04010c7f230041106b220324002001280208210420012802002105200141086a2106200141046a210702400240200128020422082f01be0322090d00410a210a0c010b4104210a0b03400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200a0e0c050a0800010203040709060b0b0b20012005417f6a2205360200200620043602002007200820094102746a41a0066a280200220836020020082f01be032209450d0b4104210a0c150b2009410574210b200841c0036a210c410021094105210a0c140b2002200c41201006220d450d0b4106210a0c130b4100210e200d4100480d114107210a0c120b200c41206a210c200941016a2109200b41606a220b0d0c4100210a0c110b200841be036a2f01002109200341003a000c20032d000c410171450d090c0a0b4100210e4108210a0c0f0b2003200e3a000c20032d000c4101710d0a4102210a0c0e0b20050d0b0c0a0b200341013a000c20032d000c410171450d034101210a0c0c0b2000200536020420004100360200200041086a20083602002000410c6a2004360200200041106a2009360200200341106a24000f0b20004201370200200041086a20083602002000410c6a2004360200200041106a2009360200200341106a24000f0b410a210a0c090b4102210a0c080b4109210a0c070b4102210a0c060b4101210a0c050b4105210a0c040b4101210a0c030b410b210a0c020b4103210a0c010b4108210a0c000b0bb20301097f23002102200141046a280200210320012802082104200241306b220241186a2205200128020022063602002002411c6a2207410036020020022003360214200220034100472208360210024002402003450d002003417f6a2101200241106a41047221092006210a03402005200a28029002220a3602002007410036020020022001360214200220014100473602102001417f6a2201417f470d000c020b0b200241106a41047221090b200241086a200941086a28020036020020022009290200370300200241106a41086a220a20063602002002411c6a22054100360200200220033602142002200836021002402003450d002003417f6a21010340200a200620062f018e024102746a4190026a28020022063602002005410036020020022001360214200220014100473602102001417f6a2201417f470d000b0b200241106a41086a28020022012f018e0221062002411c6a280200210a200228021421052000410036020c20002005360210200041146a2001360200200041186a200a3602002000411c6a200636020020002004360220200041086a200241086a280200360200200020022903003702000bf00202067f027e230041206b22012400200141086a200010ca01024020012802082202450d00200141186a2103200141146a2104034020032802002105200428020021060240200128020c450d00200210020b02402006450d002005450d00200610020b200141086a200010ca01200128020822020d000b0b2000280208210320002802002102024002400240024020002802042206280288022205450d00200632018c0221072001200536020c2001200241016a2202360208200120074220862003ad842207370310200610022005450d020c010b2003ad210741002105200610024100450d010b024002402005280288022206450d00200532018c0221082001200636020c2001200241016a36020820012008422086200742ffffffff0f83843703102005100220060d010c020b41002106200510024100450d010b2006210503402006280288022206450d02200510022006210520060d000b0b200141206a24000f0b20051002200141206a24000bcc0b01117f230041c0076b2202240020002802102203200328020041016a360200200241d8006a41086a200041086a29020037030020022000290200370358200241206a41186a22032000412c6a290000370300200241206a41106a2204200041246a290000370300200241206a41086a22052000411c6a29000037030020022000290014370320200241f8006a41206a200141206a290300370300200241f8006a41186a200141186a290300370300200241f8006a41106a200141106a290300370300200241f8006a41086a200141086a2903003703002002200129030037037820024188046a200241d8006a200241206a200241f8006a108801024002400240024002400240024020022d008804450d00200241086a20024191046a290000370300200241106a20024199046a290000370300200241186a200241a1046a2900003703002005200241c8046a2903003703002004200241d0046a2903003703002003200241d8046a290300370300200241206a41206a200241e0046a29030037030020022002290089043703002002200241c0046a290300370320200241bc046a2802002106200241b8046a280200210420022802e804210720024188046a412c6a280200210320024188046a41246a2802002100200241b0046a28020022012802b8032205450d0120012f01bc0321082002200536027c2002200041016a2209360278200220033602800120022008360284014100450d020c030b20024188046a41106a280200210020024188046a41086a2802002101200241c0076a24002001200041286c6a0f0b2002200136027c2002200036027820022003360280012003210941010d010b200241c0046a210020024188046a4101722101200241d4006a210a200241bc046a210b200241b8046a210c200241b4046a210d200241b0046a210e200241ac046a210f0340200241c8006a41086a2003360200200a20083602002002200536024c20022009360248200241d8006a41186a200241186a2203290300370300200241d8006a41106a200241106a2205290300370300200241d8006a41086a200241086a220829030037030020022002290300370358200241f8006a41206a200241206a41206a2209290300370300200241f8006a41186a200241206a41186a2210290300370300200241f8006a41106a200241206a41106a2211290300370300200241f8006a41086a200241206a41086a22122903003703002002200229032037037820024188046a200241c8006a200241d8006a200241f8006a20042006108c0120022d008804450d0302402008200141086a2900003703002005200141106a2900003703002003200141186a2900003703002012200041086a2903003703002011200041106a2903003703002010200041186a2903003703002009200041206a2903003703002002200129000037030020022000290300370320200c2802002104200d2802002103200e28020022082802b8032205450d00200b2802002106200f28020041016a210920082f01bc0321080c010b0b41d00610012200450d030c010b2009210341d00610012200450d020b200020024188046a41b803101e220041003b01be03200041003602b803200041c0036a200241f8006a419003101e2101200020032802003602a006200320003602002003200328020441016a36020420002802a006220341003b01bc03200320003602b803200120002f01be0322034105746a22012002290300370000200141186a200241186a290300370000200141106a200241106a290300370000200141086a200241086a2903003700002000200341286c6a220141106a200241206a41106a290300370300200141086a200241206a41086a29030037030020012002290320370300200141206a200241206a41206a290300370300200141186a200241206a41186a290300370300200041a0066a200341016a22014102746a2004360200200020002f01be0341016a3b01be03200420013b01bc03200420003602b8030b200241c0076a240020070f0b101c000bf10101047f230041106b220324000240024020012802002204417f460d002001200441016a3600000240024002400240200141046a20021096012204450d0020042802102205450d0020042802182202417f4c0d052002450d012002100122040d02101c000b200020012802102002200141146a2802002802101106000c020b410121040b200320023602042003200436020020034100360208200341002002102720032003280208220420026a3602082004200328020022066a20052002101e1a20002003290204370204200020063602000b20012001280200417f6a360000200341106a24000f0b109f01000b1019000b890b07027f017e107f017e047f017e027f230041f0026b22022400024020002802000d002000417f36000020024180016a41086a2203200141086a2802003602002002200129020037038001200220024180016a109d01200241286a41206a200241206a280200360200200241286a41186a200241186a290300370300200241286a41106a200241106a290300370300200241286a41086a200241086a2903003703002002200229030037032820024180016a200241286a10c801024020022903a00122044202510d002000410c6a2105200041046a2106200241f8016a411c6a210720024180016a41146a2108200241bc016a2109200241a0026a410c6a210a20024180016a41286a210b200241b0016a210c200241b4016a210d200241b8016a210e20024180016a41206a210f0340200241e0006a41186a220120024180016a41186a2210290300370300200241e0006a41106a221120024180016a41106a2212290300370300200241e0006a41086a22132003290300370300200241d0006a41086a2214200941086a280200360200200220022903800137036020022009290200370350200b2903002115200c2802002116200d2802002117200e2802002118200241c8016a41086a22192014280200360200200220022903503703c8012010200129030037030020122011290300370300200320132903003703002002200229036037038001200241b8026a41086a220120063602002002200041086a2802003602b802200220062802003602bc02200241f8016a200241b8026a20024180016a1097010240024020022802f8014101470d00200241d8016a41086a22012003290300370300200241d8016a41106a22112012290300370300200241d8016a41186a2213201029030037030020022002290380013703d80120022902fc01211a2003200241f8016a410c6a29020037030020122005360200200820022903d801370200200841086a2001290300370200200841106a2011290300370200200841186a20132903003702002002201a37038001200241f8016a41086a2015370300200241f8016a41106a2016360200200241f8016a41146a2017360200200241f8016a41186a2018360200200720022903c801370200200741086a2019280200360200200220043703f80120024180016a200241f8016a109a011a0c010b200241f8016a41086a2214280200200241f8016a41106a221b28020041286c6a211102402004500d0020112004370300201120153703080b024002402016450d00201141106a211302402011280210221c450d00201341046a280200450d00201c10020b201320173602042013201636020020112018360218410121130c010b410021130b20032019280200360200200220022903c80137038001200241f8016a20024180016a109801200f200241f8016a41206a2802003602002010200241f8016a41186a2903003703002012201b29030037030020032014290300370300200220022903f80137038001200241b8026a20024180016a10ca01024020022802b802450d002011411c6a21100340200241a0026a41106a200241b8026a41106a290300370300200241a0026a41086a22122001290300370300200220022903b8023703a002200241e0026a41086a2012280200360200200220022903a0023703e0022001200a41086a2802003602002002200a2902003703b802200241d0026a2010200241e0026a200241b8026a10d201024020022802d002450d0020022802d4022212450d00200241d0026a41086a280200450d00201210020b200241b8026a20024180016a10ca0120022802b8020d000b0b20024180016a1099012013201645720d002017450d00201610020b20024180016a200241286a10c801200f29030022044202520d000b0b200241286a109e0120004100360000200241f0026a24000f0b10c301000bb20301097f23002102200141046a280200210320012802082104200241306b220241186a2205200128020022063602002002411c6a2207410036020020022003360214200220034100472208360210024002402003450d002003417f6a2101200241106a41047221092006210a03402005200a2802a006220a3602002007410036020020022001360214200220014100473602102001417f6a2201417f470d000c020b0b200241106a41047221090b200241086a200941086a28020036020020022009290200370300200241106a41086a220a20063602002002411c6a22054100360200200220033602142002200836021002402003450d002003417f6a21010340200a200620062f01be034102746a41a0066a28020022063602002005410036020020022001360214200220014100473602102001417f6a2201417f470d000b0b200241106a41086a28020022012f01be0321062002411c6a280200210a200228021421052000410036020c20002005360210200041146a2001360200200041186a200a3602002000411c6a200636020020002004360220200041086a200241086a280200360200200020022903003702000bc70302077f027e23004190016b220124002001200010c801024020012903204202510d00200141c8006a4104722102200141386a2103200141346a2104200141306a2105200141206a21060340200141c8006a41086a200341086a29030037030020012003290300370348024020052802002207450d002004280200450d00200710020b20014180016a41086a200241086a2802003602002001200229020037038001200141d8006a20014180016a109801200141d8006a1099012001200010c80120062903004202520d000b0b20002802082105200028020021070240024002400240200028020422022802b8032203450d0020023201bc032108200120033602042001200741016a2207360200200120084220862005ad842208370308200210022003450d020c010b2005ad210841002103200210024100450d010b0240024020032802b8032202450d0020033201bc032109200120023602042001200741016a36020020012009422086200842ffffffff0f83843703082003100220020d010c020b41002102200310024100450d010b20022103034020022802b8032202450d02200310022002210320020d000b0b20014190016a24000f0b2003100220014190016a24000b080041ec3a1054000b950301067f230041106b22022400200241003a000b2002410b6a20012802002203200128020422044100472205101e1a2001200420056b22063602042001200320056a22053602000240024002400240024002402004450d0020022d000b2204450d0120044101470d022002410036020c2002410c6a20052006410420064104491b2204101e1a200141046a200620046b3602002001200520046a360200200641034d0d03200041046a200228020c360200200041023a0000200241106a24000f0b200041033a0000200241106a24000f0b200110212203450d0320022003360204200141046a22062802002104200241003a000b2002410b6a2001280200220720044100472205101e1a2006200420056b3602002001200720056a3602002004450d0220022d000b220141034f0d02200020013a0001200041013a0000200041046a2003360200200241106a24000f0b200041033a0000200241106a24000f0b200041033a0000200241106a24000f0b200041033a0000200241046a1022200241106a24000f0b200041033a0000200241106a24000bc905020f7f037e23004180016b22022400200241e0006a10302002280260220320022802681031210402402002280264450d00200310020b200241003602082002420137030020024100200410860120022802082105024002402004450d00200228020020054105746a2103200241306a41086a2106200241106a41186a2107200241106a41106a2108410021090340200241306a200910320240024002402002280230220a2006280200220b41d02d410041001000417f470d002007420037030020084200370300200241106a41086a420037030020024200370310200941016a210920022802340d010c020b200241e0006a41186a220c4200370300200241e0006a41106a220d4200370300200241e0006a41086a220e420037030020024200370360200a200b200241e0006a412041001000220b417f460d04200b411f4d0d04200241c0006a41186a220b200c290300370300200241c0006a41106a220f200d290300370300200241c0006a41086a2210200e29030037030020022002290360370340200c200b290300370300200d200f290300370300200e201029030037030020022002290340370360200b200c2903002211370300200f200d29030022123703002010200e2903002213370300200241106a41086a2013370300200820123703002007201137030020022002290360221137034020022011370310200941016a21092002280234450d010b200a10020b20032002290310370000200341186a2007290300370000200341106a2008290300370000200341086a200241106a41086a290300370000200341206a210320092004490d000b200520096a21050b200241086a2005360200200241c0006a41086a200536020020022002290300370340200241e0006a200241c0006a10a2012002350268422086200235026084211102402002280244450d00200228024010020b20024180016a240020110f0b41eb1a4133102d000bee0201077f230041206b22022400200141086a28020021032002410036021820024201370310200241106a4100410410272002280210200228021822046a20033600002002200441046a360218200241086a2205200228021836020020022002290310370300024002402003450d0020012802002101200341057421060340412010012203450d022002200336021020024220370214200241106a410041201027200241106a41086a22032003280200220441206a22033602002004200228021022076a22042001290000370000200441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a2900003700002002280214210420022005280200200310272002280200200528020022086a20072003101e1a2005200820036a36020002402004450d00200710020b200141206a2101200641606a22060d000b0b20002002290300370200200041086a2005280200360200200241206a24000f0b101c000bf80101017f23004180026b22022400024002402001450d00200220003602080c010b200241d02d360208410021010b2002200136020c20024188016a200241086a101d0240200228029001450d00200241106a20024188016a41f800101e1a20024188016a200241106a41f800101e1a20024188016a2002419c016a200241dc016a10a401024020024198016a2802002200450d0020022802900121012000410c6c210003400240200141046a280200450d00200128020010020b2001410c6a2101200041746a22000d000b0b024020024194016a280200450d0020024190016a28020010020b20024180026a240042010f0b4184351054000ba11903017f017e237f230041900d6b220324002003200029030022043703f00c200341106a41086a220042003703002003420037031041d12d4107200341106a1003200341086a220520002903003703002003200329031037030020034110200341f00c6a41081004200042003703002003420037031041d82d4107200341106a10032005200029030037030020032003290310370300200341102001412010040240024002400240410710012200450d002003200036021020034207370214200341106a4100410710272003280210200328021822056a220041002800c72d360000200341f00c6a41086a200541076a2205360200200041046a41002f00cb2d3b0000200041066a41002d00cd2d3a0000200320032903103703f00c20032005360218410810012200450d002003200036021020034208370214200341106a41004108102720032802102205200328021822006a2004427f7c3700002003200041086a220036021820032802142106200341f00c6a20032802f80c2000102720032802f00c220720032802f80c22086a20052000101e1a2003200820006a22003602f80c02402006450d00200510020b20032802f40c2105200341106a41086a220642003703002003420037031020072000200341106a1003200341086a2006290300370300200320032903103703002003411020014120100402402005450d00200710020b200341106a41086a220042003703002003420037031041df2d4107200341106a1003200341086a220120002903003703002003200329031037030020034110200241201004200042003703002003420037031041d12d4107200341106a100320012000290300370300200320032903103703002003411041d02d410041001000417f460d01200342003703100240024020034110200341106a41084100100041016a41084d0d0020032903104200510d04200341106a41086a220042003703002003420037031041d12d4107200341106a1003200341086a2000290300370300200320032903103703002003411041d02d410041001000417f460d052003420037031020034110200341106a41084100100041016a41084d0d012003290310210441002108200341106a410041e00c10171a2004427f7c2104410021094100210a4100210b4100210c4100210d4100210e4100210f410021104100211141002112410021134100211441002115410021164100211741002118410021194100211a4100211b4100211c4100211d4100211e4100211f4100212041002121410021224100212341002124410021254100212641002102410021270340200341f00c6a42002004427f7c2004501b220410a801200341106a202722004103704105746a220141186a200341f00c6a41186a290200370000200141106a200341f00c6a41106a290200370000200141086a200341f00c6a41086a290200370000200120032902f00c370000200041016a21274100210141002107024003402000200041036e2205417d6c6a4102470d01200341106a20016a220041df006a2d000022022000411f6a2d000022067120022006722000413f6a2d000071722108200041de006a2d000022022000411e6a2d000022067120022006722000413e6a2d000071722109200041dd006a2d000022022000411d6a2d000022067120022006722000413d6a2d00007172210a200041dc006a2d000022022000411c6a2d000022067120022006722000413c6a2d00007172210b200041db006a2d000022022000411b6a2d000022067120022006722000413b6a2d00007172210c200041da006a2d000022022000411a6a2d000022067120022006722000413a6a2d00007172210d200041d9006a2d00002202200041196a2d00002206712002200672200041396a2d00007172210e200041d8006a2d00002202200041186a2d00002206712002200672200041386a2d00007172210f200041d7006a2d00002202200041176a2d00002206712002200672200041376a2d000071722110200041d6006a2d00002202200041166a2d00002206712002200672200041366a2d000071722111200041d5006a2d00002202200041156a2d00002206712002200672200041356a2d000071722112200041d4006a2d00002202200041146a2d00002206712002200672200041346a2d000071722113200041d3006a2d00002202200041136a2d00002206712002200672200041336a2d000071722114200041d2006a2d00002202200041126a2d00002206712002200672200041326a2d000071722115200041d1006a2d00002202200041116a2d00002206712002200672200041316a2d000071722116200041d0006a2d00002202200041106a2d00002206712002200672200041306a2d000071722117200041cf006a2d000022022000410f6a2d000022067120022006722000412f6a2d000071722118200041ce006a2d000022022000410e6a2d000022067120022006722000412e6a2d000071722119200041cd006a2d000022022000410d6a2d000022067120022006722000412d6a2d00007172211a200041cc006a2d000022022000410c6a2d000022067120022006722000412c6a2d00007172211b200041cb006a2d000022022000410b6a2d000022067120022006722000412b6a2d00007172211c200041ca006a2d000022022000410a6a2d000022067120022006722000412a6a2d00007172211d200041c9006a2d00002202200041096a2d00002206712002200672200041296a2d00007172211e200041c8006a2d00002202200041086a2d00002206712002200672200041286a2d00007172211f200041c7006a2d00002202200041076a2d00002206712002200672200041276a2d000071722120200041c6006a2d00002202200041066a2d00002206712002200672200041266a2d000071722121200041c5006a2d00002202200041056a2d00002206712002200672200041256a2d000071722122200041c4006a2d00002202200041046a2d00002206712002200672200041246a2d000071722123200041c3006a2d00002202200041036a2d00002206712002200672200041236a2d000071722124200041c2006a2d00002202200041026a2d00002206712002200672200041226a2d000071722125200041c1006a2d00002202200041016a2d00002206712002200672200041216a2d000071722126200041c0006a2d0000220220002d00002206712002200672200041206a2d000071722102200141800c460d01200341106a20012005410574200541036e41e0006c6b6a6a220041e1006a20263a0000200041e0006a20023a0000200041e2006a20253a0000200041e3006a20243a0000200041e4006a20233a0000200041e5006a20223a0000200041e6006a20213a0000200041e7006a20203a0000200041e8006a201f3a0000200041e9006a201e3a0000200041ea006a201d3a0000200041eb006a201c3a0000200041ec006a201b3a0000200041ed006a201a3a0000200041ee006a20193a0000200041ef006a20183a0000200041f0006a20173a0000200041f1006a20163a0000200041f2006a20153a0000200041f4006a20133a0000200041f3006a20143a0000200041f5006a20123a0000200041f6006a20113a0000200041f7006a20103a0000200041f8006a200f3a0000200041f9006a200e3a0000200041fa006a200d3a0000200041fb006a200c3a0000200041fc006a200b3a0000200041fd006a200a3a0000200041fe006a20093a0000200041ff006a20083a0000200141e0006a210120052100200741016a22074111490d000b0b202741d100470d000b200320263a00f10c200320023a00f00c200320253a00f20c200320243a00f30c200320233a00f40c200320223a00f50c200320213a00f60c200320203a00f70c2003201f3a00f80c2003201e3a00f90c2003201d3a00fa0c2003201c3a00fb0c2003201b3a00fc0c2003201a3a00fd0c200320193a00fe0c200320183a00ff0c200320173a00800d200320163a00810d200320153a00820d200320133a00840d200320143a00830d200320123a00850d200320113a00860d200320103a00870d2003200f3a00880d2003200e3a00890d2003200d3a008a0d2003200c3a008b0d2003200b3a008c0d2003200a3a008d0d200320093a008e0d200320083a008f0d200341106a41086a220042003703002003420037031041e62d4107200341106a1003200341086a220120002903003703002003200329031037030020034110200341f00c6a41201004200341003602f00c200042003703002003420037031041ed2d4107200341106a1003200120002903003703002003200329031037030020034110200341f00c6a41041004200341900d6a24000f0b41c1214133102d000b41c1214133102d000b101c000b41f4214122102d000b4184c200103b000b41f4214122102d000ba80601057f230041d0096b22022400024002402001450d00200220003602080c010b200241d02d360208410021010b2002200136020c200241a0066a200241086a10200240024020022d00a8064107460d00200241106a200241a0066a418003101e1a20024190036a200241106a418003101e1a20024190066a20024190036a1026200241a0066a41086a22014200370300200242003703a00641ed2d4107200241a0066a1003200241b0096a41086a2001290300370300200220022903a0063703b009200241b0096a411041d02d410041001000417f460d01200241003602a00602400240200241b0096a4110200241a0066a41044100100041016a41044d0d0020022802a0062103200241a0096a41086a20024190066a41086a28020036020020022002290390063703a009410710012201450d01200220013602a006200242073702a406200241a0066a41004107102720022802a00620022802a80622006a220141002800e02e360000200241b0096a41086a200041076a2200360200200141046a41002f00e42e3b0000200141066a41002d00e62e3a0000200220022903a0063703b009200220003602a806410410012201450d01200220013602a006200242043702a406200241a0066a41004104102720022802a006220020022802a80622016a20033600002002200141046a22013602a80620022802a4062104200241b0096a20022802b8092001102720022802b009220320022802b80922056a20002001101e1a2002200520016a22053602b80902402004450d00200010020b20022802b4092100200241c0096a200241a0096a105120022802c809210420022802c0092101200241a0066a41086a22064200370300200242003703a00620032005200241a0066a1003200241b0096a41086a2006290300370300200220022903a0063703b009200241b0096a4110200120041004024020022802c409450d00200110020b02402000450d00200310020b024020022802a409450d0020022802a00910020b200241a0066a20024190036a418003101e1a200241a0066a10a601200241d0096a240042010f0b41c1214133102d000b101c000b4184351054000b41f4214122102d000bec0e04037f017e037f017e230041a0086b2201240020014180036a2000418003101e1a200141386a4200370300200141306a4200370300200141286a4200370300200141206a4200370300200141186a4200370300200141106a4200370300200141086a42003703002001420037030002400240024002400240200141c0056a200141c0001006450d00200141a0056a21000c010b20014188066a41186a420037030020014188066a41106a420037030020014188066a41086a42003703002001420037038806200141a0056a220020014188066a41201006450d010b2001410036029006200142013703880620014188066a41004120102720012802880620012802900622026a22032000290000370000200341186a200041186a290000370000200341106a200041106a290000370000200341086a200041086a2900003700002001200241206a220036029006200129038003210420014188066a20004108102720012802880620012802900622006a20043700002001200041086a220236029006200120014180036a41086a10282001280200210320014188066a20022001280208220010272001200020012802900622056a220636029006200520012802880622026a20032000101e1a02402001280204450d00200310020b200128028c06210020022006200141c0056a200141a0056a1015210302402000450d00200210020b200120014180036a418003101e1a20030d010c020b200120014180036a418003101e1a0c010b41bc3a103b000b20014180036a2001418003101e1a200141186a4200370300200141106a4200370300200141086a420037030020014200370300024002400240024002400240024002400240200141a0056a2200200141201006450d00200010c001200129038003520d06200010c0012104410710012203450d04200120033602002001420737020420014100410710272001280200200128020822026a220341002800d92e36000020014188066a41086a200241076a2202360200200341046a41002f00dd2e3b0000200341066a41002d00df2e3a0000200120012903003703880620012002360208412010012203450d04200442017c21042001200336020020014220370204200141004120102720012802002202200128020822056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002001200541206a22033602082001280204210620014188066a20012802900620031027200128028806220520012802900622076a20022003101e1a2001200720036a22073602900602402006450d00200210020b200128028c0621022001200437038006200141086a2203420037030020014200370300200520072001100320014188066a41086a22062003290300370300200120012903003703880620014188066a411020014180066a4108100402402002450d00200510020b200010432104200342003703002001420037030041bf2041072001100320062003290300370300200120012903003703880620014188066a411041d02d410041001000417f460d072001420037030020014188066a4110200141084100100041016a41084d0d02200420012903002208540d08410810012203450d04200120033602002001420837020420014100410810272001280200200128020822036a42f3e885d3a3ac98b63a3700002001200341086a36020820014188066a41086a20012802083602002001200129030037038806412010012203450d04200420087d21042001200336020020014220370204200141004120102720012802002202200128020822056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002001200541206a22003602082001280204210320014188066a20012802900620001027200128028806220520012802900622066a20022000101e1a2001200620006a22003602900602402003450d00200210020b200128028c0621022001200437038006200141086a2203420037030020014200370300200520002001100320014188066a41086a2003290300370300200120012903003703880620014188066a411020014180066a4108100420014188066a2103200121002002450d01200510020c010b2001210020014188066a21030b200120014180036a41c002101e22014188066a200141086a419802101e1a20014188066a200141a0026a10c101200041086a220242003700002000420037000041ed2d410720001003200341086a2002290000370000200320002900003700002003411041d02d410041001000417f460d032001410036020020034110200141044100100041016a41044d0d012001200128020041016a36028006200041086a220242003700002000420037000041ed2d410720001003200341086a2002290000370000200320002900003700002003411020014180066a41041004200141a0086a24000f0b41c1214133102d000b41c1214133102d000b101c000b41f4214122102d000b41d43a103b000b41f4214122102d000b41fc3c103b000bc51505047f017e027f017e027f23004190096b22022400024002402001450d00200220003602000c010b200241d02d360200410021010b20022001360204200241f0056a2002101d20024180066a280200210320022802fc05210420022802f805210520022903f0052106200241f8016a20024184066a41e400101e1a024002400240024002400240024002402005450d00200241f0006a200241f8016a41e400101e1a200241f8046a200241f0006a41e400101e1a200241003602f005200241f0056a2002280200220720022802042201410420014104491b2200101e1a2002200120006b3602042002200720006a3602000240200141034d0d0020022802f0052208ad4280037e2209422088a70d082009a72201417f4c0d07024002402001450d002001100122070d01101c000b410821070b2002200836020c20022007360208410021012002410036021002402008450d00200241f0056a41086a210a410021000340200241f0056a2002102002400240200a2d00004107460d00200041016a2100200241f8016a200241f0056a418003101e1a2001200228020c470d01200241086a106c200241086a41086a2802002101200228020821070c010b02402001450d0020014180036c2100200741186a210103400240200141706a2d00002208411d74411d75417f4a0d000240024020084105460d0020084104470d01200141786a2d00004101470d022001417c6a220828020010382008280200100220014180036a2101200041807d6a22000d030c040b200141786a2d00004101470d012001280200450d012001417c6a280200100220014180036a2101200041807d6a22000d020c030b200141746a2d00004101470d00200141786a220828020010382008280200100220014180036a2101200041807d6a22000d010c020b20014180036a2101200041807d6a22000d000b0b200228020c450d03200710020c030b200720014180036c6a200241f8016a418003101e1a200241086a41086a200141016a220136020020002008490d000b0b2007450d00200229020c2109200241f0056a200241f8046a41e400101e1a2005450d01200241086a200241f0056a41e400101e1a200241fc006a200436020020024180016a2003360200200220053602782002200637037020024184016a200241086a41e400101e2101200241ec016a2009370200200220073602e801200241f0006a2001200241c4016a220310a40120022903702206500d06200241f0056a2006427f7c10a801200241f0056a2001412010060d06200241e8016a2802002100200241f0016a28020021012002410036028005200242043703f804200241f8046a20014180036c22084180036d108401200228028005210720022802f8042105024002402001450d0020052007410c6c6a21010340200241f0056a2000102620022802f005450d0220004180036a2100200241f8016a41086a220a200241f0056a41086a280200360200200220022903f0053703f801200141086a200a280200360200200120022903f801370200200741016a21072001410c6a2101200841807d6a22080d000b0b200241003602f0050b20024180056a200736020020022802fc042108200241f8016a200520052007410c6c6a10a901200241f0056a20022802f8012201200228028002104c024020022802fc01450d00200110020b02402007450d002007410c6c21002005210103400240200141046a280200450d00200128020010020b2001410c6a2101200041746a22000d000b0b02402008450d00200510020b02402003200241f0056a41201006450d0041d90a410e1008200341201013200241f0056a412010130b200241c4016a200241f0056a412010060d05200241ec016a2802002104200241f0006a41f8006a2802002105200241f0016a280200210a200241f8046a200241f0006a41f800101e1a2005200a4180036c6a210720052101200a450d03200241f0056a41096a2108200521010340200141086a2d0000210020012903002106200241f8016a200141096a41f702101e1a20004107460d03200241f0056a41086a20003a0000200220063703f0052008200241f8016a41f702101e1a200241f0056a10a60120014180036a22012007470d000c050b0b02402003450d002003410c6c21012005210203400240200241046a280200450d00200228020010020b2002410c6a2102200141746a22010d000b0b2004450d00200510020b4184351054000b20014180036a21010b20012007460d002005200a4180036c6a210803402001220041086a2d000022074107460d0120004180036a210102402007411d74411d75417f4a0d00200041146a2800002103200041106a280000210a02400240200741077122074105460d0020074104470d01200a41ff01714101470d02200310382003100220082001470d030c040b200a41ff01714101470d01200041186a280000450d012003100220082001470d020c030b2000410c6a2d000041ff01714101470d00200a1038200a100220082001470d010c020b20082001470d000b0b02402004450d00200510020b1034200241f0056a41086a22014200370300200242003703f00541e72e4107200241f0056a1003200241f8016a41086a2001290300370300200220022903f0053703f8014100210b02400240024002400240200241f8016a411041d02d410041001000417f460d00200242103702f4082002200241f8016a3602f008200241f0056a200241f0086a101620022802f0052204450d02200241f8056a280200210820022802f405210b0c010b41042104410021080b4100210a02400240024002400240024020024188056a2802002008470d000240024002402008450d0020024180056a280200210141002107200421000340200141086a280200220a200041086a280200470d0202402001280200220520002802002203460d0020052003200a10060d040b2001410c6a21012000410c6a2100200741016a22072008490d000b4101210a20080d040c060b4101210a200b0d060c070b20042008410c6c6a21074100210a0c030b4100210a0b2008450d020b20042008410c6c6a21070b2004210103402001410c6a21000240200141046a280200450d00200128020010020b2000210120072000470d000b0b200b450d010b200410020b200a450d01200241f0056a10aa0120022802f8052107024020024180066a2802002201450d002001410c6c21002007210103400240200141046a280200450d00200128020010020b2001410c6a2101200041746a22000d000b0b0240200241fc056a280200450d00200710020b200241f8016a41186a22014200370300200241f8016a41106a22004200370300200241f8016a41086a22074200370300200242003703f801200241f8016a1014200241f0086a41186a2001290300370300200241f0086a41106a2000290300370300200241f0086a41086a2007290300370300200220022903f8013703f0080240200241ac056a2201200241f0086a41201006450d0041d90a410e1008200141201013200241f0086a412010130b2001200241f0086a412010060d02024020024188056a2802002200450d0020024180056a28020021012000410c6c210003400240200141046a280200450d00200128020010020b2001410c6a2101200041746a22000d000b0b024020024184056a280200450d0020024180056a28020010020b20024190096a240042010f0b41c1214133102d000b418c3a103b000b41a43a103b000b41f439103b000b41dc39103b000b105d000b105c000b8b0401067f230041306b22022400024002400240410710012203450d002002200336021020024207370214200241106a4100410710272002280210200228021822046a220341002800c72d360000200241086a200441076a2204360200200341046a41002f00cb2d3b0000200341066a41002d00cd2d3a00002002200229031037030020022004360218410810012203450d002002200336021020024208370214200241106a41004108102720022802102204200228021822036a20013700002002200341086a220336021820022802142105200220022802082003102720022802002206200228020822076a20042003101e1a2002200720036a220736020802402005450d00200410020b20022802042104200241106a41086a220342003703002002420037031020062007200241106a1003200241086a2003290300370300200220022903103703002002411041d02d410041001000417f460d02200241286a4200370300200241106a41106a4200370300200342003703002002420037031020024110200241106a4120410010002203417f460d012003411f4d0d0120002002290310370000200041186a200241106a41186a290300370000200041106a200241106a41106a290300370000200041086a200241106a41086a29030037000002402004450d00200610020b200241306a24000f0b101c000b41c1214133102d000b41f4214122102d000bc50103037f017e027f4100210302400240024002400240200220016b2204450d002004410c6d2205ad4203862206a722044100480d032006422088a74100470d03200410012207450d0420012002470d010c020b410421074100210520012002460d010b4100210320072104034020012802002108200441046a200141086a28020036020020042008360200200441086a2104200341016a21032001410c6a22012002470d000b0b2000200536020420002007360200200020033602080f0b1041000b101c000be40703037f027e057f23004180016b22012400200141e0006a41086a220242003703002001420037036041e62d4107200141e0006a1003200141c0006a41086a2203200229030037030020012001290360370340200141c0006a41101005200242003703002001420037036041ed2d4107200141e0006a10032003200229030037030020012001290360370340200141c0006a41101005200342003703002001420037034041d12d4107200141c0006a100320022003290300370300200120012903403703600240024002400240200141e0006a411041d02d410041001000417f460d0020014200370340200141e0006a4110200141c0006a41084100100041016a41084d0d0220012903402104200141c0006a41086a220242003703002001420037034041d12d4107200141c0006a1003200141e0006a41086a200229030037030020012001290340370360200141e0006a411010054201a7450d010c030b4200a70d020b41f4214122102d000b41c1214133102d000b200141d82d10d901200141c0006a41086a220242003703002001420037034041e72e4107200141c0006a1003200141e0006a41086a20022903003703002001200129034037036041002102024002400240200141e0006a411041d02d410041001000417f460d00200142103702242001200141e0006a360220200141c0006a200141206a101620012802402203450d0220012902442105200141c0006a41086a220242003703002001420037034041e72e4107200141c0006a1003200141e0006a41086a200229030037030020012001290340370360200141e0006a411010052005422088a721022005a721060c010b41042103410021060b200141206a41df2d10d901200141e0006a41186a22074200370300200141e0006a41106a22084200370300200141e0006a41086a2209420037030020014200370360200141e0006a1014200141c0006a41186a220a2007290300370300200141c0006a41106a22072008290300370300200141c0006a41086a2208200929030037030020012001290360370340200020043703002000412c6a200141186a290300370000200041246a200141106a2903003700002000411c6a200141086a29030037000020002001290300370014200020012903403700342000413c6a2008290300370000200041c4006a2007290300370000200041cc006a200a290300370000200020033602082000410c6a2006360200200041106a2002360200200041ec006a200141206a41186a290300370000200041e4006a200141206a41106a290300370000200041dc006a200141206a41086a2903003700002000200129032037005420014180016a24000f0b41c1214133102d000bda10040d7f017e017f017e230041d0016b220224001034200241b0016a41086a22034200370300200242003703b00141ed2d4107200241b0016a1003200241a0016a41086a2003290300370300200220022903b0013703a0010240200241a0016a411041d02d410041001000417f460d00200241003602080240200241a0016a4110200241086a41044100100041016a41044d0d0020022802082104200241003602c801200242043703c001200241c0016a200410840120022802c801210520022802c00121060240024002400240024002402004450d0020062005410c6c6a2107410021080340410710012203450d02200220033602082002420737020c200241086a410041071027200241086a41086a22032003280200220941076a220a360200200920022802086a220b41002800e02e36000020024180016a41086a2209200a360200200b41046a41002f00e42e3b0000200b41066a41002d00e62e3a0000200220022903083703800141041001220b450d022002200b3602082002420437020c200241086a41004104102720032003280200220a41046a220b360200200a2002280208220c6a2008360000200228020c210d20024180016a2009280200200b1027200228028001220a2009280200220e6a200c200b101e1a2009200e200b6a220e3602000240200d450d00200c10020b200228028401210d200241a0016a41086a220b4200370300200242003703a001200a200e200241a0016a10032003200b290300370300200220022903a001370308200241086a411041d02d410041001000417f460d0420024100360280014100200241086a411020024180016a41044100100022032003417f461b220c41034d0d062002280280012203417f4c0d03024002402003450d00200310012209450d0420094100200310171a0c010b410121090b20034100200241086a411020092003200c4104200c4104491b1000220c200c417f461b4b0d052009450d06200841016a21082003ad220f422086200f84210f200b4200370300200242003703a001200a200e200241a0016a1003200241b0016a41086a200b290300370300200220022903a0013703b001200241b0016a411010050240200d450d00200a10020b20072009360200200741046a200f3702002007410c6a210720082004490d000b200520086a21050b200241c8016a200536020020022802c4012108200241086a200620062005410c6c6a10a90120024180016a200228020822032002280210104c0240200228020c450d00200310020b02402005450d002005410c6c21092006210303400240200341046a280200450d00200328020010020b2003410c6a2103200941746a22090d000b0b02402008450d00200610020b200241086a41186a20024180016a41186a290300370300200241086a41106a220920024180016a41106a290300370300200241086a41086a20024180016a41086a22072903003703002002200229038001370308200241b0016a41086a22044200370300200242003703b00141df2d4107200241b0016a1003200241a0016a41086a22082004290300370300200220022903b0013703a001200241a0016a4110200241086a41201004200241086a10aa01200241003602c801200242013703c001200241c0016a41004120102720022802c00120022802c801220b6a2203200229021c370000200341086a200241246a290200370000200341106a2002412c6a290200370000200341186a200241346a2902003700002002200b41206a22033602c8012002290308210f200241c0016a20034108102720022802c00120022802c80122036a200f3700002002200341086a22033602c801200241c0016a20034120102720022802c00120022802c801220b6a2203200229023c370000200341086a200241c4006a290200370000200341106a200241cc006a290200370000200341186a200241d4006a2902003700002002200b41206a22033602c801200241c0016a20034120102720022802c00120022802c801220b6a2203200229025c370000200341086a200241e4006a290200370000200341106a200241ec006a290200370000200341186a200241f4006a2902003700002002200b41206a22103602c801200928020021052002410036028801200242013703800120024180016a41004104102720022802800120022802880122036a20053600002002200341046a36028801200820022802880136020020022002290380013703a00120022802102106024002402005450d002005410c6c210c2006210b0340200241b0016a200b105120042802002203417f4c0d0420022802b001210a024002402003450d002003100122090d010c050b410121090b200741003602002002200336028401200220093602800120024180016a41002003102720072007280200220d20036a2209360200200d200228028001220e6a200a2003101e1a2002280284012103024020022802b401450d00200a10020b200241a0016a20082802002009102720022802a001220d2008280200220a6a200e2009101e1a2008200a20096a220936020002402003450d00200e10020b200b410c6a210b200c41746a220c0d000c020b0b20022802a801210920022802a001210d0b20022802a4012103200241c0016a201020091027200220022802c801220820096a22073602c801200820022802c001220b6a200d2009101e1a02402003450d00200d10020b2007ad422086210f200bad211102402005450d002005410c6c21092006210303400240200341046a280200450d00200328020010020b2003410c6a2103200941746a22090d000b0b200f201184210f0240200241146a280200450d00200610020b200241d0016a2400200f0f0b101c000b1019000b41f4214122102d000b200910020b41c1214133102d000b41c1214133102d000b41f4214122102d000b810101047f230041106b220224002002102f2002280208210302402002280204450d00200228020010020b0240410410012204450d002002200436020020024204370204200241004104102720022802002204200228020822056a20033600002002200541046a2203360208200241106a24002003ad4220862004ad840f0b101c000b4802017f017e230041206b220224002002102f200241106a200210a2012002350218422086200235021084210302402002280204450d00200228020010020b200241206a240020030ba56d09047f027e047f017e0b7f017e027f017e0c7f230041a0016b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d0000417f6a220341044b0d000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e050004020301000b200041106a2802002104200241186a41086a2000410c6a2802003602002002200041046a290200370318200241e8006a41086a220342003703002002420037036841b00f4107200241e8006a1003200241d8006a41086a2205200329030037030020022002290368370358200241d8006a4110200241f8006a410041001000417f470d38200342003703002002420037036841b70f4107200241e8006a10032005200329030037030020022002290368370358200241d8006a411041d02d410041001000417f460d0420024100360278200241d8006a4110200241f8006a41044100100041016a41044d0d4320022802782004470d050c590b200041246a2802002104200041286a290300210c200241c0006a200041196a290000370300200241286a41106a200041116a290000370300200241286a41086a200041096a29000037030020022000290001370328200241e8006a41086a220342003703002002420037036841b70f4107200241e8006a1003200241d8006a41086a200329030037030020022002290368370358410021030240200241d8006a411041d02d410041001000417f460d0020024100360278200241d8006a4110200241f8006a41044100100041016a41044d0d42200228027821030b20032004470d36200241e8006a41086a220342003703002002420037036841b00f4107200241e8006a1003200241d8006a41086a200329030037030020022002290368370358200241d8006a411041d02d410041001000417f460d352002200241d8006a3602682002411036026c2002420037037820024100200241d8006a4110200241f8006a41084100100022032003417f461b22034108200341084922041b220336027020040d3e20024100360278200241f0006a4100200241d8006a4110200241f8006a41042003100022042004417f461b22044104200441044922041b20036a36020020040d3e200241f8006a200241e8006a103a2002280278220d450d3e200241f8006a41086a280200210e200228027c210f200241e8006a41086a22034200370300200242003703684181114107200241e8006a1003200241d8006a41086a200329030037030020022002290368370358200241d8006a411041d02d410041001000417f460d34200241003602784100200241d8006a4110200241f8006a41044100100022032003417f461b220441034d0d4a20022802782209ad2206421d88a70d332006420386a72203417f4c0d322003450d052003100122100d060c5a0b200041046a2802002103200241e8006a41086a220442003703002002420037036841b00f4107200241e8006a1003200241d8006a41086a200429030037030020022002290368370358200241d8006a4110200241f8006a410041001000417f470d30200110af01450d2f200241e8006a41086a220442003703002002420037036841c50f4107200241e8006a1003200241d8006a41086a200429030037030020022002290368370358200241d8006a411041d02d410041001000417f460d392002421037022c2002200241d8006a360228200241f8006a200241286a103a20022802782204450d2e20024180016a280200220520034d0d39200228027c21080240200420034105746a22092001460d0020092001412010060d1c0b2002200836027c20022004360278200220053602800120012003200241f8006a10b001200241e8006a41086a220342003703002002420037036841be0f4107200241e8006a1003200241d8006a41086a200329030037030020022002290368370358200241d8006a411041d02d410041001000417f460d2d20024200370378200241d8006a4110200241f8006a41084100100041016a41084d0d472002290378210620012001104422072006200720072006561b22067d10b101200110432107410810012203450d59200220033602782002420837027c200241f8006a410041081027200228027820022802800122036a42f3e885d3a3ac98b63a3700002002200341086a36028001200241286a41086a20022802800136020020022002290378370328412010012203450d59200720067c2106200220033602782002422037027c200241f8006a4100412010272002280278220420022802800122056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a220336028001200228027c2108200241286a20022802302003102720022802282205200228023022016a20042003101e1a2002200120036a220336023002402008450d00200410020b200228022c210820022006370378200241e8006a41086a220442003703002002420037036820052003200241e8006a1003200241d8006a41086a200429030037030020022002290368370358200241d8006a4110200241f8006a41081004410121042008450d58200510020c580b200041046a2802002103410710012204450d58200220043602782002420737027c200241f8006a410041071027200228027820022802800122056a220441002800bf10360000200241286a41086a200541076a2205360200200441046a41002f00c3103b0000200441066a41002d00c5103a0000200220022903783703282002200536028001412010012204450d58200220043602782002422037027c200241f8006a4100412010272002280278220520022802800122086a22042001290000370000200441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a2900003700002002200841206a220436028001200228027c2109200241286a200228023020041027200228022822082002280230220a6a20052004101e1a2002200a20046a220436023002402009450d00200510020b200228022c2105200241e8006a41086a220942003703002002420037036820082004200241e8006a1003200241d8006a41086a200929030037030020022002290368370358200241d8006a4110200241f8006a410041001000210402402005450d00200810020b2004417f470d2b200241e8006a41086a220442003703002002420037036841c6104107200241e8006a1003200241d8006a41086a200429030037030020022002290368370358200241d8006a411041d02d410041001000417f460d2a20024200370378200241d8006a4110200241f8006a41084100100041016a41084d0d452001200229037810b201450d29200241e8006a41086a220442003703002002420037036841cd104107200241e8006a1003200241d8006a41086a200429030037030020022002290368370358410021050240200241d8006a411041d02d410041001000417f460d0020024100360278200241d8006a4110200241f8006a41044100100041016a41044d0d3f200228027821050b200241e8006a41086a2204420037030020024200370368418d104107200241e8006a1003200241d8006a41086a20042903003703002002200229036837035841002109200241d8006a411041d02d410041001000417f460d052002421037022c2002200241d8006a360228200241f8006a200241286a103a20022802782208450d1920024180016a2802002104200228027c210920052003470d4e0c4d0b2000412c6a2802002103200041286a2802002111200041246a2802002112200241c0006a200041196a290000370300200241286a41106a200041116a290000370300200241286a41086a200041096a29000037030020022000290001370328200241e8006a41086a220442003703002002420037036841b00f4107200241e8006a1003200241d8006a41086a200429030037030020022002290368370358200241d8006a4110200241f8006a410041001000417f470d27200241086a200110b30120022802084101470d262002200241286a10b3012002280200450d252002280204210e200241e8006a41086a220442003703002002420037036841b70f4107200241e8006a1003200241d8006a41086a200429030037030020022002290368370358410021040240200241d8006a411041d02d410041001000417f460d0020024100360278200241d8006a4110200241f8006a41044100100041016a41044d0d3d200228027821040b20042003470d24200241e8006a41086a22044200370300200242003703684186104107200241e8006a1003200241d8006a41086a200429030037030020022002290368370358200241d8006a411041d02d410041001000417f460d2320024100360278200241d8006a4110200241f8006a41044100100041016a41044d0d41200e200320022802786b4f0d22200241e8006a41086a220342003703002002420037036841c50f4107200241e8006a1003200241d8006a41086a200329030037030020022002290368370358200241d8006a411041d02d410041001000417f460d3a2002421037026c2002200241d8006a360268200241f8006a200241e8006a103a20022802782213450d2120024180016a280200221420124d0d3a200228027c21150240201320124105746a22032001460d0020032001412010060d3b0b201420114d0d360240201320114105746a2203200241286a460d002003200241286a412010060d370b200241c8006a200241286a10b4012002280250210320022802482105200241e8006a41086a2204420037030020024200370368418d104107200241e8006a1003200241d8006a41086a20042903003703002002200229036837035841002116200241d8006a411041d02d410041001000417f460d052002421037026c2002200241d8006a360268200241f8006a200241e8006a103a20022802782217450d17200228027c211620024180016a28020041057441057522042003200320044b1b22080d060c070b41002004460d540b41dc351054000b410821100b2002200936027c20022010360278200241003602800102402009450d002004410420044104491b210441002103410021050340200242003703684100200241d8006a4110200241e8006a41082004100022082008417f461b220841074d0d442008410820084108491b2108200541016a21052002290368210602402003200228027c470d00200241f8006a1071200241f8006a41086a2802002103200228027821100b200820046a2104201020034103746a2006370300200241f8006a41086a200341016a220336020020052009490d000b200228027821100b2010450d43200229027c2118200241e8006a41086a220342003703002002420037036841c50f4107200241e8006a1003200241d8006a41086a20032903003703002002200229036837035841002119200241d8006a411041d02d410041001000417f460d042002421037026c2002200241d8006a360268200241f8006a200241e8006a103a2002280278221a450d1220024180016a280200210b200228027c21190c050b410121084100210420052003460d470c480b4101211741002003200341004b1b2208450d010b4100210420024190016a210920024188016a210a20024180016a210b2017210303400240200520046a2d0000450d0020094200370300200a4200370300200b420037030020024200370378200241f8006a2003460d002003200241f8006a41201006450d00200241f8006a200310b50120022802784101470d3b200228027c200e4d0d050b200341206a2103200441016a22042008490d000b0b410021032016450d430c420b4101211a4100210b0b200241e8006a41086a22034200370300200242003703684188114107200241e8006a1003200241d8006a41086a200329030037030020022002290368370358200241d8006a411041d02d410041001000417f460d1620024200370378200241d8006a4110200241f8006a41084100100041016a41084d0d392002290378210620011043200110447c2006200bad7e221b540d15200241e8006a41086a2203420037030020024200370368418f114107200241e8006a1003200241d8006a41086a200329030037030020022002290368370358200241d8006a411041d02d410041001000417f460d142002421037026c2002200241d8006a360268200241f8006a200241e8006a10b60120022802782217450d1320024180016a280200221c450d122017290300200c5a0d11200228027c211d200241f8006a104720022802782209200228028001221141286c22056a210a41002103200921040240024002400240200541286d4104490d0020092105410021030340200241286a20052204460d0220032004200241286a4120100622054100476a21032005450d02200441286a2205200241286a460d0220032005200241286a4120100622084100476a21032008450d02200541286a2205200241286a460d0220032005200241286a4120100622084100476a21032008450d02200541286a2205200241286a460d0220032005200241286a4120100622084100476a21032008450d02200a200541286a22056b41286d41034b0d000b200441a0016a21040b02402004200a460d002009201141286c6a21080340200241286a2004460d0220032004200241286a4120100622054100476a21032005450d022008200441286a2204470d000b0b41000d010c020b4101450d010b2003200e4f0d0c0b0240200228027c450d00200910020b200241f8006a200241286a10b50120022802784101470d10024002402018421d88a74103752203200b4105744105752204200420034b1b2208450d0020024180016a2802002109200228027c210a4200210741002104201a210320102105034020052903002106200241106a200310b301200441016a21040240024020022802104101470d002002280214200a490d00200241f8006a200310b4010240200241f8006a41086a28020020094d0d002002280278220e20096a2d0000210b0240200228027c450d00200e10020b200b41ff01710d020c010b200228027c450d00200228027810020b420021060b200341206a2103200541086a2105200620077c210720042008490d000c020b0b420021070b2017201c41286c22056a21042017210302400240200541286d4104490d00200241206a2105200241786a2108200241506a2109200241a87f6a210a20172103034020052003460d02200341086a200241286a41201006450d0220082003460d02200341306a200241286a41201006450d0220092003460d02200341d8006a200241286a41201006450d02200a2003460d0220034180016a200241286a41201006450d022004200341a0016a22036b41286d41034b0d000b0b024020032004460d002017201c41286c6a2105200241206a2104034020042003460d02200341086a200241286a41201006450d022005200341286a2203470d000b0b2007200c520d00200241f8006a41186a2203200241286a41186a290300370300200241f8006a41106a2204200241286a41106a290300370300200241f8006a41086a2205200241286a41086a290300370300200220022903283703782017200c370300201741206a2003290300370300201741186a2004290300370300201741106a200529030037030020172002290378370308201c41144b0d02201c41014d0d03201c417f6a21092017201c41286c6a41586a210e0340201c20092203417f6a2209490d2d0240201c20096b22084102490d002017200341286c6a22052903002017200941286c6a220b29030022065a0d00200b2005290300370300200b2903082107200b41086a200541086a290300370300200241f8006a41186a2211200b41206a2203290300370300200241f8006a41106a2212200b41186a2204290300370300200241f8006a41086a2213200b41106a22012903003703002001200541106a2903003703002004200541186a2903003703002003200541206a2903003703002002200737037841012101024020084103490d0041012104200e21030340200441016a220120084f0d340240200341286a220529030020065a0d00200420084f0d34200341206a200341c8006a290300370300200341186a200341c0006a290300370300200341106a200341386a290300370300200341086a200341306a29030037030020032005290300370300200441026a210a2001210420052103200a2008490d010c020b0b20042101200321050b20052006370300200b200141286c6a22032002290378370308200341206a2011290300370300200341186a2012290300370300200341106a20132903003703000b200e41586a210e20090d000c040b0b200110432106410810012203450d4d200220033602782002420837027c200241f8006a410041081027200228027820022802800122036a42f3e885d3a3ac98b63a3700002002200341086a36028001200241e8006a41086a20022802800136020020022002290378370368412010012203450d4d2006201b20062006201b561b220c7d2107200220033602782002422037027c200241f8006a4100412010272002280278220420022802800122056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a220336028001200228027c2108200241e8006a20022802702003102720022802682205200228027022096a20042003101e1a2002200920036a220336027002402008450d00200410020b200228026c210420022007370378200241e8006a41086a220842003703002002420037036820052003200241e8006a1003200241d8006a41086a200829030037030020022002290368370358200241d8006a4110200241f8006a4108100402402004450d00200510020b0240201b2006580d002001200110442206201b200c7d2207200620062007561b7d10b1010b0240201d450d00201710020b02402019450d00201a10020b2018a7450d3f0c3e0b4101210320160d3f0c400b201c410176221ead42287e2206422088a70d082006a72203417f4c0d074108211f02402003450d0020031001221f450d4c0b410021042002410036027020024204370368201741586a2120201741887f6a212141042105200241e8006a41086a2115201c211603402016210e410021164101210802400240024002400240024002400240200e417f6a2203450d0002400240024002400240024002402017200341286c6a2903002017200e417e6a220841286c6a29030022065a0d00410021092008450d022021200e41286c6a210303402006200329030022075a0d02200341586a2103200721062008417f6a22080d000c030b0b02402008450d002021200e41286c6a2103410221080340200620032903002207540d04200341586a210320072106200e200841016a2208470d000b41002116200e21082004200228026c470d0e0c0d0b41022108410021162004200228026c470d0d0c0c0b200821090b200e2009490d02200e201c4b0d090240200e20096b2208410176220a450d002020200e41286c6a21032017200941286c6a21010340200241f8006a41206a220b200141206a2211290300370300200241f8006a41186a2212200141186a2213290300370300200241f8006a41106a2214200141106a2216290300370300200241f8006a41086a2222200141086a222329030037030020022001290300370378200341086a22242903002106200341106a22252903002107200341186a2226290300211b2003290300210c2011200341206a22272903003703002013201b37030020162007370300202320063703002001200c3703002027200b29030037030020262012290300370300202520142903003703002024202229030037030020032002290378370300200341586a2103200141286a2101200a417f6a220a0d000b0b2009450d010c030b200e20086b22090d020b200921160c020b2009200e1055000b0240200841094b0d00200e201c4b0d042017200941286c6a21120340200e2009417f6a2216490d060240200e20166b22084102490d002017200941286c6a22092903002017201641286c6a221129030022065a0d002011200929030037030020112903082107201141086a200941086a290300370300200241f8006a41186a2213201141206a2203290300370300200241f8006a41106a2214201141186a2201290300370300200241f8006a41086a2222201141106a220a290300370300200a200941106a2903003703002001200941186a2903003703002003200941206a290300370300200220073703784101210a024020084103490d0041012101201221030340200141016a220a20084f0d060240200341286a220929030020065a0d00200120084f0d08200341206a200341c8006a290300370300200341186a200341c0006a290300370300200341106a200341386a290300370300200341086a200341306a29030037030020032009290300370300200141026a210b200a210120092103200b2008490d010c020b0b2001210a200321090b200920063703002011200a41286c6a22032002290378370308200341206a2013290300370300200341186a2014290300370300200341106a20222903003703000b2016450d02201241586a2112201621092008410a490d000c020b0b200921162004200228026c470d070c060b2004200228026c460d050c060b41ccc100200141016a2008103c000b41dcc10020012008103c000b200e2009417f6a22164f0d010b2016200e1055000b200e201c1029000b200241e8006a107a20152802002104200228026821050b200520044103746a22032008360204200320163602002015200441016a2204360200024020044102490d00200228026821050340024002400240024020052004417f6a4103746a2203280200450d00200520044103746a220941746a2802002201200328020422084d0d00200441024d0d0520052004417d6a22124103746a2802042203200820016a4d0d01200441034d0d05200941646a280200200320016a4d0d010c050b20044103490d012003280204210820052004417d6a22124103746a28020421030b20032008490d010b2004417e6a21120b2004201241016a22134d0d04200420124d0d052005201241037422226a2203280204222320032802006a22032005201341037422246a22042802002214490d062003201c4b0d072017201441286c6a220e2004280204221141286c22046a2108200341286c210502400240024002400240200320146b220920116b220320114f0d00201f2008200341286c2204101e220b20046a210120114101480d0120034101480d01202020056a21052008210303402005200341586a2208200141586a22092009290300200829030054220a1b2204290300370300200541206a200441206a290300370300200541186a200441186a290300370300200541106a200441106a290300370300200541086a200441086a29030037030020012009200a1b2101200e20082003200a1b22034f0d04200541586a2105200b2104200b2001490d000c050b0b201f200e2004101e220320046a210120114101480d01200920114c0d01201720056a210a20032104200e21030340200320082004200829030020042903005422091b2205290300370300200341206a200541206a290300370300200341186a200541186a290300370300200341106a200541106a290300370300200341086a200541086a2903003703002004200441286a20091b2104200341286a2103200841286a200820091b2208200a4f0d04200120044b0d000c040b0b200821030c010b200e21030b201f21040b20032004200120046b220520054128706b101e1a2015280200220320124d0d082002280268220520226a2204202320116a36020420042014360200200320134d0d09200520246a2204200441086a200320136b41037441786a10391a20152003417f6a2204360200200441014b0d000b0b20160d000b0240200228026c450d00200228026810020b201e450d00201f10020b2002201d36027c200220173602782002201c36028001200241f8006a10b7010240201d450d00201710020b02402019450d00201a10020b2018a70d3b0c3c0b41acc10020132004103c000b41acc10020122004103c000b201420031055000b2003201c1029000b41bcc10020122003103c000b41b4c300103b000b105f000b105e000b418439103b000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41d437103b000b41ce114123102d000b41ec38103b000b41cc3641004100103c000b41c1214133102d000b4196114131102d000b41d438103b000b41f4214122102d000b41c1214133102d000b41b436103b000b41f4214122102d000b419c36103b000b41da0f412c102d000b418436103b000b41ec35103b000b418438103b000b41f4214122102d000b41ec37103b000b41f4214122102d000b41c1214133102d000b41a437103b000b418c37103b000b1063000b1062000b41f4214122102d000b41d410412d102d000b41c4381054000b41c435103b000b2009201c1055000b41f436103b000b41bc37103b000b41dcc10020042008103c000b41ccc100200441016a2008103c000b41dc36103b000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b419410412b102d000b41c1214133102d000b41ac35103b000b41c1214133102d000b41c1214133102d000b41c1214133102d000b200228027c450d00201010020b41c1214133102d000b201010020b200f450d09200d10020c090b201710020b0240200228024c450d00200510020b2002201536027c2002201336027820022014360280012001200241286a20031b2012201120031b200241f8006a10b001200241e8006a41086a220442003703002002420037036841be0f4107200241e8006a1003200241d8006a41086a2004290300370300200220022903683703580240200241d8006a411041d02d410041001000417f460d00200242003703780240200241d8006a4110200241f8006a41084100100041016a41084d0d002002290378210602402003450d0020012001104422072006200720072006561b7d10b1010c0a0b200241286a200241286a104422072006200720072006561b22067d10b101200110432107410810012203450d0d200220033602782002420837027c200241f8006a410041081027200228027820022802800122036a42f3e885d3a3ac98b63a3700002002200341086a36028001200241e8006a41086a20022802800136020020022002290378370368412010012203450d0d200720067c2106200220033602782002422037027c200241f8006a4100412010272002280278220420022802800122056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a220336028001200228027c2108200241e8006a20022802702003102720022802682205200228027022016a20042003101e1a2002200120036a220336027002402008450d00200410020b200228026c210420022006370378200241e8006a41086a220842003703002002420037036820052003200241e8006a1003200241d8006a41086a200829030037030020022002290368370358200241d8006a4110200241f8006a410810042004450d09200510020c090b41c1214133102d000b41f4214122102d000b20042003460d010b200420034d0d0120024190016a420037030020024188016a420037030020024180016a420037030020024200370378200820034105746a220a200241f8006a460d00200a200241f8006a412010060d010b2002200936024c20022008360248200220043602500240024020042003470d00200241f8006a41186a2204200141186a290000370300200241f8006a41106a220b200141106a290000370300200241f8006a41086a220e200141086a290000370300200220012900003703782003210a20032009460d010c040b200241f8006a41186a2209200141186a290000370300200241f8006a41106a220a200141106a290000370300200241f8006a41086a220b200141086a29000037030020022001290000370378200420034d0d02200820034105746a22042002290378370000200441186a2009290300370000200441106a200a290300370000200441086a200b2903003700000c040b200241c8006a107c200241c8006a41086a280200210a200228024821080c020b419c38103b000b41b43820032004103c000b200e2903002106200b29030021072004290300211b2008200a4105746a22042002290378370000200441186a201b370000200441106a2007370000200441086a2006370000200241c8006a41086a200a41016a3602000b200241286a41086a200241c8006a41086a28020036020020022002290348370328200241f8006a200241286a10a201200228028001210820022802782104200241e8006a41086a2209420037030020024200370368418d104107200241e8006a1003200241d8006a41086a200929030037030020022002290368370358200241d8006a41102004200810040240200228027c450d00200410020b0240200228022c450d00200228022810020b2002200541016a360278200241e8006a41086a220442003703002002420037036841cd104107200241e8006a1003200241d8006a41086a2205200429030037030020022002290368370358200241d8006a4110200241f8006a41041004200442003703002002420037036841b70f4107200241e8006a10032005200429030037030020022002290368370358410021050240200241d8006a411041d02d410041001000417f460d0020024100360278200241d8006a4110200241f8006a41044100100041016a41044d0d02200228027821050b410710012204450d04200220043602782002420737027c200241f8006a410041071027200228027820022802800122086a220441002800bf10360000200241286a41086a200841076a2208360200200441046a41002f00c3103b0000200441066a41002d00c5103a0000200220022903783703282002200836028001412010012204450d04200220043602782002422037027c200241f8006a4100412010272002280278220820022802800122096a22042001290000370000200441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a2900003700002002200941206a220436028001200228027c2109200241286a200228023020041027200228022822012002280230220a6a20082004101e1a2002200a20046a220a36023002402009450d00200810020b200228022c2108200241003602800120024201370378200241f8006a410041041027200228027820022802800122046a20053600002002200441046a220436028001200241f8006a2004410410272002280278220420022802800122056a20033600002002200541046a220336028001200241e8006a41086a22054200370300200242003703682001200a200241e8006a1003200241d8006a41086a200529030037030020022002290368370358200241d8006a41102004200310040240200228027c450d00200410020b2008450d00200110020b410121040c020b41c1214133102d000b0240200110af010d00200241e8006a41086a220342003703002002420037036841be0f4107200241e8006a1003200241d8006a41086a2003290300370300200220022903683703580240024002400240200241d8006a411041d02d410041001000417f460d00200242003703780240200241d8006a4110200241f8006a41084100100041016a41084d0d00200229037821062001104322072006540d02410810012203450d07200220033602782002420837027c200241f8006a410041081027200228027820022802800122036a42f3e885d3a3ac98b63a3700002002200341086a36028001200241286a41086a20022802800136020020022002290378370328412010012203450d07200720067d2107200220033602782002422037027c200241f8006a4100412010272002280278220520022802800122086a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200841206a220336028001200228027c2109200241286a200228023020031027200228022822082002280230220a6a20052003101e1a2002200a20036a220336023002402009450d00200510020b200228022c210520022007370378200241e8006a41086a220942003703002002420037036820082003200241e8006a1003200241d8006a41086a200929030037030020022002290368370358200241d8006a4110200241f8006a4108100402402005450d00200810020b20012001104420067c10b101200241e8006a41086a220342003703002002420037036841c50f4107200241e8006a1003200241d8006a41086a20032903003703002002200229036837035802400240200241d8006a411041d02d410041001000417f460d002002421037022c2002200241d8006a360228200241f8006a200241286a103a20022802782208450d052002200229027c220637022c20022008360228200241f8006a41186a200141186a290000370300200241f8006a41106a200141106a290000370300200241f8006a41086a200141086a29000037030020022001290000370378200241f8006a21032006422088a722052006a7460d010c060b2002410036023020024201370328200241f8006a41186a200141186a290000370300200241f8006a41106a200141106a290000370300200241f8006a41086a200141086a29000037030020022001290000370378200241f8006a21030b200241286a107c200241306a2802002105200228022821080c040b41c1214133102d000b41f4214122102d000b41ec3d103b000b41c1214133102d000b20032900002106200241286a41086a2209200541016a360200200820054105746a22052006370000200541186a200341186a290000370000200541106a200341106a290000370000200541086a200341086a290000370000200241c8006a41086a200928020036020020022002290328370348200241f8006a200241c8006a10a201200228028001210520022802782103200241e8006a41086a220842003703002002420037036841c50f4107200241e8006a1003200241d8006a41086a200829030037030020022002290368370358200241d8006a41102003200510040240200228027c450d00200310020b200228024c450d00200228024810020b200241f8006a41186a200141186a290000370300200241f8006a41106a200141106a290000370300200241f8006a41086a200141086a29000037030020022001290000370378200241c8006a41086a200241186a41086a28020036020020022002290318370348410710012203450d01200220033602282002420737022c200241286a4100410710272002280228200228023022056a220341002800cc0f360000200241e8006a41086a200541076a2205360200200341046a41002f00d00f3b0000200341066a41002d00d20f3a00002002200229032837036820022005360230412010012203450d01200220033602282002422037022c200241286a41004120102720022802282205200228023022086a22032002290378370000200341086a200241f8006a41086a290300370000200341106a200241f8006a41106a290300370000200341186a200241f8006a41186a2903003700002002200841206a2203360230200228022c2109200241e8006a200228027020031027200228026822082002280270220a6a20052003101e1a2002200a20036a220a36027002402009450d00200510020b200228026c2105200241286a200241c8006a10b8012002280230210920022802282103200241e8006a41086a220b4200370300200242003703682008200a200241e8006a1003200241d8006a41086a200b29030037030020022002290368370358200241d8006a41102003200910040240200228022c450d00200310020b02402005450d00200810020b0240200228024c450d00200228024810020b410710012203450d01200220033602782002420737027c200241f8006a410041071027200228027820022802800122056a220341002800d30f360000200241286a41086a200541076a2205360200200341046a41002f00d70f3b0000200341066a41002d00d90f3a0000200220022903783703282002200536028001412010012203450d01200220033602782002422037027c200241f8006a4100412010272002280278220520022802800122086a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200841206a220336028001200228027c2101200241286a20022802302003102720022802282208200228023022096a20052003101e1a2002200920036a220336023002402001450d00200510020b200228022c210520022004360278200241e8006a41086a220442003703002002420037036820082003200241e8006a1003200241d8006a41086a200429030037030020022002290368370358200241d8006a4110200241f8006a4104100402402005450d00200810020b410021040b0240024020002d000022034107714101460d0020034105460d0120034102460d0120034101470d01200041086a280200450d01200041046a2802001002200241a0016a24000f0b2004450d00200041086a280200450d00200041046a28020010020b200241a0016a24000f0b101c000ba90301057f230041206b220124000240410710012202450d002001200236021020014207370214200141106a4100410710272001280210200128021822036a220241002800d30f360000200141086a200341076a2203360200200241046a41002f00d70f3b0000200241066a41002d00d90f3a00002001200129031037030020012003360218412010012202450d002001200236021020014220370214200141106a41004120102720012802102203200128021822046a22022000290000370000200241086a200041086a290000370000200241106a200041106a290000370000200241186a200041186a2900003700002001200441206a220036021820012802142104200120012802082000102720012802002202200128020822056a20032000101e1a2001200520006a220036020802402004450d00200310020b20012802042103200141106a41086a220442003703002001420037031020022000200141106a1003200141086a20042903003703002001200129031037030020014110200141106a410041001000210002402003450d00200210020b200141206a24002000417f470f0b101c000bc70908057f017e017f027e017f017e017f017e230041d0006b220324000240200241086a2204280200220520014d0d002002280200220620014105746a220141186a2207290000210820062005417f6a22094105746a2205290000210a200541086a2206290000210b200541106a220c290000210d2007200541186a220e290000370000200141106a2207290000210f2007200d370000200141086a2207290000210d2007200b3700002001290000210b2001200a370000200341106a41186a2008370300200341106a41106a200f370300200341106a41086a2201200d370300200e2008370000200c200f3700002006200d3700002005200b3700002003200b37031020042009360200200341086a200936020020032002290200370300200341c0006a200310a2012003280248210220032802402105200142003703002003420037031041c50f4107200341106a1003200341306a41086a200129030037030020032003290310370330200341306a411020052002100402402003280244450d00200510020b02402003280204450d00200328020010020b0240410710012201450d002003200136021020034207370214200341106a4100410710272003280210200328021822056a220141002800cc0f360000200341306a41086a200541076a2205360200200141046a41002f00d00f3b0000200141066a41002d00d20f3a00002003200329031037033020032005360218412010012201450d002003200136021020034220370214200341106a41004120102720032802102205200328021822026a22012000290000370000200141086a200041086a290000370000200141106a200041106a290000370000200141186a200041186a2900003700002003200241206a220136021820032802142109200341306a20032802382001102720032802302202200328023822046a20052001101e1a2003200420016a220136023802402009450d00200510020b20032802342105200341106a41086a220942003703002003420037031020022001200341106a1003200341306a41086a200929030037030020032003290310370330200341306a4110100502402005450d00200210020b410710012201450d002003200136021020034207370214200341106a4100410710272003280210200328021822056a220141002800d30f360000200341306a41086a200541076a2205360200200141046a41002f00d70f3b0000200141066a41002d00d90f3a00002003200329031037033020032005360218412010012201450d002003200136021020034220370214200341106a41004120102720032802102205200328021822026a22012000290000370000200141086a200041086a290000370000200141106a200041106a290000370000200141186a200041186a2900003700002003200241206a220036021820032802142102200341306a20032802382000102720032802302201200328023822096a20052000101e1a2003200920006a220036023802402002450d00200510020b20032802342105200341106a41086a220242003703002003420037031020012000200341106a1003200341306a41086a200229030037030020032003290310370330200341306a4110100502402005450d00200110020b200341d0006a24000f0b101c000b419c3920012005103c000b9a0301057f230041306b220224000240410810012203450d002002200336022020024208370224200241206a4100410810272002280220200228022822036a42f3e885d3c3cdd8b73a3700002002200341086a360228200241106a41086a200228022836020020022002290320370310412010012203450d002002200336022020024220370224200241206a41004120102720022802202204200228022822056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002002200541206a220036022820022802242105200241106a20022802182000102720022802102203200228021822066a20042000101e1a2002200620006a220036021802402005450d00200410020b2002280214210420022001370308200241206a41086a220542003703002002420037032020032000200241206a1003200241106a41086a200529030037030020022002290320370310200241106a4110200241086a4108100402402004450d00200310020b200241306a24000f0b101c000bfd0602067f017e230041306b220224000240410810012203450d00200220033602182002420837021c200241186a4100410810272002280218200228022022036a42f3e885d3a3ec9bb73a3700002002200341086a360220200241086a41086a200228022036020020022002290318370308412010012203450d00200220033602182002422037021c200241186a41004120102720022802182204200228022022056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002002200541206a2203360220200228021c2106200241086a20022802102003102720022802082205200228021022076a20042003101e1a2002200720036a220336021002402006450d00200410020b200228020c210442002108200241186a41086a220642003703002002420037031820052003200241186a1003200241086a41086a20062903003703002002200229031837030802400240200241086a411041d02d410041001000417f460d0020024200370318200241086a4110200241186a41084100100041016a41084d0d01200229031821080b02402004450d00200510020b4100210302402008427f510d002008102e560d002000104322082001540d00410810012203450d02200220033602182002420837021c200241186a4100410810272002280218200228022022036a42f3e885d3a3ac98b63a3700002002200341086a360220200241086a41086a200228022036020020022002290318370308412010012203450d02200820017d2108200220033602182002422037021c200241186a41004120102720022802182204200228022022056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002002200541206a2200360220200228021c2103200241086a20022802102000102720022802082205200228021022066a20042000101e1a2002200620006a220036021002402003450d00200410020b200228020c210420022008370328200241186a41086a220342003703002002420037031820052000200241186a1003200241086a41086a200329030037030020022002290318370308200241086a4110200241286a41081004410121032004450d00200510020b200241306a240020030f0b41c1214133102d000b101c000bf80301057f230041206b22022400024002400240410710012203450d002002200336021020024207370214200241106a4100410710272002280210200228021822046a220341002800d30f360000200241086a200441076a2204360200200341046a41002f00d70f3b0000200341066a41002d00d90f3a00002002200229031037030020022004360218412010012203450d002002200336021020024220370214200241106a41004120102720022802102204200228021822056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a220136021820022802142105200220022802082001102720022802002203200228020822066a20042001101e1a2002200620016a220136020802402005450d00200410020b20022802042104200241106a41086a220542003703002002420037031020032001200241106a1003200241086a20052903003703002002200229031037030041002101024002402002411041d02d410041001000417f460d00200241003602104101210120024110200241106a41044100100041016a41044d0d01200228021021052004450d040c030b20040d020c030b41c1214133102d000b101c000b200310020b2000200136020020002005360204200241206a24000b8806010a7f230041306b22022400024002400240024002400240024002400240410710012203450d00200220033602182002420737021c200241186a4100410710272002280218200228022022046a220341002800cc0f360000200241086a41086a200441076a2204360200200341046a41002f00d00f3b0000200341066a41002d00d20f3a00002002200229031837030820022004360220412010012203450d00200220033602182002422037021c200241186a41004120102720022802182204200228022022056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a2201360220200228021c2103200241086a20022802102001102720022802082206200228021022056a20042001101e1a2002200520016a220136021002402003450d00200410020b200228020c2107200241186a41086a220342003703002002420037031820062001200241186a1003200241086a41086a200329030037030020022002290318370308200241086a411041d02d410041001000417f460d01200241003602184100200241086a4110200241186a41044100100022012001417f461b220141034d0d0720022802182208417f4c0d082008450d022008100122090d030b101c000b200041003602082000420137020020070d020c030b410121090b2002200836021c200220093602182002410036022002402008450d002001410420014104491b2103200241206a210a41002101410021040340200241003a002f200241086a41102002412f6a41012003100041016a41014b220b450d04200441016a210420022d002f210502402001200228021c470d00200241186a1023200a2802002101200228021821090b2003200b6a2103200920016a20053a0000200a200141016a220136020020042008490d000b200228021821090b2009450d032000200229021c370204200020093602002007450d010b200610020b200241306a24000f0b200228021c450d00200910020b41c1214133102d000b1024000b990401057f230041206b220224000240410710012203450d002002200336021020024207370214200241106a4100410710272002280210200228021822046a220341002800bf10360000200241086a200441076a2204360200200341046a41002f00c3103b0000200341066a41002d00c5103a00002002200229031037030020022004360218412010012203450d002002200336021020024220370214200241106a41004120102720022802102204200228021822056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a220136021820022802142105200220022802082001102720022802002203200228020822066a20042001101e1a2002200620016a220136020802402005450d00200410020b20022802042104200241106a41086a220542003703002002420037031020032001200241106a1003200241086a20052903003703002002200229031037030041002101024002402002411041d02d410041001000417f460d002002410036021020024110200241106a41044100100041016a41044d0d01200228021021012002410036021020024110200241106a41044104100041016a41044d0d01200041086a200228021036020020002001360204410121010b2000200136020002402004450d00200310020b200241206a24000f0b41c1214133102d000b101c000b930503067f017e097f230041d0006b220224002002410036023020012001280208220341002001280200220420012802042205200241306a41042003100022032003417f461b2203410420034104491b6a220636020802400240024002400240200341034d0d0020022802302207ad42287e2208422088a70d042008a72203417f4c0d032003450d012003100122090d02101c000b20004100360200200241d0006a24000f0b410821090b20022007360204200220093602002002410036020802402007450d00200241306a41186a210a200241306a41106a210b4100210c4100210d034020024200370330200141086a220e410020042005200241306a41082006100022032003417f461b2203410820034108491b20066a220636020002400240200341074d0d0020022903302108200a4200370300200b4200370300200241306a41086a220f420037030020024200370330200e410020042005200241306a41202006100022032003417f461b2203412020034120491b20066a22063602002003411f4d0d00200d41016a210d200241106a41186a220e200a290300370300200241106a41106a2210200b290300370300200241106a41086a2211200f29030037030020022002290330370310200c2002280204470d0120021068200241086a280200210c200228020021090c010b2000410036020002402002280204450d00200910020b200241d0006a24000f0b2009200c41286c6a2203200837030020032002290310370308200341206a200e290300370300200341186a2010290300370300200341106a2011290300370300200241086a200c41016a220c360200200d2007490d000b0b20002002290300370200200041086a200241086a280200360200200241d0006a24000f0b105f000b105e000bf40403057f017e037f230041306b22012400200041086a28020021022001410036022820014201370320200141206a4100410410272001280220200128022822036a20023600002001200341046a360228200141086a220420012802283602002001200129032037030002400240024002402002450d0020002802002200200241286c6a21050340200141106a41086a220341003602002001420137031020002903002106200141106a41004108102720032003280200220241086a2207360200200220012802106a2006370000200141106a20074120102720032003280200220741206a22023602002007200128021022086a220341086a200041106a290000370000200341106a200041186a290000370000200341186a200041206a2900003700002003200041086a2900003700002002417f4c0d03024002402002450d002002100122030d010c060b410121030b200141206a41086a220741003602002001200236022420012003360220200141206a41002002102720072007280200220920026a22033602002009200128022022076a20082002101e1a2001280224210202402001280214450d00200810020b200120042802002003102720012802002209200428020022086a20072003101e1a2004200820036a220336020002402002450d00200710020b200041286a22002005470d000c020b0b20012802082103200128020021090b20012802042102200141206a41086a2200420037030020014200370320418f114107200141206a1003200141106a41086a200029030037030020012001290320370310200141106a411020092003100402402002450d00200910020b200141306a24000f0b1019000b101c000bb50201077f230041206b22022400200141086a28020021032002410036021820024201370310200241106a4100410410272002280210200228021822046a20033600002002200441046a360218200241086a2204200228021836020020022002290310370300024002402003450d00200128020021050340410110012201450d022002200136021020024201370214200241106a410041011027200241106a41086a22012001280200220641016a22013602002006200228021022076a20052d00003a00002002280214210620022004280200200110272002280200200428020022086a20072001101e1a2004200820016a36020002402006450d00200710020b200541016a21052003417f6a22030d000b0b20002002290300370200200041086a2004280200360200200241206a24000f0b101c000bd60c03047f047e017f230041f0006b210202400240024002400240024002400240024002400240024002400240024020012d002822034103714101460d0020034102470d01200141206a22032802002204450d0e20032004417f6a3602002001411c6a2d0000450d050c0e0b20012802102204450d01200141106a4100360200024020012802082203200128020c2205460d002004417f7321040340200241c8006a41206a200341206a290300370300200241c8006a41186a200341186a290300370300200241c8006a41106a200341106a290300370300200241c8006a41086a200341086a29030037030020022003290300370348200441016a2204450d072005200341286a2203470d000b200141086a20053602000b200042003703000f0b20012802102204450d01200141106a410036020020012802082203200128020c2205460d022004417f7321040340200241c8006a41206a200341206a290300370300200241c8006a41186a200341186a290300370300200241c8006a41106a200341106a290300370300200241c8006a41086a200341086a29030037030020022003290300370348200441016a2204450d062005200341286a2203470d000b200141086a20053602000c020b20012802082202200128020c460d06200141086a200241286a360200200041286a200241206a290300370300200041206a200241186a290300370300200041186a200241106a290300370300200041106a200241086a29030037030020002002290300370308200042013703000f0b20012802082203200128020c460d00200141086a200341286a360200200241206a200341206a290300370300200241186a200341186a290300370300200241106a200341106a290300370300200241086a200341086a290300370300200220032903003703000c040b200141286a41023a0000200141206a22032802002204450d0820032004417f6a3602002001411c6a2d0000450d050c080b200141186a22042802002203200141146a280200460d082004200341586a220336020020032903004200510d05200241c8006a41206a200341206a2903002206370300200241c8006a41186a200341186a2903002207370300200241c8006a41106a200341106a2903002208370300200241c8006a41086a200341086a2903002209370300200241086a22042008370300200241106a22052007370300200241186a220a20063703002002200329030037034820022009370300200041286a200141246a280200290300370300200041206a200a290300370300200041186a2005290300370300200041106a200429030037030020002002290300370308200042013703000f0b2000200229034837030820004201370300200141086a200341286a360200200041106a200241c8006a41086a290300370300200041186a200241c8006a41106a290300370300200041206a200241c8006a41186a290300370300200041286a200241c8006a41206a2903003703000f0b200141086a200341286a360200200241086a200241c8006a41086a290300370300200241106a200241c8006a41106a290300370300200241186a200241c8006a41186a290300370300200241206a200241c8006a41206a290300370300200220022903483703000b2000200229030037030820004201370300200041106a200241086a290300370300200041186a200241106a290300370300200041206a200241186a290300370300200041286a200241206a2903003703000f0b200042003703000f0b200141186a22042802002203200141146a280200460d022004200341586a220336020020032903004200510d01200241c8006a41206a200341206a2903002206370300200241c8006a41186a200341186a2903002207370300200241c8006a41106a200341106a2903002208370300200241c8006a41086a200341086a2903002209370300200241286a41086a22042008370300200241286a41106a22052007370300200241286a41186a220a20063703002002200329030037034820022009370328200041286a200141246a280200290300370300200041206a200a290300370300200041186a2005290300370300200041106a200429030037030020002002290328370308200042013703000f0b2001411c6a41013a0000200042003703000f0b2001411c6a41013a0000200042003703000f0b200042003703000f0b200042003703000b8c0204017f017e017f017e230041c0006b22022400102e2103200241086a220442003703002002420037030041f726410720021003200241306a41086a2004290300370300200220022903003703300240200241306a411041d02d410041001000417f460d00200242003703000240200241306a4110200241084100100041016a41084d0d0020022903002105200241286a200041286a290300370300200241206a200041206a290300370300200241186a200041186a290300370300200241106a200041106a290300370300200241086a200041086a29030037030020022000290300370300200520037c20022001103f200241c0006a24000f0b41c1214133102d000b41f4214122102d000bba0503047f017e087f230041e0006b22012400200141c0006a41086a220242003703002001420037034041f2224107200141c0006a1003200141086a2002290300370300200120012903403703000240024002402001411041d02d410041001000417f460d00200141003602400240410020014110200141c0006a41044100100022022002417f461b220341034d0d0020012802402204ad42287e2205422088a70d022005a72202417f4c0d03024002402002450d002002100122060d01101c000b410821060b200120043602142001200636021020014100360218024002402004450d002003410420034104491b2107200141c0006a41186a21084100210341002109034020014200370340410020014110200141c0006a41082007100022022002417f461b220241074d0d022001290340210520084200370300200141c0006a41106a220a4200370300200141c0006a41086a220b420037030020014200370340410020014110200141c0006a41202002410820024108491b20076a2207100022022002417f461b2202411f4d0d02200941016a21092002412020024120491b2102200141206a41186a220c2008290300370300200141206a41106a220d200a290300370300200141206a41086a220a200b29030037030020012001290340370320024020032001280214470d00200141106a106f200141106a41086a2802002103200128021021060b200220076a21072006200341286c6a2202200537030020022001290320370308200241206a200c290300370300200241186a200d290300370300200241106a200a290300370300200141106a41086a200341016a220336020020092004490d000b200128021021060b2006450d012000200129021437020420002006360200200141e0006a24000f0b2001280214450d00200610020b41c1214133102d000b41f4214122102d000b1064000b1065000bf40403057f017e037f230041306b22012400200041086a28020021022001410036022820014201370320200141206a4100410410272001280220200128022822036a20023600002001200341046a360228200141086a220420012802283602002001200129032037030002400240024002402002450d0020002802002200200241286c6a21050340200141106a41086a220341003602002001420137031020002903002106200141106a41004108102720032003280200220241086a2207360200200220012802106a2006370000200141106a20074120102720032003280200220741206a22023602002007200128021022086a220341086a200041106a290000370000200341106a200041186a290000370000200341186a200041206a2900003700002003200041086a2900003700002002417f4c0d03024002402002450d002002100122030d010c060b410121030b200141206a41086a220741003602002001200236022420012003360220200141206a41002002102720072007280200220920026a22033602002009200128022022076a20082002101e1a2001280224210202402001280214450d00200810020b200120042802002003102720012802002209200428020022086a20072003101e1a2004200820036a220336020002402002450d00200710020b200041286a22002005470d000c020b0b20012802082103200128020021090b20012802042102200141206a41086a220042003703002001420037032041f2224107200141206a1003200141106a41086a200029030037030020012001290320370310200141106a411020092003100402402002450d00200910020b200141306a24000f0b1019000b101c000b922305077f017e027f017e037f230041b0016b22022400200241003a005020012001280208220320012802002001280204200241d0006a41012003100041016a220341014b6a220436020802400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020034102490d0020022d0050220341074b0d03024020030e080005020404060703000b200241003a0050200141086a20042001280200200141046a280200200241d0006a41012004100041016a220341014b6a220436020020034102490d1e20022d00502203450d0a20034101470d1e200141046a280200210520024100360250200141086a4100200128020022062005200241d0006a41042004100022032003417f461b2207410420074104491b20046a2203360200200741034d0d1e20022802502208ad42187e2209422088a70d202009a72204417f4c0d1f2004450d1b20041001220a0d1c0c210b20004106360200200241b0016a24000f0b200241003a005041042107200141086a200420012802002205200141046a280200220b200241d0006a41012004100041016a220341014b6a220436020020034102490d1020022d0050220341034b0d10024020030e04000e0f10000b20024200370350200141086a41002005200b200241d0006a41082004100022012001417f461b2201410820014108491b20046a360200200141074d0d1020022903502109410121070c0f0b200241003a0050200141086a200420012802002207200141046a2802002205200241d0006a41012004100041016a220341014b6a220436020020034102490d0620022d00502203450d0420034101470d0620024200370350200141086a410020072005200241d0006a41082004100022012001417f461b2201410820014108491b20046a360200200141074d0d06200229035021094202210c0c050b20004106360200200241b0016a24000f0b200241003a0050200141086a200420012802002207200141046a2802002205200241d0006a41012004100041016a220341014b6a220436020020034102490d0820022d00502203450d0620034101470d08420221090c070b200241003a0050200141086a200420012802002207200141046a2802002205200241d0006a41012004100041016a220341014b6a220436020020034102490d1120022d00502203450d0820034101470d1120024100360250200141086a410020072005200241d0006a41042004100022012001417f461b2201410420014104491b20046a360200200141034d0d1120022802502103420221090c200b200241003a0050200141086a200420012802002207200141046a2802002205200241d0006a41012004100041016a220341014b6a2204360200024020034102490d004105210320022d0050220b41034b0d1d0240200b0e0400100e0f000b20024100360250200141086a410020072005200241d0006a41042004100022012001417f461b2201410420014104491b20046a360200200141034d0d1d20022802502101410121030c1f0b410521030c1c0b20024200370350200141086a410020072005200241d0006a41082004100022012001417f461b2201410820014108491b20046a360200200141074d0d01200229035021094201210c0b20004105360200200041086a200c370300200041106a2009370300200041186a2002290350370300200041206a200241d0006a41086a290300370300200041286a200241d0006a41106a290300370300200241b0016a24000f0b20004106360200200241b0016a24000f0b200141046a280200210320024100360250200141086a410020012802002003200241d0006a41042004100022032003417f461b2203410420034104491b20046a2204360200200341034d0d1320022802502203417f4c0d172003450d0e20031001220a450d16200a4100200310171a200141086a28020021040c0f0b20024200370350200141086a410020072005200241d0006a41082004100022012001417f461b22014108200141084922011b20046a36020020010d012002290350210c420121090b20004101360200200041086a2009370300200041106a200c370300200041186a2002290350370300200041206a200241d0006a41086a290300370300200041286a200241d0006a41106a290300370300200241b0016a24000f0b20004106360200200241b0016a24000f0b200241d0006a200110bd0120024180016a41086a2203200241dc006a29020037030020024180016a41106a2204200241e4006a29020037030020024180016a41186a2207200241ec006a29020037030020024180016a41206a2205200241f4006a29020037030020024180016a41286a220b200241fc006a2802003602002002200229025437038001200228025022064106460d08200241206a41286a220a200b280200360200200241206a41206a220b2005290300370300200241206a41186a22052007290300370300200241206a41106a22072004290300370300200241206a41086a220420032903003703002002200229038001370320200241d0006a41286a200a280200360200200241d0006a41206a200b290300370300200241d0006a41186a2005290300370300200241d0006a41106a2007290300370300200241d0006a41086a200429030037030020022002290320370350413010012203450d1220032002290350370204200320063602002003410c6a200241d0006a41086a290300370200200341146a200241e0006a2903003702002003411c6a200241e8006a290300370200200341246a200241f0006a2903003702002003412c6a200241f8006a28020036020020022003360208200241003a0050200141086a2204200428020022042001280200200141046a280200200241d0006a41012004100041016a41014b22016a3602002001450d0720022d0050220141034f0d07420121090c170b20024200370350200141086a41002005200b200241d0006a41082004100022012001417f461b2201410820014108491b20046a360200200141074d0d0220022903502109410221070c010b20024100360250200141086a41002005200b200241d0006a41042004100022012001417f461b2201410420014104491b20046a36020041032107200141034d0d01200228025021060b20004102360200200041086a20073602002000410c6a2006360200200041106a2009370200200041186a2002290350370300200041206a200241d0006a41086a290300370300200041286a200241d0006a41106a290300370300200241b0016a24000f0b20004106360200200241b0016a24000f0b20024200370350200141086a410020072005200241d0006a41082004100022012001417f461b2201410820014108491b20046a360200200141074d0d0f20022903502109410321030c100b20024200370350200141086a410020072005200241d0006a41082004100022012001417f461b2201410820014108491b20046a360200200141074d0d0e20022903502109410421030c0f0b200241d0006a41186a220b4200370300200241d0006a41106a22064200370300200241d0006a41086a220a420037030020024200370350200141086a410020072005200241d0006a41202004100022012001417f461b2201412020014120491b20046a3602002001411f4d0d0220024180016a41186a2201200b29030037030020024180016a41106a2203200629030037030020024180016a41086a2204200a2903003703002002200229035037038001200b200129030037030020062003290300370300200a20042903003703002002200229038001370350410221032002411c6a41026a220420022d00523a0000200241086a41086a2207200241e7006a290000370300200241086a41106a2205200241d0006a411f6a2d00003a0000200220022f01503b011c2002200229005f3703082002280053210120022900572109200241046a41026a20042d00003a0000200241206a41086a2007290300370300200241206a41106a20052d00003a0000200220022f011c3b0104200220022903083703200c0f0b200241086a10220b20004106360200200241b0016a24000f0b200b20024180016a41186a290000370300200620024180016a41106a290000370300200a20024180016a41086a29000037030020022002290080013703500c0a0b4101210a0b200141086a200341002001280200200141046a280200200a20032004100022012001417f461b2201200120034b1b20046a3602000240200320014d0d00200a10020c040b200a450d032003ad22094220862009842109410121010c020b4104210a0b200220083602542002200a3602502002410036025802402008450d00200141086a21044101210d4100210b03402002410036028001200441002006200520024180016a41042003100022072007417f461b2207410420074104491b20036a220f36020002400240200741034d0d002002280280012203417f4c0d09024002402003450d00200310012207450d0a20074100200310171a0c010b410121070b2004200341002006200520072003200f100022052005417f461b2205200520034b1b200f6a3602000240200320054b0d002007450d012003ad22094220862009842109200141046a220e28020021052004280200210320024100360280012004200341002001280200200520024180016a41042003100022052005417f461b2205410420054104491b6a22063602000240200541034d0d002002280280012203417f4c0d0b024002402003450d00200310012205450d0c20054100200310171a200428020021060c010b410121050b2004200341002001280200200e2802002005200320061000220f200f417f461b220f200f20034b1b20066a36020002402003200f4b0d002005450d012003ad220c422086200c84210c200b2002280254470d04200241d0006a1076200241d0006a41086a280200210b2002280250210a0c040b200510020b2009a7450d010b200710020b200228025021040240200b450d00200b41186c21032004210103400240200141046a280200450d00200128020010020b0240200141106a280200450d002001410c6a28020010020b200141186a2101200341686a22030d000b0b2002280254450d04200410020c040b0240200a200b41186c6a22032009370204200320073602002003410c6a2005360200200341106a200c370200200241d0006a41086a200b41016a220b360200200d20084f0d00200d41016a210d20042802002103200e2802002105200128020021060c010b0b2002280250210a0b200a450d0120022902542109410221010b2000200136020420004100360200200041086a200a3602002000410c6a2009370200200041146a20022902503702002000411c6a200241d0006a41086a290200370200200041246a200241e0006a2902003702002000412c6a200241e8006a280200360200200241b0016a24000f0b20004106360200200241b0016a24000f0b1061000b1060000b101c000b1019000b0b0b200241086a41026a2204200241046a41026a2d00003a0000200241d0006a41086a2207200241206a41086a290300370300200241d0006a41106a2205200241206a41106a290300370300200220022f01043b010820022002290320370350024020034105470d0020004106360200200241b0016a24000f0b2002411c6a41026a220b20042d00003a000020024180016a41086a2204200729030037030020024180016a41106a22072005290300370300200220022f01083b011c2002200229035037038001200041086a20033a0000200041043602002000410c6a2001360000200041106a2009370000200020022f011c3b00092000410b6a200b2d00003a0000200041186a200229038001370000200041206a2004290300370000200041286a2007290300370000200241b0016a24000f0b200041033602002000410c6a2002290250370200200041146a200241d8006a2902003702002000411c6a200241e0006a290200370200200041246a200241e8006a2902003702002000412c6a200241f0006a28020036020020002003ad422086200141ff0171ad42088684200984370204200241b0016a24000be60201047f230041206b22022400200241003602082002420137030020024100412010272002280200200228020822036a22042001290000370000200441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a2900003700002002200341206a2204360208200220044120102720022802002203200228020822056a22042001290020370000200441086a200141286a290000370000200441106a200141306a290000370000200441186a200141386a2900003700002002200541206a220136020802402001417f4c0d00024002402001450d002001100122040d01101c000b410121040b200220013602142002200436021020024100360218200241106a41002001102720022002280218220420016a360218200420022802106a20032001101e1a200041086a20022802183602002000200229031037020002402002280204450d00200310020b200241206a24000f0b1019000be70101037f0240024002402000280200220128020022024103460d0020020d0220012802042202450d0220024101470d012001410c6a280200450d02200141086a2802001002200028020010020f0b20012d00044101470d01200141086a10bf01200028020010020f0b0240200141106a2802002203450d00200141086a2802002102200341186c210303400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200341686a22030d000b0b2001410c6a280200450d00200141086a28020010020b200028020010020be00302057f017e230041206b220124000240410710012202450d002001200236021020014207370214200141106a4100410710272001280210200128021822036a220241002800d92e360000200141086a200341076a2203360200200241046a41002f00dd2e3b0000200241066a41002d00df2e3a00002001200129031037030020012003360218412010012202450d002001200236021020014220370214200141106a41004120102720012802102203200128021822046a22022000290000370000200241086a200041086a290000370000200241106a200041106a290000370000200241186a200041186a2900003700002001200441206a220036021820012802142104200120012802082000102720012802002202200128020822056a20032000101e1a2001200520006a220036020802402004450d00200310020b2001280204210342002106200141106a41086a220442003703002001420037031020022000200141106a1003200141086a200429030037030020012001290310370300024002402001411041d02d410041001000417f460d002001420037031020014110200141106a41084100100041016a41084d0d01200129031021060b02402003450d00200210020b200141206a240020060f0b41c1214133102d000b101c000bd14b05067f017e057f047e047f230041a0076b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d00002203417f6a220441054b0d0002400240024002400240024020040e06000402030105000b200241f8006a41086a22042000410a6a290000370300200241f8006a41106a2205200041126a290000370300200241f8006a41186a22062000411a6a2900003703002002200041026a29000037037820002d0001450d21200241d8036a41186a2006290300370300200241d8036a41106a2005290300370300200241d8036a41086a2004290300370300200220022903783703d803410810012204450d43200220043602582002420837025c200241d8006a4100410810272002280258200228026022046a42f3cacdd3e38d9eba3a3700002002200441086a360260200241206a41086a200228026036020020022002290358370320412010012204450d43200220043602582002422037025c200241d8006a41004120102720022802582205200228026022066a22042001290000370000200441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a2900003700002002200641206a2201360260200228025c2106200241206a20022802282001102720022802202204200228022822076a20052001101e1a2002200720016a220136022802402006450d00200510020b20022802242105200241d8006a41086a220642003703002002420037035820042001200241d8006a1003200241c0006a41086a200629030037030020022002290358370340200241c0006a4110200241d8036a412010042005450d38200410020c380b200241d8036a41286a200041306a290300370300200241d8036a41206a200041286a290300370300200241d8036a41186a200041206a290300370300200241d8036a41106a200041186a290300370300200241d8036a41086a200041106a2903003703002002200041086a2903003703d803200241d8036a200110ae0141002101410121040c400b200041086a2903004200510d20200041106a2903002108200241f0036a4200370300200241d8036a41106a4200370300200241d8036a41086a4200370300200242003703d8030240200241d8036a2001460d002001200241d8036a412010060d270b200241d8006a41086a220142003703002002420037035841ad0b4107200241d8006a1003200241c0006a41086a2204200129030037030020022002290358370340200241c0006a411020024190076a410041001000417f470d21200142003703002002420037035841ed2d4107200241d8006a10032004200129030037030020022002290358370340200241c0006a411041d02d410041001000417f460d22200241003602d803200241c0006a4110200241d8036a41044100100041016a41044d0d1a20022802d8030d23200220083703d803200241d8006a41086a220142003703002002420037035841a90c4107200241d8006a1003200241c0006a41086a2205200129030037030020022002290358370340200241c0006a4110200241d8036a4108100441012104200241013a00d803200142003703002002420037035841ad0b4107200241d8006a10032005200129030037030020022002290358370340200241c0006a4110200241d8036a410110040c370b200241086a2205200041106a2903003703002002200041086a29030037030020022d000022044103714101460d0520044102460d0320044103470d2320022d0001210920022802042105410810012206450d40200220063602d803200242083702dc03200241d8036a41004108102720022802d80320022802e00322066a42e4cab5d383cedcb73a3700002002200641086a3602e003200241f8006a41086a20022802e003360200200220022903d803370378410410012206450d40200220063602d803200242043702dc03200241d8036a41004104102720022802d803220720022802e00322066a20053600002002200641046a22063602e00320022802dc03210a200241f8006a200228028001200610272002280278220b200228028001220c6a20072006101e1a2002200c20066a2206360280010240200a450d00200710020b200228027c2107200241d8006a41086a220a420037030020024200370358200b2006200241d8006a1003200241c0006a41086a200a29030037030020022002290358370340200241c0006a411020024190076a410041001000210602402007450d00200b10020b2006417f460d2620011043210820011044420020087d510d27200241e4036a200141086a290000370200200241ec036a200141106a290000370200200241f4036a200141186a290000370200200220053602d803200220012900003702dc03410810012206450d40200220063602782002420837027c200241f8006a410041081027200228027820022802800122066a42e4cab5d3e3ee9bba3a3700002002200641086a36028001200241d8006a41086a220620022802800136020020022002290378370358200241f8006a200241d8036a1045200228027c210c2002280278210b200241d8006a2006280200200228028001220710272002280258220a2006280200220d6a200b2007101e1a2006200d20076a22073602000240200c450d00200b10020b200228025c2106200241d8006a41086a220b420037030020024200370358200a2007200241d8006a1003200241c0006a41086a200b29030037030020022002290358370340200241c0006a411020024190076a410041001000210702402006450d00200a10020b2007417f470d3a20024190076a20051042200241d8036a41186a2207200141186a290000370300200241d8036a41106a220b200141106a290000370300200241d8036a41086a220a200141086a290000370300200220012900003703d8032002280298072206200228029407460d170c390b200241086a2204200041116a290000370300200241106a2205200041196a290000370300200241186a2206200041216a2900003703002002200041096a290000370300200041086a2d000041037122034101460d0520034103460d0320034102470d23200241d8006a41086a220342003703002002420037035841d61d4108200241d8006a1003200241c0006a41086a200329030037030020022002290358370340200241c0006a411041d02d410041001000417f460d122002421037027c2002200241c0006a360278200241d8036a200241f8006a103a20022802d8032206450d27200220022902dc0322083702242002200636022020062008422088a7220741057422036a210520034105754104490d06200621040340200120042203460d182003200141201006450d18200341206a22042001460d182004200141201006450d18200441206a22042001460d182004200141201006450d18200441206a22042001460d182004200141201006450d182005200441206a22046b41057541034b0d000b20034180016a22032005470d070c080b200241f8036a200041246a280200360200200241f0036a2000411c6a290200370300200241e8036a200041146a290200370300200241e0036a2000410c6a2902003703002002200041046a2902003703d803200241d8036a200110db014100210541012104410121010c3d0b200041106a2d00004102470d32419cc200103b000b200241d8036a20022802042205103720022802e003450d25200241d8006a41106a2206200241d8036a41106a290300370300200241d8006a41086a200241d8036a41086a290300370300200220022903d8033703582001200229035810b201450d26200241f8006a41186a2207200141186a290000370300200241f8006a41106a200141106a290000370300200241f8006a41086a200141086a2900003703002002200129000037037820062802002201200241e4006a280200460d110c340b200241d8006a41086a220342003703002002420037035841d61d4108200241d8006a1003200241c0006a41086a2003290300370300200220022903583703404100210b200241c0006a411041d02d410041001000417f460d052002421037027c2002200241c0006a360278200241d8036a200241f8006a103a20022802d8032205450d2c2005200241e0036a280200220941057422036a210720022802dc03210b20034105754104490d0620052106410021030340200120062204460d0a2003200420014120100622064100476a21032006450d0a200441206a22062001460d0a20032006200141201006220a4100476a2103200a450d0a200641206a22062001460d0a20032006200141201006220a4100476a2103200a450d0a200641206a22062001460d0a20032006200141201006220a4100476a2103200a450d0a2007200641206a22066b41057541034b0d000b20044180016a22042007470d070c080b20052903002108200220022802042206360220200241d8006a41086a220442003703002002420037035841a2294107200241d8006a1003200241c0006a41086a200429030037030020022002290358370340200241c0006a411041d02d410041001000417f460d25200242003703d803200241c0006a4110200241d8036a41084100100041016a41084d0d1420022903d8032008560d262001200810b201450d27200241d8006a41086a220442003703002002420037035841a9294107200241d8006a1003200241c0006a41086a200429030037030020022002290358370340410021050240200241c0006a411041d02d410041001000417f460d00200241003602d803200241c0006a4110200241d8036a41044100100041016a41044d0d1820022802d80321050b2002200541016a3602d803200241d8006a41086a220442003703002002420037035841a9294107200241d8006a1003200241c0006a41086a200429030037030020022002290358370340200241c0006a4110200241d8036a41041004412010012204450d3a200241e4036a428180808010370200200141086a2207290000210e200141106a220b290000210f20012900002110200441186a200141186a220a290000370000200441106a200f370000200441086a200e37000020042010370000200220083703d803200220043602e0032005200241d8036a10df01200241d8006a1036200241d8036a200610e001200241f8006a41186a2206200a290000370300200241f8006a41106a200b290000370300200241f8006a41086a20072900003703002002200129000037037820022802602204200228025c460d100c310b200041306a2903002108200241206a41186a2006290300370300200241206a41106a2005290300370300200241206a41086a20042903003703002002200229030037032041d02d200110c60122112008540d2741d02d200241206a10c601210e410810012203450d39200220033602d803200242083702dc03200241d8036a41004108102720022802d80320022802e00322036a42f3e885d3a3ec9bb73a3700002002200341086a3602e003200241f8006a41086a20022802e003360200200220022903d803370378412010012203450d39200220033602d803200242203702dc03200241d8036a41004120102720022802d803220420022802e00322056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a22033602e00320022802dc032106200241f8006a200228028001200310272002280278220520022802800122076a20042003101e1a2002200720036a22033602800102402006450d00200410020b200228027c21044200210f200241d8006a41086a220642003703002002420037035820052003200241d8006a1003200241c0006a41086a2006290300370300200220022903583703400240200241c0006a411041d02d410041001000417f460d00200242003703d803200241c0006a4110200241d8036a41084100100041016a41084d0d1520022903d803210f0b02402004450d00200510020b410810012203450d39200220033602d803200242083702dc03200241d8036a41004108102720022802d80320022802e00322036a42f3e885d3a3ec9bb73a3700002002200341086a3602e003200241f8006a41086a20022802e003360200200220022903d803370378412010012203450d39200220033602d803200242203702dc03200241d8036a41004120102720022802d803220420022802e00322056a22032002290320370000200341086a200241206a41086a290300370000200341106a200241206a41106a290300370000200341186a200241206a41186a2903003700002002200541206a22033602e00320022802dc032106200241f8006a200228028001200310272002280278220520022802800122076a20042003101e1a2002200720036a22033602800102402006450d00200410020b200228027c210442002110200241d8006a41086a220642003703002002420037035820052003200241d8006a1003200241c0006a41086a2006290300370300200220022903583703400240200241c0006a411041d02d410041001000417f460d00200242003703d803200241c0006a4110200241d8036a41084100100041016a41084d0d1620022903d80321100b02402004450d00200510020b200f2010560d28200e20087c220f200e580d2941a00610012203450d392003200241d8036a41b803101e220341003b01be03200341003602b803200341c0036a200241f8006a41e002101e1a200241c8006a4200370300200241d4006a41d43c3602002002200336024420024100360240200241d02d360250200241206a2001460d0b2001200241206a41201006450d0b2002417f360240200241d8036a41186a2207200141186a290000370300200241d8036a41106a220b200141106a290000370300200241d8036a41086a220a200141086a290000370300200220012900003703d8032002200241c0006a41047222043602602002200241c0006a41086a2802003602582002200228024436025c200241f8006a200241d8006a200241d8036a10970141012103200241f8006a41106a2802002105200241f8006a410c6a2802002109200241f8006a41086a2802002106200228027c210c024020022802784101470d00200241d8006a41186a2007290300370300200241d8006a41106a200b290300370300200241d8006a41086a200a290300370300200220022903d803370358410021030b41900210012201450d39201120087d21082001200241d8036a418802101e220141003b018e0220014100360288022003450d09200220013602782002420037027c2006200541286c6a2101200241d8036a200241f8006a109801200241d8036a1099010c0a0b200622032005460d010b200620074105746a2104034020012003460d102003200141201006450d102004200341206a2203470d000b0b200241d8036a41186a200141186a290000370300200241d8036a41106a200141106a290000370300200241d8036a41086a200141086a290000370300200220012900003703d803200241d8036a210320072008a7460d0a0c290b41012105410021094100210341000d270c040b41002103200522042007460d010b034020012004460d022003200420014120100622064100476a21032006450d022007200441206a2204470d000b0b4100450d010c240b41010d230b41dc3b103b000b200241f4036a200241e0006a290300370200200241fc036a200241e8006a29030037020020024184046a200241f0006a290300370200200220063602dc032002200c3602d803200220093602e003200220053602e4032002200241c0006a410c6a3602e803200220022903583702ec0320024198016a42003703002002410036028801200242003703782002200136029401200241d8036a200241f8006a109a0121010b20014201370300200120083703082002417f360240200241d8036a41186a2201200241206a41186a290300370300200241d8036a41106a2206200241206a41106a290300370300200241d8036a41086a2207200241206a41086a290300370300200220022903203703d803200220043602602002200241c0006a41086a2802003602582002200228024436025c200241f8006a200241d8006a200241d8036a10970141012103200241f8006a41106a2802002104200241f8006a410c6a280200210b200241f8006a41086a2802002105200228027c210a024020022802784101470d00200241d8006a41186a2001290300370300200241d8006a41106a2006290300370300200241d8006a41086a2007290300370300200220022903d803370358410021030b41900210012201450d2e2001200241d8036a418802101e220141003b018e022001410036028802024002402003450d00200220013602782002420037027c2005200441286c6a2101200241d8036a200241f8006a109801200241d8036a1099010c010b200241f4036a200241e0006a290300370200200241fc036a200241e8006a29030037020020024184046a200241f0006a290300370200200220053602dc032002200a3602d8032002200b3602e003200220043602e4032002200241c0006a410c6a3602e803200220022903583702ec0320024198016a42003703002002410036028801200242003703782002200136029401200241d8036a200241f8006a109a0121010b200142013703002001200f370308200241003602400b200241d8036a200241c0006a200241206a109b010240024020022802e0032201450d0020022802d80322032001200241206a200241c0006a108e01450d010b200241c8006a290300210820022802442101024020022802dc03450d0020022802d80310020b2001450d22200220083702dc03200220013602d80320024190076a200241d8036a10c7010c220b200241c0006a4104722101024020022802dc03450d00200310020b200241f8006a41086a200141086a28020036020020022001290200370378200241d8036a200241f8006a109d01200241d8036a109e010c210b2002410036022820024201370320200241d8036a41186a200141186a290000370300200241d8036a41106a200141106a290000370300200241d8036a41086a200141086a290000370300200220012900003703d803200241d8036a21030b200241206a107c200241286a2802002107200228022021060c1e0b200241e0006a107c200241e8006a28020021010c220b200241d8006a1074200241e0006a28020021040c200b20024190076a107c20024190076a41086a28020021060c210b41c43b103b000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b418431103b000b41dc32103b000b418c33103b000b41f4214122102d000b41a433103b000b419cc000103b000b41f43b103b000b41f432103b000b41fcc000103b000b4194c100103b000b41c1214133102d000b41b0294124102d000b41e4c000103b000b41f4214122102d000b41b4c000103b000b41ccc000103b000b418c3c103b000b41a43c103b000b41bc3c103b000b41c1214133102d000b200241d8036a41186a2206200520034105746a220341186a2207290000370300200241d8036a41106a220a200341106a220c290000370300200241d8036a41086a220d200341086a2212290000370300200220032900003703d80320052009417f6a22094105746a22042900002108200441086a2213290000210e200441106a2214290000210f2007200441186a2215290000370000200c200f3700002012200e37000020032008370000200420022903d8033700002013200d2903003700002014200a290300370000201520062903003700002002200b36027c200220053602782002200936028001200241d8036a200241f8006a10a20120022802e003210420022802d8032103200241d8006a41086a220642003703002002420037035841d61d4108200241d8006a1003200241c0006a41086a200629030037030020022002290358370340200241c0006a4110200320041004024020022802dc03450d00200310020b0240200b450d00200510020b200241d8006a41086a220342003703002002420037035841c81d4107200241d8006a1003200241c0006a41086a20032903003703002002200229035837034002400240200241c0006a411041d02d410041001000417f460d00200242003703d80302400240200241c0006a4110200241d8036a41084100100041016a41084d0d0020022903d8032108200241d8006a41086a220342003703002002420037035841d21e4107200241d8006a1003200241c0006a41086a200329030037030020022002290358370340200241c0006a411041d02d410041001000417f460d03200242003703d803200241c0006a4110200241d8036a41084100100041016a41084d0d01200120022903d80320087c10c5010c050b41c1214133102d000b41c1214133102d000b41f4214122102d000b41f4214122102d000b200341086a2900002108200341106a290000210e200341186a290000210f200620074105746a22042003290000370000200441186a200f370000200441106a200e370000200441086a2008370000200241206a41086a2203200741016a360200200241f8006a41086a200328020036020020022002290320370378200241d8036a200241f8006a10a20120022802e003210420022802d8032103200241d8006a41086a220542003703002002420037035841d61d4108200241d8006a1003200241c0006a41086a200529030037030020022002290358370340200241c0006a4110200320041004024020022802dc03450d00200310020b0240200228027c450d00200228027810020b2001427f10c5010b20002d000021030b410121040b410121010c070b2002280258200441d8006c6a220120022903d8033703002001200536023020012002290378370234200141086a200241d8036a41086a2205290300370300200141106a200241d8036a41106a290300370300200141186a200241d8036a41186a290300370300200141206a200241d8036a41206a290300370300200141286a200241d8036a41286a2903003703002001413c6a200241f8006a41086a290300370200200141c4006a200241f8006a41106a290300370200200141cc006a2006290300370200200241d8006a41086a2201200441016a36020020052001280200360200200220022903583703d803200241d8036a103e20022802d8032106024020052802002201450d00200141d8006c210420062101034020011038200141d8006a2101200441a87f6a22040d000b0b024020022802dc03450d00200610020b200241206a10220c050b200241d8006a41106a2206200141016a360200200241d8006a41086a220b28020020014105746a22012002290378370000200141086a200241f8006a41086a290300370000200141106a200241f8006a41106a290300370000200141186a2007290300370000200241d8036a41106a2006290300370300200241d8036a41086a200b290300370300200220022903583703d8032005200241d8036a10df010c020b20024190076a41086a220c200641016a360200200a2903002108200b290300210e2007290300210f20022802900720064105746a220620022903d803370000200641186a200f370000200641106a200e370000200641086a2008370000200241206a41086a200c2802003602002002200229039007370320410810012206450d06200220063602d803200242083702dc03200241d8036a41004108102720022802d80320022802e00322066a42e4cab5d3e38e9db93a3700002002200641086a3602e003200241f8006a41086a20022802e003360200200220022903d803370378410410012206450d06200220063602d803200242043702dc03200241d8036a41004104102720022802d803220720022802e00322066a20053600002002200641046a22063602e00320022802dc03210a200241f8006a200228028001200610272002280278220b200228028001220c6a20072006101e1a2002200c20066a220c360280010240200a450d00200710020b200228027c2107200241d8036a200241206a10a20120022802e003210a20022802d8032106200241d8006a41086a220d420037030020024200370358200b200c200241d8006a1003200241c0006a41086a200d29030037030020022002290358370340200241c0006a41102006200a1004024020022802dc03450d00200610020b02402007450d00200b10020b2002280224450d00200228022010020b200241e4036a200141086a290000370200200241ec036a200141106a290000370200200241f4036a200141186a290000370200200220053602d803200220012900003702dc03200220093a0020410810012201450d05200220013602782002420837027c200241f8006a410041081027200228027820022802800122016a42e4cab5d3e3ee9bba3a3700002002200141086a36028001200241d8006a41086a220120022802800136020020022002290378370358200241f8006a200241d8036a1045200228027c210b20022802782106200241d8006a200128020020022802800122051027200228025822072001280200220a6a20062005101e1a2001200a20056a22053602000240200b450d00200610020b200228025c2101200241d8006a41086a220642003703002002420037035820072005200241d8006a1003200241c0006a41086a200629030037030020022002290358370340200241c0006a4110200241206a410110042001450d002007100220044101460d010c020b20044101470d010b200241047210220b41012101410021040b410121050b2003411d74411d75417f4a0d0102400240200341077122034104460d0020034105470d012001450d03200041086a2d00004101470d03200041106a280200450d032000410c6a2802001002200241a0076a24000f0b2004450d02200041086a2d00004101470d022000410c6a104b200241a0076a24000f0b2005450d01200041046a2d00004101470d01200041086a104b200241a0076a24000f0b101c000b200241a0076a24000b080041ec3a1054000b080041ec3a1054000bfe2507097f027e0a7f027e067f017e0d7f230041d0026b220424000240024020014115490d0041012105410121060240024002400340200620057121070340024002402003450d0020054101710d012000200110e1012003417f6a21030c010b2000200110e201200441d0026a24000f0b2001410276220641036c2108200641017421094100210a024020014132490d0020082008417f6a220b2000200841286c6a220c41586a290300220d200c290300220e54220a1b220f200841016a200b2008200a1b200d200e200a1b220d200c41286a290300220e5422101b2000200f41286c6a290300200e200d20101b5422111b210820092009417f6a220c2000200941286c6a220b41586a290300220d200b290300220e54220b1b22122009410172220f200c2009200b1b200d200e200b1b220d2000200f41286c6a290300220e54220f1b2000201241286c6a290300200e200d200f1b5422131b210920062006417f6a22142000200641286c6a221241586a290300220d2012290300220e54220c1b2215200641016a20142006200c1b200d200e200c1b220d201241286a290300220e5422121b2000201541286c6a290300200e200d20121b5422141b210641024101200c1b200c20121b20146a200b6a200f6a20136a200a6a20106a20116a210a0b200a2000200641286c6a290300220d2000200941286c6a290300220e54220c6a200d200e200c1b220d2000200841286c6a290300220e54220b6a210a0240024002400240200020092006200c1b221641286c6a290300200e200d200b1b5a0d00200a41016a220a410b4b0d012007200a45714101470d030c020b200820062009200c1b200b1b21162007200a45714101470d020c010b2001417f6a2117024020014101762208450d002000200141286c6a41586a2106200021090340200441a8016a41206a220c200941206a220a290300370300200441a8016a41186a220b200941186a2210290300370300200441a8016a41106a220f200941106a2212290300370300200441a8016a41086a2211200941086a2213290300370300200420092903003703a801200641086a2214290300210d200641106a2215290300210e200641186a221829030021192006290300211a200a200641206a221b290300370300201020193703002012200e3703002013200d3703002009201a370300201b200c2903003703002018200b2903003703002015200f29030037030020142011290300370300200620042903a801370300200941286a2109200641586a21062008417f6a22080d000b0b201720166b211620074101714101470d010b2000200110e3010d070b024002400240024002402002450d00201620014f0d092000201641286c6a22062903002002290300540d00200441a8016a41206a220a200041206a2212290300370300200441a8016a41186a220b200041186a2211290300370300200441a8016a41106a2210200041106a2213290300370300200441a8016a41086a220f200041086a2209290300370300200420002903003703a801200641086a2208290300210d200641106a220c290300210e200641186a221429030021192006290300211a2012200641206a2215290300370300201120193703002013200e3703002009200d3703002000201a3703002015200a2903003703002014200b290300370300200c20102903003703002008200f290300370300200620042903a8013703002000290300210d200441086a41186a221c2012290300370300200441086a41106a221d2011290300370300200441086a41086a221e201329030037030020042009290300370308200041286a21144100210841002001417f6a22094f0d010c020b201620014f0d07200441a8016a41206a2224200041206a2205290300370300200441a8016a41186a2225200041186a2226290300370300200441a8016a41106a2227200041106a2228290300370300200441a8016a41086a2229200041086a222a290300370300200420002903003703a8012000201641286c6a2206290300210d200641086a2209290300210e200641106a22082903002119200641186a220c290300211a2005200641206a220a2903003703002026201a37030020282019370300202a200e3703002000200d370300200a2024290300370300200c20252903003703002008202729030037030020092029290300370300200620042903a8013703002000290300210d200441086a41186a222b2005290300370300200441086a41106a222c2026290300370300200441086a41086a222d20282903003703002004202a2903003703082001417f6a210941002120200041286a2208210602400340200d20062903005a0d01200641286a2106202041016a22202009490d000b0b200921070240200920204d0d002000200141286c6a41586a2106200921070340200d2006290300540d01200641586a21062007417f6a220720204b0d000b0b20072020490d0620092007490d032008200741286c6a210b41800121164100210a410021154100210c4100211441800121172008202041286c6a222e21180340200b20186b220641286e21090240024002400240024002400240200641a7d0004b221f0d00200941807f6a20092015200a492014200c4922087222101b21062010450d012017200620081b21172006201620081b21160b2014200c470d020c010b2006200641017622176b21162014200c470d010b2017450d0141002106200441286a2214210c201821090340200c20063a0000200c200d20092903005a6a210c200941286a2109200641016a22062017490d000b0b2015200a470d020c010b200441286a220c21142015200a470d010b02402016450d00200b41586a210641002109200441a8016a2215210a0340200a20093a0000200a200d2006290300546a210a200641586a2106200941016a22092016490d000c020b0b200441a8016a220a21150b0240200a20156b2206200c20146b2209200920064b1b221b450d00200441a8026a41206a2222201820142d000041286c6a220641206a290300370300200441a8026a41186a221c200641186a290300370300200441a8026a41106a221d200641106a290300370300200441a8026a41086a221e200641086a290300370300200420062903003703a802201820142d000041286c6a2206200b20152d00002210417f7341286c6a2209290300370300200641206a200941206a290300370300200641186a200941186a290300370300200641106a200941106a290300370300200641086a200941086a2903003703000240201b4101460d00410021080340200b2010417f7341807e7241286c6a22092018201420086a41016a2d000041286c6a2206290300370300200941206a200641206a220f290300370300200941186a200641186a2212290300370300200941106a200641106a2211290300370300200941086a200641086a22132903003703002006200b201520086a41016a2d00002210417f7341286c6a2209290300370300200f200941206a2903003703002012200941186a2903003703002011200941106a2903003703002013200941086a290300370300200841026a2106200841016a220f21082006201b490d000b2015200f6a21152014200f6a21140b200920042903a802370300200941206a2022290300370300200941186a201c290300370300200941106a201d290300370300200941086a201e290300370300201541016a2115201441016a21140b2018201741286c6a20182014200c461b2118200b410020166b41286c6a200b2015200a461b210b201f0d000b024002402014200c4f0d00200b41586a2106200c21080340200441a8026a41206a220a20182008417f6a22082d000041286c6a220941206a2210290300370300200441a8026a41186a220f200941186a2212290300370300200441a8026a41106a2211200941106a2213290300370300200441a8026a41086a2215200941086a221b290300370300200420092903003703a802200641086a2216290300210e200641106a22172903002119200641186a221f290300211a200629030021212010200641206a22222903003703002012201a37030020132019370300201b200e370300200920213703002022200a290300370300201f200f2903003703002017201129030037030020162015290300370300200620042903a802370300200641586a210620142008490d000b200b2014200c6b41286c6a21180c010b20182106200a21082015200a4f0d0003402008417f6a22082d00002109200441a8026a41206a220c200641206a2210290300370300200441a8026a41186a220f200641186a2212290300370300200441a8026a41106a2211200641106a2213290300370300200441a8026a41086a2214200641086a221b290300370300200420062903003703a802200b2009417f7341286c6a2209290300210e200941086a22162903002119200941106a2217290300211a200941186a221f29030021212010200941206a2222290300370300201220213703002013201a370300201b20193703002006200e3703002022200c290300370300201f200f2903003703002017201129030037030020162014290300370300200920042903a802370300200641286a210620152008490d000b2018200a20156b41286c6a21180b2000200d3703002005202b2903003703002026202c2903003703002028202d290300370300200020042903083703080240024020012018202e6b41286e20206a22094d0d002024200529030037030020252026290300370300202720282903003703002029202a290300370300200420002903003703a8012000200941286c6a2206290300210d200641086a2208290300210e200641106a220c2903002119200641186a220a290300211a2005200641206a220b2903003703002026201a37030020282019370300202a200e3703002000200d370300200b2024290300370300200a2025290300370300200c202729030037030020082029290300370300200620042903a801370300200120096b2208450d0120082009200920084b1b210c2001410376210a200641286a210b0240024020092008417f6a22014f0d00200020092002200310c40120062102200b21000c010b200b20012006200310c401200921010b200c200a4f2105200720204d2106200141154f0d070c0b0b41b4c20020092001103c000b41c4c200103b000b410021230c010b410621230b03400240024002400240024002400240024002400240024002400240024002400240024020230e0a04080905060001020307070b200a2014200841286c6a220c41206a2215290300370300200b200c41186a22182903003703002010200c41106a221b290300370300200f200c41086a22162903003703002004200c2903003703a801200641086a2217290300210e200641106a221f2903002119200641186a2220290300211a200629030021212015200641206a22222903003703002018201a370300201b20193703002016200e370300200c20213703002022200a2903003703002020200b290300370300201f20102903003703002017200f290300370300200620042903a801370300200841016a22082009417f6a22094f0d0d410621230c100b2014200841286c6a2106410721230c0f0b2006290300200d540d0a410821230c0e0b200641286a2106200841016a22082009490d08410021230c0d0b200820094f0d06410321230c0c0b2000200941286c6a2106410421230c0b0b2006290300200d5a0d09410921230c0a0b200641586a210620082009417f6a2209490d07410121230c090b2000200d3703002012201c2903003703002011201d2903003703002013201e290300370300200020042903083703082001200841016a2206490d01410221230c080b2000200641286c6a2100200120066b220141154f0d090c0e0b200620011055000b410121230c050b410721230c040b410021230c030b410021230c020b410421230c010b410521230c000b0b0b0b200720091029000b202020071055000b41b4c20020162001103c000b41dcc20020162001103c000b20014102490d002000210a410121090340200941016a210c02402000200941286c6a220641586a22082903002006290300220d5a0d00200441086a41186a2210200641206a220b290300370300200441086a41106a220f200641186a2212290300370300200441086a41086a2211200641106a22132903003703002004200629030837030820062008290300370300200641086a200841086a2903003703002013200841106a2903003703002012200841186a290300370300200b200841206a2903003703004100210b0240024002402009417f6a2208450d00200a21060340200641586a2209290300200d5a0d02200641206a200641786a290300370300200641186a200641706a290300370300200641106a200641686a290300370300200641086a200641606a29030037030020062009290300370300200921062008417f6a22080d000b200921060c020b2000200841286c6a21060c010b2008210b0b2006200d3703002000200b41286c6a22062004290308370308200641206a2010290300370300200641186a200f290300370300200641106a20112903003703000b200a41286a210a200c2109200c2001490d000b0b200441d0026a24000b9a0301057f230041306b220224000240410810012203450d002002200336022020024208370224200241206a4100410810272002280220200228022822036a42f3e885d3a3ec9bb73a3700002002200341086a360228200241106a41086a200228022836020020022002290320370310412010012203450d002002200336022020024220370224200241206a41004120102720022802202204200228022822056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002002200541206a220036022820022802242105200241106a20022802182000102720022802102203200228021822066a20042000101e1a2002200620006a220036021802402005450d00200410020b2002280214210420022001370308200241206a41086a220542003703002002420037032020032000200241206a1003200241106a41086a200529030037030020022002290320370310200241106a4110200241086a4108100402402004450d00200310020b200241306a24000f0b101c000bc70302057f017e230041206b220224000240410810012203450d002002200336021020024208370214200241106a4100410810272002280210200228021822036a42f3e885d3a3ac98b63a3700002002200341086a360218200241086a200228021836020020022002290310370300412010012203450d002002200336021020024220370214200241106a41004120102720022802102204200228021822056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a220136021820022802142105200220022802082001102720022802002203200228020822066a20042001101e1a2002200620016a220136020802402005450d00200410020b2002280204210442002107200241106a41086a220542003703002002420037031020032001200241106a1003200241086a200529030037030020022002290310370300024002402002411041d02d410041001000417f460d002002420037031020024110200241106a41084100100041016a41084d0d01200229031021070b02402004450d00200310020b200241206a240020070f0b41c1214133102d000b101c000ba11105027f017e0e7f017e0b7f230041b0036b2202240020024188016a41086a2203200141086a2802003602002002200129020037038801200241086a20024188016a109d01200241306a41206a200241086a41206a280200360200200241306a41186a200241086a41186a290300370300200241306a41106a200241086a41106a290300370300200241306a41086a200241086a41086a2903003703002002200229030837033020024188016a200241306a10c8010240024020022903a80122044202510d00200241f0016a4104722105200241c0016a210620024188016a41206a2107200241b0016a2108200241b8016a2109200241bc016a210a20024194016a210b2002419c016a210c200241ac016a210d0340200241e8006a41186a220120024188016a41186a220e290300370300200241e8006a41106a220f20024188016a41106a2210290300370300200241e8006a41086a22112003290300370300200241d8006a41086a2212200641086a2903003703002002200229038801370368200220062903003703582008290300211320092802002114200a2802002115200241d0016a41186a22162001290300370300200241d0016a41106a2217200f290300370300200241d0016a41086a22182011290300370300200220022903683703d001200241f0016a41086a2012290300370300200220022903583703f001024020044201520d00410810012201450d0320022001360288012002420837028c0120024188016a41004108102720032003280200220141086a36020020012002280288016a42f3e885d3a3ac98b63a370000200241a8026a41086a2201200328020036020020022002290388013703a80241201001220f450d032002200f360288012002422037028c0120024188016a41004120102720032003280200221141206a220f360200201120022802880122126a221120022903d001370000201141086a2018290300370000201141106a2017290300370000201141186a2016290300370000200228028c012119200241a8026a2001280200200f102720022802a80222112001280200221a6a2012200f101e1a2001201a200f6a220f36020002402019450d00201210020b20022802ac022101200220133703880120024190036a41086a2212420037030020024200370390032011200f20024190036a100320024180036a41086a201229030037030020022002290390033703800320024180036a411020024188016a410810042001450d00201110020b024002402014450d00200320022802f0013602002002201536028c012002201436028801200241d0016a20024188016a10c9014101211b2015450d01201410020c010b4100211b0b2003200541086a280200360200200220052902003703880120024180026a20024188016a109801200241a8026a41206a20024180026a41206a280200360200200241a8026a41186a20024180026a41186a290300370300200241a8026a41106a20024180026a41106a290300370300200241a8026a41086a20024180026a41086a29030037030020022002290380023703a80220024188016a200241a8026a10ca010240200228028801450d000340200241d0026a41086a2201200328020036020020022002290388013703d002200b280200211120102802002112200c2802002119200241e0026a41086a220f2001280200360200200220022903d0023703e002024002402011450d00200241f0026a41086a2019360200200220123602f402200220113602f002200e20162903003703002010201729030037030020032018290300370300200720022903e002370200200741086a200f280200360200200220022903d00137038801410810012201450d062002200136029003200242083702940320024190036a41004108102720024190036a41086a22012001280200220f41086a360200200f2002280290036a42f3e885d3b38eddb73a37000020024180036a41086a220f200128020036020020022002290390033703800320024190036a20024188016a10cb01200228029403211c200228029003211a20024180036a200f280200200128020022191027200228028003221d200f280200221e6a201a2019101e1a200f201e20196a221e3602000240201c450d00201a10020b200228028403211a200241a0036a200241f0026a1051200241a0036a41086a280200211c20022802a0032119200142003703002002420037039003201d201e20024190036a1003200f200129030037030020022002290390033703800320024180036a41102019201c1004024020022802a403450d00201910020b0240201a450d00201d10020b0240200d280200450d00200728020010020b2012450d01201110020c010b200720022903e002370200200e20162903003703002010201729030037030020032018290300370300200741086a200f280200360200200220022903d00137038801410810012201450d052002200136029003200242083702940320024190036a41004108102720024190036a41086a22012001280200220f41086a360200200f2002280290036a42f3e885d3b38eddb73a37000020024180036a41086a220f200128020036020020022002290390033703800320024190036a20024188016a10cb01200228029403211a200228029003211220024180036a200f2802002001280200221110272002280280032219200f280200221d6a20122011101e1a200f201d20116a22113602000240201a450d00201210020b20022802840321122001420037030020024200370390032019201120024190036a1003200f200129030037030020022002290390033703800320024180036a4110100502402012450d00201910020b200d280200450d00200728020010020b20024188016a200241a8026a10ca012002280288010d000b0b200241a8026a1099010240201b201445720d002015450d00201410020b20024188016a200241306a10c801200729030022044202520d000b0b200241306a109e01200241b0036a24000f0b101c000bc10b03087f017e027f230041d0016b220224000240024020012802202203450d00200141206a2003417f6a36020020012802082104200128020c2203200128020422052f01be034f0d01200241306a41186a2206200520034105746a220741d8036a290000370300200241306a41106a2208200741d0036a290000370300200241306a41086a2209200741c8036a2900003703002002200741c0036a290000370330200141046a2005360200200141086a20043602002001410c6a200341016a360200200241d0006a41206a22072005200341286c6a220341206a290300370300200241d0006a41186a2205200341186a290300370300200241d0006a41106a2204200341106a290300370300200241d0006a41086a2201200341086a29030037030020022003290300370350200241f8006a41186a2006290300370300200241f8006a41106a2008290300370300200241f8006a41086a2009290300370300200241f8006a41286a2001290300370300200241a8016a2004290300370300200241b0016a2005290300370300200241b8016a20072903003703002002200229033037037820022002290350370398012000200241f8006a41c800101e1a200241d0016a24000f0b20004202370320200241d0016a24000f0b200128020021070240024020052802b8032203450d0020053201bc03210a2002200336027c2002200741016a22073602782002200a4220862004ad84220a370380010c010b2004ad210a410021030b20051002200241106a220820033602002002200736020c02400240200a422088a7220520032f01be034f0d00200241186a2005360200200241146a200a3e020020024100360208200241086a410472210b200241206a21070c010b200241146a2209200a37020020024101360208200aa72104200241086a410472210b200241186a210c2003210503400240024020032802b8032206450d00200741016a210720033201bc034220862004ad84210a200621030c010b2004ad210a410021030b024020051002200820033602002002200736020c0240200a422088a7220520032f01be034f0d00200c20053602002009200aa72204360200200241003602082003210541000d020c010b2009200a370200200aa72104200241013602082003210541010d010b0b200241206a21070b2007200b290200370200200741086a200b41086a290200370200200241306a41086a20022802242206200228022c22084105746a220341c8036a290000370300200241306a41106a200341d0036a290000370300200241306a41186a200341d8036a2900003703002002200341c0036a290000370330200241d0006a41206a2006200841286c6a220341206a290300370300200241d0006a41186a200341186a290300370300200241d0006a41106a200341106a290300370300200241d0006a41086a200341086a290300370300200220032903003703502007280200210920022802282105200241f8006a41086a2204200620084102746a41a4066a280200220736020020024184016a2206200536020020022009417f6a220336027c20022003410047360278024002402003450d002009417e6a2103200241f8006a41047221080340200420072802a0062207360200200620053602002002200336027c200220034100473602782003417f6a2203417f470d000c020b0b200241f8006a41047221080b200120082902003702002001410c6a4100360200200141086a200841086a280200360200200241f8006a41186a200241306a41186a290300370300200241f8006a41106a200241306a41106a290300370300200241f8006a41086a200241306a41086a290300370300200241a0016a200241d0006a41086a290300370300200241a8016a200241d0006a41106a290300370300200241b0016a200241d0006a41186a290300370300200241b8016a200241f0006a2903003703002002200229033037037820022002290350370398012000200241f8006a41c800101e1a200241d0016a24000bb30301057f230041306b220224000240410810012203450d002002200336022020024208370224200241206a4100410810272002280220200228022822036a42f3e885d3b3ec9bb23a3700002002200341086a360228200241106a41086a200228022836020020022002290320370310412010012203450d002002200336022020024220370224200241206a41004120102720022802202204200228022822056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002002200541206a220036022820022802242105200241106a20022802182000102720022802102203200228021822066a20042000101e1a2002200620006a220636021802402005450d00200410020b200228021421042002200110512002280208210120022802002100200241206a41086a220542003703002002420037032020032006200241206a1003200241106a41086a200529030037030020022002290320370310200241106a411020002001100402402002280204450d00200010020b02402004450d00200310020b200241306a24000f0b101c000bba0803057f017e057f230041f0006b220224000240024020012802202203450d00200141206a2003417f6a36020020012802082104200128020c2203200128020422052f018e024f0d01200141046a2005360200200141086a20043602002001410c6a200341016a360200200241086a220620052003410c6c6a220341086a28020036020020022003290200370300200241c8006a41086a22052006280200360200200241dc006a2003418c016a280200360200200020022903002207370200200220034184016a290200370254200041086a2005290300370200200041106a200241c8006a41106a29030037020020022007370348200241f0006a24000f0b20004100360200200241f0006a24000f0b20012802002106024002402005280288022203450d00200532018c0221072002200336024c2002200641016a2206360248200220074220862004ad8422073703500c010b2004ad2107410021030b20051002200241086a2208200336020020022006360204024002402007422088a7220520032f018e024f0d00200241106a20053602002002410c6a20073e02002002410036020020024104722109200241186a21060c010b2002410c6a220a2007370200200241013602002007a7210420024104722109200241106a210b20032105034002400240200328028802220c450d00200641016a2106200332018c024220862004ad842107200c21030c010b2004ad2107410021030b024020051002200820033602002002200636020402402007422088a7220520032f018e024f0d00200b2005360200200a2007a72204360200200241003602002003210541000d020c010b200a20073702002007a72104200241013602002003210541010d010b0b200241186a21060b20062009290200370200200641086a200941086a290200370200200241286a41086a200228021c220c2002280224220a410c6c6a220341086a28020036020020022003290200370328200241386a41086a2003418c016a280200360200200220034184016a2902003703382006280200210820022802202105200241c8006a41086a2204200c200a4102746a4194026a2802002206360200200241c8006a410c6a220c200536020020022008417f6a220336024c20022003410047360248024002402003450d002008417e6a2103200241c8006a4104722108034020042006280290022206360200200c20053602002002200336024c200220034100473602482003417f6a2203417f470d000c020b0b200241c8006a41047221080b200120082902003702002001410c6a4100360200200141086a200841086a280200360200200241c8006a41086a2203200241286a41086a280200360200200241dc006a200241386a41086a28020036020020002002290328220737020020022002290338370254200041086a2003290300370200200041106a200241c8006a41106a29030037020020022007370348200241f0006a24000bda0201057f230041206b22022400200241003602082002420137030020024100412010272002280200200228020822036a22042001290000370000200441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a2900003700002002200341206a2205360208200241106a200141206a1051200228021021032002200520022802182204102720022004200228020822066a22013602082006200228020022056a20032004101e1a02402002280214450d00200310020b02402001417f4c0d00024002402001450d002001100122040d01101c000b410121040b200220013602142002200436021020024100360218200241106a41002001102720022002280218220420016a360218200420022802106a20052001101e1a200041086a20022802183602002000200229031037020002402002280204450d00200510020b200241206a24000f0b1019000b02000be90502047f017e230041d0006b220524000240024002402004417f4c0d000240024002402004450d002004100122060d010c020b410121060b200520043602042005200636020020054100360208200541002004102720052005280208220620046a360208200620052802006a20032004101e1a200541c0006a41086a2204200528020836020020052005290300370340200541186a200241186a290000370300200541106a200241106a290000370300200541086a200241086a290000370300200541286a20042802003602002005200229000037030020052005290340370320410810012204450d002005200436024020054208370244200541c0006a4100410810272005280240200528024822046a42f3e885d3b38eddb73a3700002005200441086a360248200541306a41086a2204200528024836020020052005290340370330200541c0006a200510cb012005280244210720052802402103200541306a200428020020052802482202102720052802302206200428020022086a20032002101e1a2004200820026a220236020002402007450d00200310020b20052802342103200541c0006a41086a220442003703002005420037034020062002200541c0006a1003200541306a41086a20042903003703002005200529034037033002400240024002400240200541306a411041d02d410041001000417f460d00200541003602404100200541306a4110200541c0006a41044100100022042004417f461b220741034d0d0820052802402204417f4c0d062004450d01200410012202450d0520024100200410171a0c020b2000410036020020030d020c030b410121020b20044100200541306a4110200220042007410420074104491b100022072007417f461b4b0d042002450d0520002004ad2209422086200984370204200020023602002003450d010b200610020b0240200541246a280200450d00200541206a28020010020b200541d0006a24000f0b101c000b1019000b200210020b41c1214133102d000bd50402057f017e230041206b220324000240024002400240410810012204450d002003200436021020034208370214200341106a4100410810272003280210200328021822046a42f3e885d3b3ec9bb23a3700002003200441086a360218200341086a200328021836020020032003290310370300412010012204450d002003200436021020034220370214200341106a41004120102720032802102205200328021822066a22042002290000370000200441086a200241086a290000370000200441106a200241106a290000370000200441186a200241186a2900003700002003200641206a220236021820032802142104200320032802082002102720032802002206200328020822076a20052002101e1a2003200720026a220236020802402004450d00200510020b20032802042105200341106a41086a220442003703002003420037031020062002200341106a1003200341086a200429030037030020032003290310370300024002400240024002402003411041d02d410041001000417f460d0020034100360210410020034110200341106a41044100100022022002417f461b220741034d0d0820032802102202417f4c0d062002450d01200210012204450d0520044100200210171a0c020b200041003602082000420137020020050d020c030b410121040b2002410020034110200420022007410420074104491b100022072007417f461b4b0d042004450d0520002002ad2208422086200884370204200020043602002005450d010b200610020b200341206a24000f0b101c000b1019000b200410020b41c1214133102d000ba90701047f230041f0006b220424000240024002402003280200450d00200441086a200341086a28020036020020042003290200370300200441106a41186a200141186a290000370300200441106a41106a200141106a290000370300200441106a41086a200141086a290000370300200441386a200241086a2802003602002004200129000037031020042002290200370330410810012201450d022004200136025020044208370254200441d0006a4100410810272004280250200428025822016a42f3e885d3b38eddb73a3700002004200141086a360258200441c0006a41086a2201200428025836020020042004290350370340200441d0006a200441106a10cb012004280254210520042802502102200441c0006a200128020020042802582203102720042802402206200128020022076a20022003101e1a2001200720036a220336020002402005450d00200210020b20042802442102200441e0006a200410512004280268210520042802602101200441d0006a41086a220742003703002004420037035020062003200441d0006a1003200441c0006a41086a200729030037030020042004290350370340200441c0006a411020012005100402402004280264450d00200110020b02402002450d00200610020b0240200441346a280200450d00200441306a28020010020b2004280204450d0120042802001002200441f0006a24000f0b200441106a41186a200141186a290000370300200441106a41106a200141106a290000370300200441106a41086a200141086a290000370300200441386a200241086a2802003602002004200129000037031020042002290200370330410810012201450d012004200136025020044208370254200441d0006a4100410810272004280250200428025822016a42f3e885d3b38eddb73a3700002004200141086a360258200441c0006a41086a2201200428025836020020042004290350370340200441d0006a200441106a10cb012004280254210520042802502102200441c0006a200128020020042802582203102720042802402206200128020022076a20022003101e1a2001200720036a220336020002402005450d00200210020b20042802442101200441d0006a41086a220242003703002004420037035020062003200441d0006a1003200441c0006a41086a200229030037030020042004290350370340200441c0006a4110100502402001450d00200610020b200441346a280200450d00200441306a28020010020b200441f0006a24000f0b101c000b1e002001200210c9010240200241046a280200450d00200228020010020b0b9a0301057f230041306b220324000240410810012204450d002003200436022020034208370224200341206a4100410810272003280220200328022822046a42f3e885d3a3ac98b63a3700002003200441086a360228200341106a41086a200328022836020020032003290320370310412010012204450d002003200436022020034220370224200341206a41004120102720032802202205200328022822066a22042001290000370000200441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a2900003700002003200641206a220136022820032802242106200341106a20032802182001102720032802102204200328021822076a20052001101e1a2003200720016a220136021802402006450d00200510020b2003280214210520032002370308200341206a41086a220642003703002003420037032020042001200341206a1003200341106a41086a200629030037030020032003290320370310200341106a4110200341086a4108100402402005450d00200410020b200341306a24000f0b101c000bf90f020b7f017e230041a0036b220424002001280204210520022802082106200228020421072002280200210802400240200128020022092f018e02220a450d004107210b0c010b4101210b0b03400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200b0e1b0a090b0c0d0708000102030406050e1a0f10141617151819121113130b2009200a410c6c6a210c4100210a200921024108210b0c300b20082002280200200241086a280200220d20062006200d4b1b1006220e450d1b4109210b0c2f0b200e411e76417f73410271417f6a220d450d24410a210b0c2e0b200d4101470d1d410b210b0c2d0b200a41016a210a2002410c6a2202200c470d1b0c1a0b4100417f41012006200d491b2006200d461b220d0d20410c210b0c2b0b200441013a00980120042d0098014101710d154105210b0c2a0b2005450d1d4106210b0c290b2005417f6a21052009200a4102746a4190026a28020022092f018e02220a0d124101210b0c280b200441003a00980120042d009801410171450d180c190b2009418e026a2f0100210a0c130b200141086a2102200aad4220862001ad84210f2007450d184103210b0c250b200810024104210b0c240b20042005360268200420023602782004200936026c2004200f370370200441086a41086a2202200341086a2802003602002004200329020037030820044198016a41086a220a2009200f422088a7410c6c6a2206418c016a220d280000220536020020064184016a2206290000210f20062004290308370000200d2002280200360000200220053602002004200f370398012004200f370308200a20022802003602002004200429030837039801200041013602002000410c6a200a2802003602002000200429039801370204200441a0036a24000f0b200441086a41106a20093602002001200128020841016a3602082004411c6a200aad4220862001ad84220f3702002004200736020c2004200836020820042006ad3703102004200936026c200441003602682004200f3703702004200736024c2004200836024820042006360250200441d8006a41086a200341086a2802003602002004200329020037035820044198016a200441e8006a200441c8006a200441d8006a1089012004280298014101470d1a4110210b0c220b200441286a41086a200441b0016a280200360200200441386a41086a200441bc016a280200360200200420044198016a41106a2903003703282004200441b4016a290200370338200441a4016a2802002102200441c4016a2802002109200441c0016a280200210a200428029c01210520044198016a41086a280200220d280288022206450d1a4111210b0c210b200d2f018c02210d2004200636026c2004200541016a2205360268200420023602702004200d3602744100450d1b4119210b0c200b2005210241c002100122060d1e4118210b0c1f0b101c000b2004200d36026c20042005360268200420023602702002210541010d174112210b0c1d0b200441b4016a210e200441a8016a2108200441e8006a410c6a210c200441c4016a2103200441c0016a21010c180b20032802002109200428029c0141016a2105200d2f018c02210d4113210b0c1b0b200441e8006a41086a2002360200200c200d3602002004200636026c20042005360268200441c8006a41086a200441286a41086a220228020036020020042004290328370348200441d8006a41086a200441386a41086a22062802003602002004200429033837035820044198016a200441e8006a200441c8006a200441d8006a200a2009108a012004280298014101470d114114210b0c1a0b2002200841086a2802003602002006200e41086a280200360200200420082902003703282004200e29020037033820044198016a410c6a28020021022001280200210a20044198016a41086a280200220d2802880222060d164116210b0c190b41c00210012206450d164117210b0c180b200620044198016a418802101e220641003b018e022006410036028802200620042902683702900220064198026a200441e8006a41086a290200370200200641a0026a200441f8006a290200370200200641a8026a20044180016a290200370200200641b0026a20044188016a290200370200200641b8026a20044190016a2902003702002006200228020036029002200220063602002002200228020441016a360204200628029002220241003b018c022002200636028802200620062f018e02220d410c6c6a220220042903283702002002418c016a200441386a41086a280200220536020020024184016a2004290338220f370200200241086a200441286a41086a28020036020020064190026a200d41016a22024102746a200a360200200620062f018e0241016a3b018e0220044198016a41086a2005360200200a20023b018c02200a2006360288022004200f37039801410f210b0c170b20004100360200200441a0036a24000f0b4107210b0c150b4102210b0c140b410d210b0c130b4101210b0c120b4100210b0c110b4108210b0c100b4101210b0c0f0b4105210b0c0e0b4102210b0c0d0b4104210b0c0c0b410e210b0c0b0b410a210b0c0a0b410c210b0c090b410f210b0c080b410f210b0c070b411a210b0c060b4119210b0c050b4112210b0c040b4113210b0c030b4115210b0c020b4118210b0c010b4117210b0c000b0b4501017f230041c0006b22012400200141386a2000410c6a28020036020020012000290204370330200141086a200141306a109d01200141086a109e01200141c0006a24000b7302017f017e024020002802002202417f460d002000200241016a36000002400240200041046a20011096012202450d002002280200450d00200241086a29030021030c010b20002802102001200041146a28020028021411140021030b20002000280200417f6a36000020030f0b109f01000b960501077f230041e0026b22032400200341086a200241086a28020036020020032002290200370300024002400240024020002802000d002000417f360000200341306a41186a2204200141186a290000370300200341306a41106a2205200141106a290000370300200341306a41086a200141086a290000370300200320012900003703302003200041046a3602182003200041086a28020036021020032000280204360214200341b8026a200341106a200341306a10970141012102200341b8026a41106a2802002106200341c4026a2802002107200341b8026a41086a280200210820032802bc022109024020032802b8024101470d00200341106a41186a2004290300370300200341106a41106a2005290300370300200341106a41086a200341306a41086a29030037030020032003290330370310410021020b41900210012201450d012001200341306a418802101e220141003b018e02200141003602880202402002450d00200320013602b802200342003702bc02200341306a200341b8026a109801200341306a1099012008200641286c6a220241106a210120022802102206450d040c030b200341cc006a200341186a290300370200200341d4006a200341206a290300370200200341dc006a200341286a2903003702002003200836023420032009360230200320073602382003200636023c20032000410c6a36024020032003290310370244200341d8026a4200370300200341003602c802200342003703b802200320013602d402200341306a200341b8026a109a01220241106a2101200228021022060d020c030b10c301000b101c000b200241146a280200450d00200610020b20012003290300370200200141086a200341086a28020036020020004100360000200341e0026a24000bab0401097f230041d0026b220324000240024020002802000d002000417f360000200341c8006a41186a2204200141186a290000370300200341c8006a41106a2205200141106a290000370300200341c8006a41086a2206200141086a290000370300200320012900003703482003200041046a3602082003200041086a28020036020020032000280204360204200341206a2003200341c8006a10970141012107200341206a41106a28020021082003412c6a2802002109200341206a41086a280200210a2003280224210b024020032802204101470d00200341186a2004290300370300200341106a2005290300370300200341086a200629030037030020032003290348370300410021070b41900210012201450d012001200341c8006a418802101e220141003b018e022001410036028802024002402007450d002003200136022020034200370224200a200841286c6a2101200341c8006a200341206a109801200341c8006a1099010c010b200341e4006a200341086a290300370200200341ec006a200341106a290300370200200341f4006a200341186a2903003702002003200a36024c2003200b360248200320093602502003200836025420032000410c6a3602582003200329030037025c200341c0006a420037030020034100360230200342003703202003200136023c200341c8006a200341206a109a0121010b200142013703002001200237030820004100360000200341d0026a24000f0b10c301000b101c000bfc0103017f017e047f230041306b2203240020034100360208200342013703002002290300210420034100410810272003280200200328020822056a20043700002003200541086a2206360208200341206a200241086a10a201200328022021052003200620032802282202102720032002200328020822076a22083602082007200328020022066a20052002101e1a02402003280224450d00200510020b200341206a41086a220242003703002003420037032020002001200341206a1003200341106a41086a200229030037030020032003290320370310200341106a411020062008100402402003280204450d00200610020b200341306a24000bfb1903047f017e077f230041d0006b22022400200241003602082002420137030002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001280200417f6a220341044b0d000240024002400240024020030e050004020301000b2002107e2002280200200241086a22032802006a41013a00002003200328020041016a22043602002002410036024820024201370340200141086a28020022054101460d0920054102470d1a200241c0006a107e20022802402205200241c8006a220328020022016a41013a00002003200141016a22013602000c0a0b2002107e2002280200200241086a22032802006a41073a00002003200328020041016a3602002002410036024820024201370340200141086a28020022034101460d0420034102470d1a200241c0006a107e2002280240200241c0006a41086a220328020022056a41013a00002003200541016a2205360200200141106a2903002106200241c0006a20054108102720032003280200220441086a22013602002004200228024022056a20063700000c050b2002107e2002280200200241086a22032802006a41053a00002003200328020041016a360200200241003602382002420137033020012d000422034103714101460d0520034102470d1a200241306a107e2002280230200241306a41086a220328020022056a41013a00002003200541016a2205360200200141086a2802002104200241306a20054104102720032003280200220741046a22013602002007200228023022056a20043600000c060b2002107e2002280200200241086a22032802006a41063a00002003200328020041016a3602002002410036024820024201370340200141086a22042d0000417f6a220341034b0d1a024020030e04000d0a0c000b200241c0006a107e2002280240200241c8006a220328020022056a41003a00002003200541016a22053602002001410c6a2802002104200241c0006a20054104102720032003280200220741046a22013602002007200228024022056a20043600000c0d0b2002107e2002280200200241086a22032802006a41023a00002003200328020041016a3602002002410036024820024201370340200141086a280200417f6a220341034b0d1a024020030e04000f0a0e000b200241c0006a107e2002280240200241c0006a41086a220328020022056a41003a00002003200541016a2205360200200141106a2903002106200241c0006a20054108102720032003280200220441086a22013602002004200228024022056a20063700000c0f0b2002107e2002280200200241086a22032802006a41003a00002003200328020041016a3602002002410036021820024201370310200128020422034101460d0620034102470d1a200241106a107e2002280210200241106a41086a220328020022056a41013a00002003200541016a2208360200200141106a220328020021052002410036024820024201370340200241c0006a4100410410272002280240200228024822046a20053600002002200441046a360248200241206a41086a220420022802483602002002200229034037032020032802002203450d0f200141086a2802002201200341186c6a21090340200241306a41086a2203410036020020024201370330200241c0006a200110512002280240210a200241306a4100200241c0006a41086a220528020022071027200320072003280200220b6a220c360200200b20022802306a200a2007101e1a02402002280244450d00200a10020b200241c0006a2001410c6a220d10512002280240210a200241306a200c200528020022071027200320072003280200220c6a2201360200200c2002280230220b6a200a2007101e1a02402002280244450d00200a10020b2001417f4c0d14024002402001450d002001100122030d010c170b410121030b200541003602002002200136024420022003360240200241c0006a41002001102720052005280200220720016a22033602002007200228024022056a200b2001101e1a2002280244210102402002280234450d00200b10020b200241206a2004280200200310272002280220220a200428020022076a20052003101e1a2004200720036a220336020002402001450d00200510020b200d410c6a22012009470d000c110b0b200241c0006a107e2002280240200241c0006a41086a220328020022056a41003a00002003200541016a2205360200200141106a2903002106200241c0006a20054108102720032003280200220441086a22013602002004200228024022056a20063700000b200228024421042002200241086a22032802002001102720032003280200220720016a360200200720022802006a20052001101e1a2004450d10200510020c100b200241306a107e2002280230200241306a41086a220328020022056a41003a00002003200541016a2207360200200241c0006a200141086a28020010d80120022802402104200241306a200720022802482205102720032005200328020022076a220a360200200720022802306a20042005101e1a02402002280244450d00200410020b410221030240200141056a2d000022014103714102460d004100210320014101470d00410121030b200241306a200a41011027200241386a22012001280200220441016a22013602002004200228023022056a20033a00000b200228023421042002200241086a22032802002001102720032003280200220720016a360200200720022802006a20052001101e1a2004450d0e200510020c0e0b200241c0006a107e2002280240200241c0006a41086a220428020022056a41003a00002004200541016a2205360200200141106a2903002106200241c0006a20054108102720022802402205200428020022016a20063700002004200141086a2201360200200328020021040b200228024421032002200420011027200241086a22042004280200220420016a360200200420022802006a20052001101e1a2003450d0c200510020c0c0b200241106a107e2002280210200241106a41086a220328020022056a41003a00002003200541016a2205360200200241c0006a200141086a105120022802402107200241106a2005200228024822041027200320042003280200220a6a2201360200200a200228021022056a20072004101e1a2002280244450d0a200710020c0a0b200241c0006a107e2002280240200241c0006a41086a220328020022056a41023a00002003200541016a2205360200200141106a2903002106200241c0006a20054108102720032003280200220441086a22013602002004200228024022056a20063700000c030b200241c0006a107e2002280240200241c8006a220328020022056a41023a00002003200541016a22053602002001410c6a2802002104200241c0006a20054104102720032003280200220741046a22013602002007200228024022056a20043600000c050b200241c0006a107e2002280240200241c0006a41086a220328020022056a41033a00002003200541016a2205360200200141106a2903002106200241c0006a20054108102720032003280200220441086a22013602002004200228024022056a20063700000c010b200241c0006a107e2002280240200241c0006a41086a220328020022016a41013a00002003200141016a2201360200200241c0006a20014120102720032003280200220741206a22013602002007200228024022056a220341086a200441096a290000370000200341106a200441116a290000370000200341186a200441196a290000370000200320042900013700000b200228024421042002200241086a22032802002001102720032003280200220720016a360200200720022802006a20052001101e1a2004450d06200510020c060b200241c0006a107e20022802402205200241c8006a220328020022016a41033a00002003200141016a22013602000c010b200241c0006a107e2002280240200241c0006a41086a220328020022056a41013a00002003200541016a2205360200200141106a2903002106200241c0006a20054108102720032003280200220441086a22013602002004200228024022056a20063700000b200228024421042002200241086a22032802002001102720032003280200220720016a360200200720022802006a20052001101e1a2004450d03200510020c030b200228022821032002280220210a0b20022802242104200241106a20082003102720022002280218220720036a22013602182007200228021022056a200a2003101e1a2004450d00200a10020b200228021421042002200241086a22032802002001102720032003280200220720016a360200200720022802006a20052001101e1a2004450d00200510020b20002002290300370200200041086a200241086a280200360200200241d0006a24000f0b1019000b101c000b41ec30103b000b41843e103b000b41ac3f103b000b419435103b000b41943b103b000b41ecc100103b000bc20201027f230041c0006b22022400200241106a41086a220342003703002002420037031020014107200241106a1003200241086a20032903003703002002200229031037030002402002411041d02d410041001000417f460d00200241386a4200370300200241206a41106a4200370300200241206a41086a420037030020024200370320024020024110200241206a4120410010002203417f460d002003411f4d0d0020002002290320370000200041186a200241206a41186a290300370000200041106a200241206a41106a290300370000200041086a200241206a41086a2200290300370000200241106a41086a220342003703002002420037031020014107200241106a10032000200329030037030020022002290310370320200241206a41101005200241c0006a24000f0b41c1214133102d000b41f4214122102d000bb80101027f230041306b22032400200341206a41086a220442003703002003420037032020012002200341206a1003200341086a200429030037030020032003290320370300024002402003411041d02d410041001000417f460d002003421037021420032003360210200341206a200341106a103a20032802202201450d012000200329022437020420002001360200200341306a24000f0b2000410036020820004201370200200341306a24000f0b41c1214133102d000b8d5b05087f037e137f017e017f230041e0016b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d000022034103714101460d00024020034102460d0020034103470d0d200241206a200041196a290000370300200241186a200041116a290000370300200241106a200041096a29000037030020022000290001370308200241386a1047200228023822042002280240220541286c22066a2107200421030240200641286d4104490d00200421060340200120062203460d062003200141201006450d06200341286a22062001460d0a2006200141201006450d0a200641286a22062001460d0b2006200141201006450d0b200641286a22062001460d0c2006200141201006450d0c2007200641286a22066b41286d41034b0d000b200341a0016a21030b024020032007460d002004200541286c6a2106034020012003460d042003200141201006450d042006200341286a2203470d000b0b2004200228023c10870141fc3e103b000b200041216a2d0000210520024198016a41186a200041196a220329000037030020024198016a41106a200041116a220629000037030020024198016a41086a200041096a22042900003703002002200029000137039801200241386a41186a2003290000370300200241386a41106a2006290000370300200241386a41086a2004290000370300200241e0006a200141086a290000370300200241e8006a200141106a290000370300200241f0006a200141186a2900003703002002200029000137033820022001290000370358410910012203450d17200220033602c001200242093702c401200241c0016a41004109102720022802c00120022802c80122066a220441002900f922370000200241086a41086a2203200641096a2206360200200441086a41002d0081233a0000200220022903c001370308200220063602c801200241c0016a200241386a10be0120022802c401210820022802c0012104200241086a200328020020022802c8012206102720022802082207200328020022096a20042006101e1a2003200920066a220636020002402008450d00200410020b200228020c210320024188016a41086a2204420037030020024200370388012007200620024188016a1003200241f8006a41086a20042903003703002002200229038801370378200241f8006a411041d02d410041001000417f460d02200241003a00c001200241f8006a4110200241c0016a41014100100041016a41014d0d1020022d00c00121062003450d160c150b200041046a280200210d102e210a20024188016a41086a22034200370300200242003703880141e122410a20024188016a1003200241f8006a41086a20032903003703002002200229038801370378200241f8006a411041d02d410041001000417f460d0c20024200370338200241f8006a4110200241386a41084100100041016a41084d0d0a2002290338200a7c210a200241386a1047200228023822072002280240220841286c22066a2105200721030240200641286d4104490d00200721030340200120032206460d052006200141201006450d05200641286a2103200641286a22042001460d062004200141201006450d06200641d0006a2103200441286a22042001460d062004200141201006450d06200641f8006a2103200441286a22042001460d062004200141201006450d062005200441286a22036b41286d41034b0d000b200641a0016a21030b4102210420032005460d052007200841286c6a2106034020012003460d052003200141201006450d052006200341286a2203470d000c060b0b200228023c450d120c110b4102210620030d120c130b200228023c0d0f0c100b200621030b200341206a290300200a5621040b200441024720047121030240200228023c450d00200710020b2003450d0720024198016a200d10d80120022802a00121052002280298012107200241386a41186a22034200370300200241386a41106a22064200370300200241386a41086a220442003703002002420037033820072005200241386a1012200241c0016a41186a22052003290300370300200241c0016a41106a22082006290300370300200241c0016a41086a22092004290300370300200220022903383703c0010240200228029c01450d00200710020b200320052903003703002006200829030037030020042009290300370300200220022903c001370338410710012203450d1020022003360298012002420737029c0120024198016a41004107102720022802980120022802a00122066a220341002800eb22360000200241086a41086a200641076a2206360200200341046a41002f00ef223b0000200341066a41002d00f1223a00002002200229039801370308200220063602a001412010012203450d1020022003360298012002422037029c0120024198016a410041201027200228029801220620022802a00122046a22032002290338370000200341086a200241386a41086a290300370000200341106a200241386a41106a290300370000200341186a200241386a41186a2903003700002002200441206a22033602a001200228029c012107200241086a20022802102003102720022802082204200228021022056a20062003101e1a2002200520036a220336021002402007450d00200610020b200228020c210620024188016a41086a2207420037030020024200370388012004200320024188016a1003200241f8006a41086a20072903003703002002200229038801370378200241f8006a411020024198016a410041001000210302402006450d00200410020b2003417f470d08200241386a200241c0016a10dc01024020022802402203450d002002290338210b20022802442106102e210c02402006450d00200310020b200c200b540d0b0b200241286a10bb01200241386a41186a2206200241c0016a41186a290300370300200241386a41106a2204200241c0016a41106a290300370300200241386a41086a2207200241c0016a41086a290300370300200220022903c00137033820022802302205200228022c460d030c0b0b200228023c0d0b0c0c0b200228023c0d0a0c0b0b200228023c0d090c0a0b200241286a106f200241286a41086a28020021050c070b41c1214133102d000b419c3e103b000b41f4214122102d000b41b43e103b000b41cc3e103b000b41c1214133102d000b41e43e103b000b200241286a41086a200541016a22153602002002280228220f200541286c6a2203200a37030020032002290338370308200341106a2007290300370300200341186a2004290300370300200341206a2006290300370300024002400240024002400240024002400240024002400240024002400240024002400240201541144b0d00201541014d0d01200f200541286c6a21110340201520052203417f6a2205490d100240201520056b22074102490d00200f200341286c6a2204290300200f200541286c6a220e290300220a5a0d00200e2004290300370300200e290308210b200e41086a200441086a290300370300200241386a41186a2200200e41206a2203290300370300200241386a41106a2212200e41186a2206290300370300200241386a41086a2213200e41106a22082903003703002008200441106a2903003703002006200441186a2903003703002003200441206a2903003703002002200b37033841012108024020074103490d0041012106201121030340200641016a220820074f0d150240200341286a2204290300200a5a0d00200620074f0d15200341206a200341c8006a290300370300200341186a200341c0006a290300370300200341106a200341386a290300370300200341086a200341306a29030037030020032004290300370300200641026a2109200821062004210320092007490d010c020b0b20062108200321040b2004200a370300200e200841286c6a22032002290338370308200341206a2000290300370300200341186a2012290300370300200341106a20132903003703000b201141586a211120050d000c020b0b20154101762216ad42287e220a422088a70d0d200aa72203417f4c0d0c4108211702402003450d00200310012217450d160b41002106200241003602a0012002420437039801200f41586a2118200f41887f6a21194104210420024198016a41086a211a2015211003402010211141002110410121070240024002402011417f6a2203450d000240024002400240024002400240200f200341286c6a290300200f2011417e6a220741286c6a290300220a5a0d00410021082007450d022019201141286c6a21030340200a2003290300220b5a0d02200341586a2103200b210a2007417f6a22070d000c030b0b02402007450d002019201141286c6a2103410221070340200a2003290300220b540d04200341586a2103200b210a2011200741016a2207470d000b41002110201121072006200228029c01470d090c080b41022107410021102006200228029c01470d080c070b200721080b024020112008490d00201120154b0d140240201120086b22074101762209450d002018201141286c6a2103200f200841286c6a21050340200241386a41206a220e200541206a2200290300370300200241386a41186a2212200541186a2213290300370300200241386a41106a2214200541106a2210290300370300200241386a41086a221b200541086a221c29030037030020022005290300370338200341086a221d290300210a200341106a221e290300210b200341186a221f290300210c200329030021202000200341206a22212903003703002013200c3703002010200b370300201c200a370300200520203703002021200e290300370300201f2012290300370300201e2014290300370300201d201b29030037030020032002290338370300200341586a2103200541286a21052009417f6a22090d000b0b2008450d030c020b200820111055000b201120076b2208450d010b200741094d0d010b200821102006200228029c01470d030c020b201120154b0d0d200f200841286c6a2112034020112008417f6a2210490d0f0240201120106b22074102490d00200f200841286c6a2208290300200f201041286c6a2200290300220a5a0d00200020082903003703002000290308210b200041086a200841086a290300370300200241386a41186a2213200041206a2203290300370300200241386a41106a2214200041186a2205290300370300200241386a41086a221b200041106a22092903003703002009200841106a2903003703002005200841186a2903003703002003200841206a2903003703002002200b37033841012109024020074103490d0041012105201221030340200541016a220920074f0d090240200341286a2208290300200a5a0d00200520074f0d0b200341206a200341c8006a290300370300200341186a200341c0006a290300370300200341106a200341386a290300370300200341086a200341306a29030037030020032008290300370300200541026a210e2009210520082103200e2007490d010c020b0b20052109200321080b2008200a3703002000200941286c6a22032002290338370308200341206a2013290300370300200341186a2014290300370300200341106a201b2903003703000b2010450d01201241586a2112201021082007410a490d000b0b2006200228029c01470d010b20024198016a107a201a280200210620022802980121040b200420064103746a2203200736020420032010360200201a200641016a2206360200024020064102490d0020022802980121040340024002400240024020042006417f6a4103746a2203280200450d00200420064103746a220841746a2802002205200328020422074d0d00200641024d0d0520042006417d6a22124103746a2802042203200720056a4d0d01200641034d0d05200841646a280200200320056a4d0d010c050b20064103490d012003280204210720042006417d6a22124103746a28020421030b20032007490d010b2006417e6a21120b2006201241016a22134d0d06200620124d0d0720042012410374221b6a2203280204221c20032802006a220320042013410374221d6a22062802002214490d08200320154b0d09200f201441286c6a22112006280204220041286c22066a2107200341286c210402400240024002400240200320146b220820006b220320004f0d0020172007200341286c2206101e220e20066a210520004101480d0120034101480d01201820046a21042007210303402004200341586a2207200541586a2208200829030020072903005422091b2206290300370300200441206a200641206a290300370300200441186a200641186a290300370300200441106a200641106a290300370300200441086a200641086a2903003703002005200820091b210520112007200320091b22034f0d04200441586a2104200e2106200e2005490d000c050b0b201720112006101e220320066a210520004101480d01200820004c0d01200f20046a210920032106201121030340200320072006200729030020062903005422081b2204290300370300200341206a200441206a290300370300200341186a200441186a290300370300200341106a200441106a290300370300200341086a200441086a2903003703002006200641286a20081b2106200341286a2103200741286a200720081b220720094f0d04200520064b0d000c040b0b200721030c010b201121030b201721060b20032006200520066b220420044128706b101e1a201a280200220320124d0d0a2002280298012204201b6a2206201c20006a36020420062014360200200320134d0d0b2004201d6a2206200641086a200320136b41037441786a10391a201a2003417f6a2206360200200641014b0d000b0b20100d000b0240200228029c01450d0020022802980110020b2016450d00201710020b200241286a10bc0120024198016a41186a200241c0016a41186a29030037030020024198016a41106a200241c0016a41106a29030037030020024198016a41086a200241c0016a41086a290300370300200220022903c00137039801200241386a41286a200d41286a290300370300200241386a41206a200d41206a290300370300200241386a41186a200d41186a290300370300200241386a41106a200d41106a290300370300200241386a41086a200d41086a2903003703002002200d290300370338410710012203450d14200220033602082002420737020c200241086a4100410710272002280208200228021022066a220341002800eb2236000020024188016a41086a200641076a2206360200200341046a41002f00ef223b0000200341066a41002d00f1223a0000200220022903083703880120022006360210412010012203450d14200220033602082002422037020c200241086a41004120102720022802082206200228021022046a2203200229039801370000200341086a20024198016a41086a290300370000200341106a20024198016a41106a290300370000200341186a20024198016a41186a2903003700002002200441206a2203360210200228020c210720024188016a20022802900120031027200228028801220420022802900122056a20062003101e1a2002200520036a22053602900102402007450d00200610020b200228028c012106200241086a200241386a10d801200228021021072002280208210320024188016a41086a2208420037030020024200370388012004200520024188016a1003200241f8006a41086a20082903003703002002200229038801370378200241f8006a41102003200710040240200228020c450d00200310020b02402006450d00200410020b024002400240200228023822034103460d0020030d02200228023c2203450d0220034101470d01200241c4006a280200450d02200241c0006a28020010020c020b20022d003c4101470d01200241c0006a10bf010c010b0240200241386a41106a2802002206450d00200241c0006a2802002103200641186c210603400240200341046a280200450d00200328020010020b0240200341106a280200450d002003410c6a28020010020b200341186a2103200641686a22060d000b0b200241c4006a280200450d00200241c0006a28020010020b200241386a41186a2206200241c0016a41186a2204290300370300200241386a41106a2207200241c0016a41106a2205290300370300200241386a41086a2208200241c0016a41086a2209290300370300200220022903c001370338412010012203450d14200141086a220e290000210a200141106a2211290000210b2001290000210c200341186a200141186a2200290000370000200341106a200b370000200341086a200a3700002003200c3700002002200336029801200242818080801037029c01200241386a20024198016a10dd01200620042903003703002007200529030037030020082009290300370300200241e0006a200e290000370300200241e8006a2011290000370300200241f0006a2000290000370300200220022903c00137033820022001290000370358200241386a410110de010240200228022c450d00200228022810020b200d1002200241e0016a24000f0b41ccc100200541016a2007103c000b41dcc10020052007103c000b41acc10020132006103c000b41acc10020122006103c000b201420031055000b200320151029000b41bcc10020122003103c000b41b4c300103b000b20112008417f6a22104f0d010b201020111055000b201120151029000b1065000b1064000b200520151055000b41dcc10020062007103c000b41ccc100200641016a2007103c000b200410020b410b10012203450d02200220033602382002420b37023c200241386a4100410b10272002280238200228024022066a220341002900822337000020024198016a41086a2006410b6a2206360200200341086a41002f008a233b00002003410a6a41002d008c233a0000200220022903383703980120022006360240412010012203450d02200220033602382002422037023c200241386a41004120102720022802382206200228024022046a22032002290308370000200341086a200241086a41086a290300370000200341106a200241086a41106a290300370000200341186a200241086a41186a2903003700002002200441206a2203360240200228023c210720024198016a20022802a00120031027200228029801220420022802a00122056a20062003101e1a2002200520036a22033602a00102402007450d00200610020b200228029c01210620024188016a41086a2207420037030020024200370388012004200320024188016a1003200241f8006a41086a20072903003703002002200229038801370378200241f8006a411020024198016a410041001000210302402006450d00200410020b02400240024002402003417f460d00200241386a200241086a10dc010240024002400240024020022802402208450d0020022002290244220a37022c20022008360228200aa7210e200a422088a72209450d0120094101470d02410021030c030b410021092002410036023020024201370328410121084100210e0b410021060c020b4100210320092106034020032006410176220720036a2204200820044105746a2001412010062205417f4a1b200420051b2103200620076b220641014b0d000b0b200820034105746a2001412010062206450d032006411f7620036a21060b200241386a41186a200141186a290000370300200241386a41106a200141106a290000370300200241386a41086a200141086a2900003703002002200129000037033820092006490d012009200e470d03200241286a107c200228022821080c030b41943f103b000b419cc300103b000b200310c201000b200820064105746a220341206a2003200920066b41057410391a20032002290338370000200341186a200241386a41186a290300370000200341106a200241386a41106a290300370000200341086a200241386a41086a290300370000200241286a41086a200941016a360200102e210a20024188016a41086a220342003703002002420037038801418d23410b20024188016a1003200241f8006a41086a200329030037030020022002290388013703780240200241f8006a411041d02d410041001000417f460d00200242003703380240200241f8006a4110200241386a41084100100041016a41084d0d002002290338210b200241c8006a200241286a41086a2802003602002002200b200a7c37033820022002290328370340410910012203450d0420022003360298012002420937029c0120024198016a41004109102720022802980120022802a00122036a2206410029009823370000200241c0016a41086a200341096a2203360200200641086a41002d00a0233a000020022002290398013703c001200220033602a001412010012203450d0420022003360298012002422037029c0120024198016a410041201027200228029801220620022802a00122046a22032002290308370000200341086a200241086a41086a290300370000200341106a200241086a41106a290300370000200341186a200241086a41186a2903003700002002200441206a22033602a001200228029c012107200241c0016a20022802c8012003102720022802c001220420022802c80122056a20062003101e1a2002200520036a22033602c80102402007450d00200610020b20022802c401210620042003200241386a10d70102402006450d00200410020b0240200241c4006a280200450d00200241c0006a28020010020b200241386a10bb01200228023c210f20022802382110024002400240024020022802402203450d00200341286c41b07f6a2104200241386a41086a2106201021030340200241386a41206a200341206a290300370300200241386a41186a200341186a290300370300200241386a41106a200341106a2903003703002006200341086a29030037030020022003290300370338200241c0016a41186a200641186a290000370300200241c0016a41106a200641106a290000370300200241c0016a41086a200641086a290000370300200220062900003703c001200241c0016a200241086a412010060d02200341286a2103200441586a220441b07f470d000b0b2002410036024020024208370338200f450d0120101002200241386a10bc010c020b20024198016a41206a2206200241386a41206a29030037030020024198016a41186a2207200241386a41186a29030037030020024198016a41106a2205200241386a41106a29030037030020024198016a41086a2208200241386a41086a2903003703002002200229033837039801412810012211450d062011200229039801370300201141206a2006290300370300201141186a2007290300370300201141106a2005290300370300201141086a20082903003703002002201136028801200242818080801037028c01024020044158460d00200341286a2103200241386a41086a21064101210e0340200241386a41206a2205200341206a290300370300200241386a41186a2208200341186a290300370300200241386a41106a2209200341106a2903003703002006200341086a29030037030020022003290300370338200241c0016a41186a200641186a290000370300200241c0016a41106a200641106a290000370300200241c0016a41086a200641086a290000370300200220062900003703c0010240200241c0016a200241086a41201006450d0020024198016a41206a2207200529030037030020024198016a41186a2212200829030037030020024198016a41106a2213200929030037030020024198016a41086a2214200629030037030020022002290338370398012005200729030037030020082012290300370300200920132903003703002006201429030037030020022002290398013703380240200e200228028c01470d0020024188016a200e410110820120022802880121110b2011200e41286c6a22072002290338370300200741206a2005290300370300200741186a2008290300370300200741106a2009290300370300200741086a200629030037030020024188016a41086a200e41016a220e3602000b2004450d01200341286a2103200441586a21040c000b0b0240200f450d00201010020b200241386a41086a20024188016a41086a2802003602002002200229038801370338200228023c2103200241386a10bc012003450d01200228023810020c010b200241386a10bc010b200241386a41186a200241086a41186a290300370300200241386a41106a200241086a41106a290300370300200241386a41086a200241086a41086a29030037030020022002290308370338410b10012203450d0420022003360298012002420b37029c0120024198016a4100410b102720022802980120022802a00122066a2203410029008223370000200241c0016a41086a2006410b6a2206360200200341086a41002f008a233b00002003410a6a41002d008c233a000020022002290398013703c001200220063602a001412010012203450d0420022003360298012002422037029c0120024198016a410041201027200228029801220620022802a00122046a22032002290338370000200341086a200241386a41086a290300370000200341106a200241386a41106a290300370000200341186a200241386a41186a2903003700002002200441206a22033602a001200228029c012107200241c0016a20022802c8012003102720022802c001220420022802c80122056a20062003101e1a2002200520036a22033602c80102402007450d00200610020b20022802c401210620024188016a41086a2207420037030020024200370388012004200320024188016a1003200241f8006a41086a20072903003703002002200229038801370378200241f8006a4110100502402006450d00200410020b200241386a41186a200241086a41186a290300370300200241386a41106a200241086a41106a290300370300200241386a41086a200241086a41086a29030037030020022002290308370338410710012203450d0420022003360298012002420737029c0120024198016a41004107102720022802980120022802a00122066a220341002800eb22360000200241c0016a41086a200641076a2206360200200341046a41002f00ef223b0000200341066a41002d00f1223a000020022002290398013703c001200220063602a001412010012203450d0420022003360298012002422037029c0120024198016a410041201027200228029801220620022802a00122046a22032002290338370000200341086a200241386a41086a290300370000200341106a200241386a41106a290300370000200341186a200241386a41186a2903003700002002200441206a22033602a001200228029c012107200241c0016a20022802c8012003102720022802c001220420022802c80122056a20062003101e1a2002200520036a22033602c80102402007450d00200610020b20022802c401210620024188016a41086a2207420037030020024200370388012004200320024188016a1003200241f8006a41086a20072903003703002002200229038801370378200241f8006a4110100502402006450d00200410020b200241386a1047200228023c211320022802382112024020022802402203450d00200341286c2109200241d8006a210620122103034020062003290000370000200241386a41186a200241086a41186a290300370300200241386a41106a200241086a41106a290300370300200241386a41086a200241086a41086a290300370300200641086a200341086a290000370000200641106a200341106a290000370000200641186a200341186a29000037000020022002290308370338410910012204450d0620022004360298012002420937029c0120024198016a41004109102720024198016a41086a22072007280200220441096a220536020020042002280298016a220841002900f922370000200241c0016a41086a22042005360200200841086a41002d0081233a000020022002290398013703c00120024198016a200241386a10be01200228029c01210e2002280298012105200241c0016a200428020020072802002207102720022802c0012208200428020022116a20052007101e1a2004201120076a22073602000240200e450d00200510020b20022802c401210420024188016a41086a2205420037030020024200370388012008200720024188016a1003200241f8006a41086a20052903003703002002200229038801370378200241f8006a4110100502402004450d00200810020b200341286a2103200941586a22090d000b0b02402013450d00201210020b20002d00004101470d0a0c090b41c1214133102d000b41f4214122102d000b200710020b200641ff01714102470d04410b10012203450d00200220033602382002420b37023c200241386a4100410b10272002280238200228024022066a2203410029008223370000200241c0016a41086a2006410b6a2206360200200341086a41002f008a233b00002003410a6a41002d008c233a0000200220022903383703c00120022006360240412010012203450d00200220033602382002422037023c200241386a41004120102720022802382206200228024022046a2203200229039801370000200341086a20024198016a41086a290300370000200341106a20024198016a41106a290300370000200341186a20024198016a41186a2903003700002002200441206a2203360240200228023c2107200241c0016a20022802c8012003102720022802c001220420022802c80122086a20062003101e1a2002200820036a22033602c80102402007450d00200610020b20022802c401210720024188016a41086a2206420037030020024200370388012004200320024188016a1003200241f8006a41086a20062903003703002002200229038801370378410021030240200241f8006a411041d02d410041001000417f460d00200242103702c4012002200241f8006a3602c001200241386a200241c0016a103a20022802382206450d022002200229023c220a37020c20022006360208200a422088a72103200aa721092007450d040c030b2002410036021020024201370308410121064100210920070d020c030b101c000b41c1214133102d000b200410020b200241386a41186a2204200141186a290000370300200241386a41106a2207200141106a290000370300200241386a41086a2208200141086a29000037030020022001290000370338024020032009470d00200241086a107c200241086a41086a2802002103200228020821060b2008290300210a2007290300210b2004290300210c200620034105746a22062002290338370000200641186a200c370000200641106a200b370000200641086a200a370000200241086a41086a2206200341016a360200200420024198016a41186a290300370300200720024198016a41106a290300370300200820024198016a41086a2903003703002002200229039801370338200241c0016a41086a2006280200360200200220022903083703c001200241386a200241c0016a10dd010b200241386a41186a20024198016a41186a290300370300200241386a41106a20024198016a41106a290300370300200241386a41086a20024198016a41086a290300370300200241e0006a200141086a290000370300200241e8006a200141106a290000370300200241f0006a200141186a290000370300200220022903980137033820022001290000370358200241386a200541ff017141004710de0120002d00004101470d010b200041046a10bf010b200241e0016a24000bcd0402057f017e230041c0006b220224000240024002400240410910012203450d002002200336023020024209370234200241306a4100410910272002280230200228023822036a2204410029009823370000200241086a200341096a2203360200200441086a41002d00a0233a00002002200229033037030020022003360238412010012203450d002002200336023020024220370234200241306a41004120102720022802302204200228023822056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a220136023820022802342105200220022802082001102720022802002203200228020822066a20042001101e1a2002200620016a220136020802402005450d00200410020b20022802042104200241306a41086a220542003703002002420037033020032001200241306a1003200241086a20052903003703002002200229033037030002402002411041d02d410041001000417f460d002002200236021020024110360214200242003703302002410020024110200241306a41084100100022012001417f461b2201410820014108491b360218200141074d0d0220022903302107200241306a200241106a103a20022802302201450d022002200229023437032020002001360208200020073703002000200229032037020c200041146a200241286a2802003602002004450d040c030b2000410036020820040d020c030b101c000b41c1214133102d000b200310020b200241c0006a24000be20301067f230041306b220224000240410b10012203450d00200220033602202002420b370224200241206a4100410b10272002280220200228022822046a2203410029008223370000200241106a41086a2004410b6a2204360200200341086a41002f008a233b00002003410a6a41002d008c233a00002002200229032037031020022004360228412010012203450d002002200336022020024220370224200241206a41004120102720022802202204200228022822056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002002200541206a220036022820022802242105200241106a20022802182000102720022802102203200228021822066a20042000101e1a2002200620006a220636021802402005450d00200410020b200228021421042002200110a2012002280208210520022802002100200241206a41086a220742003703002002420037032020032006200241206a1003200241106a41086a200729030037030020022002290320370310200241106a411020002005100402402002280204450d00200010020b02402004450d00200310020b0240200141046a280200450d00200128020010020b200241306a24000f0b101c000bc00201057f230041306b22022400200220013a000f0240410910012201450d002002200136022020024209370224200241206a4100410910272002280220200228022822036a220441002900f922370000200241106a41086a2201200341096a2203360200200441086a41002d0081233a00002002200229032037031020022003360228200241206a200010be012002280224210520022802202103200241106a200128020020022802282200102720022802102204200128020022066a20032000101e1a2001200620006a220036020002402005450d00200310020b20022802142103200241206a41086a220542003703002002420037032020042000200241206a10032001200529030037030020022002290320370310200241106a41102002410f6a4101100402402003450d00200410020b200241306a24000f0b101c000bab0201057f230041206b220224000240410810012203450d002002200336021020024208370214200241106a4100410810272002280210200228021822036a42e4cab5d3c3ac99b83a3700002002200341086a360218200241086a200228021836020020022002290310370300410410012203450d002002200336021020024204370214200241106a41004104102720022802102203200228021822046a20003600002002200441046a220036021820022802142105200220022802082000102720022802002204200228020822066a20032000101e1a2002200620006a220036020802402005450d00200310020b2002280204210320042000200110d70102402003450d00200410020b02402001410c6a280200450d00200128020810020b200241206a24000f0b101c000b9c0b04027f017e027f017e230041d0006b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001280200417f6a220341044b0d000240024002400240024020030e050004020301000b200141086a28020022034101460d0720034102470d16420221040c080b420121040240200141086a28020022034101460d0020034102470d17420221040b20004105360200200041086a2004370300200041106a200141106a290300370300200241d0006a24000f0b20012d000422034103714101460d034102210520034102470d16200141086a28020021030c040b200141086a22052d0000417f6a220341034b0d16024020030e04000c080a000b2001410c6a2802002101410121030c0c0b200141086a280200417f6a220641034b0d1641042103024020060e0400080d0e000b200141106a2903002104410121030c0d0b200128020422034101460d0420034102470d16200141106a2802002205ad42187e2204422088a70d172004a72203417f4c0d18200141086a28020021012003450d0d2003100122060d0e0c100b413010012203450d0f2003200141086a28020010e001200141056a2d00002101410121050b20004103360200200041086a20033602002000200141ff0171410874200572360204200241d0006a24000f0b200141106a2903002107420121040b20004101360200200041106a2007370300200041086a2004370300200241d0006a24000f0b200141106a2802002203417f4c0d14200141086a2802002106410121014101210502402003450d00200310012205450d0c0b2002200336023c2002200536023820024100360240200241386a41002003102720022002280240220520036a360240200520022802386a20062003101e1a200241286a2002280240360200200220022903383703200c0a0b200141106a2903002104410321030c020b200141106a2903002104410221030c050b200141106a2903002104410421030b0c010b41022103200241206a41026a200541036a2d00003a0000200241c0006a200141206a290000370300200241386a41106a200141286a2d00003a0000200220052f00013b01202002200141186a290000370338200141106a29000021042001410c6a28000021010b200020022f01203b000920004104360200200041086a20033a00002000410c6a2001360200200041106a2004370300200041186a20022903383703002000410b6a200241226a2d00003a0000200041206a200241386a41086a290300370300200041286a200241386a41106a290300370300200241d0006a24000f0b2001410c6a2802002105410321030b200041023602002000410c6a2005360200200041086a2003360200200041106a2004370300200241d0006a24000f0b410421060b20022006360208200241003602102002200536020c200241086a4100200341186d10830120022802102103200228020821062002200136021820022001200541186c6a36021c200241386a200241186a103302402002280238450d002006200341186c6a21010340200241206a41106a2205200241386a41106a290300370300200241206a41086a2206200241386a41086a29030037030020022002290338370320200141106a2005290300370200200141086a200629030037020020012002290320370200200341016a2103200141186a2101200241386a200241186a103320022802380d000b0b200241086a41086a2003360200200241206a41086a200336020020022002290308370320410221010b2000200136020420004100360200200041086a2002290320370200200041106a200241206a41086a280200360200200241d0006a24000f0b101c000b41ec30103b000b41843e103b000b41ac3f103b000b419435103b000b41943b103b000b41ecc100103b000b1060000b1061000b1019000b9d08090e7f017e017f017e017f017e017f017e017f230041306b22022400024002400240024020014108490d00200141017641feffffff07712203417f6a220420014f0d032001410d74200173220541117620057322054105742005732206417f2001417f6a677622077122054100200120052001491b6b220520014f0d01200241086a41206a22082000200441286c6a220441206a2209290300370300200241086a41186a220a200441186a220b290300370300200241086a41106a220c200441106a220d290300370300200241086a41086a220e200441086a220f2903003703002000200541286c6a22052903002110200541086a22112903002112200541106a22132903002114200541186a221529030021162009200541206a2217290300370300200b2016370300200d2014370300200f2012370300200429030021122004201037030020022012370308201720082903003703002015200a2903003703002013200c2903003703002011200e29030037030020052002290308370300200320014f0d022006410d7420067322054111762005732205410574200573220620077122054100200120052001491b6b220520014f0d01200241086a41206a22082000200341286c6a220441206a2209290300370300200241086a41186a220a200441186a220b290300370300200241086a41106a220c200441106a220d290300370300200241086a41086a220e200441086a220f2903003703002000200541286c6a22052903002110200541086a22112903002112200541106a22132903002114200541186a221529030021162009200541206a2217290300370300200b2016370300200d2014370300200f2012370300200429030021122004201037030020022012370308201720082903003703002015200a2903003703002013200c2903003703002011200e290300370300200520022903083703002003410172220420014f0d032006410d742006732205411176200573220541057420057320077122054100200120052001491b6b220520014f0d01200241086a41206a22032000200441286c6a220141206a2204290300370300200241086a41186a2206200141186a2207290300370300200241086a41106a2208200141106a2209290300370300200241086a41086a220a200141086a220b2903003703002000200541286c6a22002903002110200041086a22052903002112200041106a220c2903002114200041186a220d29030021162004200041206a220e2903003703002007201637030020092014370300200b2012370300200129030021122001201037030020022012370308200e2003290300370300200d2006290300370300200c20082903003703002005200a290300370300200020022903083703000b200241306a24000f0b41b4c20020052001103c000b200321040b41ecc20020042001103c000bd808070d7f017e017f017e017f027e027f230041306b2202240002400240024002400240024020014101762203450d0003402003417f6a2203210403402004410174220d41017221160240200d41026a220d20014f0d00201620014f0d06200d20162000200d41286c6a2903002000201641286c6a290300541b21160b0240201620014f0d00200420014f0d042000201641286c6a220d2903002000200441286c6a22042903005a0d00200241086a41206a2205200441206a2206290300370300200241086a41186a2207200441186a2208290300370300200241086a41106a2209200441106a220a290300370300200241086a41086a220b200441086a220c290300370300200d41086a220e290300210f200d41106a22102903002111200d41186a22122903002113200d29030021142006200d41206a221529030037030020082013370300200a2011370300200c200f3703002004290300210f200420143703002002200f370308201520052903003703002012200729030037030020102009290300370300200e200b290300370300200d2002290308370300201621040c010b0b20030d000b0b024020014102490d002001210503402005417f6a220520014f0d06200241086a41206a2206200041206a220d290300370300200241086a41186a2207200041186a2216290300370300200241086a41106a2208200041106a220a290300370300200241086a41086a2209200041086a220b2903003703002000200541286c6a2204290300210f200441086a220c2903002111200441106a220e2903002113200441186a22102903002114200d200441206a221229030037030020162014370300200a2013370300200b2011370300200029030021112000200f370300200220113703082012200629030037030020102007290300370300200e2008290300370300200c2009290300370300200420022903083703004100210403402004410174220d41017221160240200d41026a220d20054f0d00201620054f0d07200d20162000200d41286c6a2903002000201641286c6a290300541b21160b0240201620054f0d00200420054f0d052000201641286c6a220d2903002000200441286c6a22042903005a0d002006200441206a220a2903003703002007200441186a220b2903003703002008200441106a220c2903003703002009200441086a220e290300370300200d41086a2210290300210f200d41106a22122903002111200d41186a22152903002113200d2903002114200a200d41206a2203290300370300200b2013370300200c2011370300200e200f3703002004290300210f200420143703002002200f37030820032006290300370300201520072903003703002012200829030037030020102009290300370300200d2002290308370300201621040c010b0b200541014b0d000b0b200241306a24000f0b418cc30020042001103c000b418cc30020042005103c000b41fcc20020162001103c000b41fcc20020162005103c000b41b4c20020052001103c000bac0904097f017e0e7f017e230041306b22022400200041286a2103200041887f6a2104200041586a21054100210620014132492107410121080240024002400340024002400240200820014f0d002005200841286c6a210903402009290300200941286a2209290300540d0220092109200841016a22082001490d000b0b410021092008200146220a0d030c010b410121092008200146220a0d020b20070d012008417f6a220a20014f0d022009450d032000200a41286c6a2209290300210b20092000200841286c220c6a220a290300370300200241086a41206a220d200941206a220e290300370300200241086a41186a220f200941186a2210290300370300200241086a41106a2211200941106a2212290300370300200241086a41086a2213200941086a22142903003703002014200a41086a22152903003703002012200a41106a22162903003703002010200a41186a2217290300370300200e200a41206a22182903003703002002200b3703082018200d2903003703002017200f2903003703002016201129030037030020152013290300370300200a2002290308370300024020084102490d0020002008417e6a220d41286c6a22192903002009290300220b5a0d00200920192903003703002009290308211a2014201941086a290300370300200f200e29030037030020112010290300370300201320122903003703002012201941106a2903003703002010201941186a290300370300200e201941206a2903003703002002201a3703084100210e0240200d450d002004200c6a2109024003402009290300200b5a0d01200941286a2009290300370300200941c8006a200941206a290300370300200941c0006a200941186a290300370300200941386a200941106a290300370300200941306a200941086a290300370300200941586a2109200d417f6a220d0d000b200941286a21190c010b200941286a2119200d210e0b2019200b3703002000200e41286c6a22092002290308370308200941206a200f290300370300200941186a2011290300370300200941106a20132903003703000b200641016a21060240200120086b22124102490d00200a290300220b200a2903285a0d00200a200a41286a220d290300370300200a290308211a2015200d41086a290300370300200f201829030037030020112017290300370300201320162903003703002016200d41106a2903003703002017200d41186a2903003703002018200d41206a2903003703002002201a37030841012116024020124103490d002003200c6a21094101210e02400340200b200941286a220d2903005a0d01200941206a200941c8006a290300370300200941186a200941c0006a290300370300200941106a200941386a290300370300200941086a200941306a2903003703002009200d290300370300200e41026a2110200e41016a2216210e200d210920102012490d000c020b0b200e21162009210d0b200d200b370300200a201641286c6a22092002290308370308200941206a200f290300370300200941186a2011290300370300200941106a20132903003703000b20064105490d000b4100210a0b200241306a2400200a0f0b41ecc200200a2001103c000b41b4c20020082001103c000b0bdb3b02004180080bec282f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f73657373696f6e2f7372632f6c69622e72737365733a696e647365733a6c656e7365733a6c6c637365733a6e6c6e7365733a76616c00000000002f636865636b6f75742f7372632f6c6962636f72652f6f70732f61726974682e72730000000000000000000000000000617474656d707420746f20646976696465206279207a65726f00000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f616c6c206974656d7320636f6d652066726f6d2060766f74657273603b20666f7220616e206974656d20746f20626520696e2060766f7465727360207468657265206d757374206265206120766f746520726567697374657265643b2071656448617368206e6f7420657175616c52756e74696d65206d656d6f7279206578686175737465642e2041626f7274696e676c6962616c6c6f632f7261775f7665632e72736361706163697479206f766572666c6f7774696d3a64696454696d657374616d70206d7573742062652075706461746564206f6e636520696e2074686520626c6f636b2f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f74696d657374616d702f7372632f6c69622e727374696d3a76616c54696d657374616d70206d7573742062652066697273742065787472696e73696320696e2074686520626c6f636b54696d657374616d70206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b617373657274696f6e206661696c65643a206175782e69735f656d7074792829656e766578745f7365745f73746f726167656578745f6765745f73746f726167656578745f7472616e736665726578745f6372656174656d656d6f727963616c6c002f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f7374616b696e672f7372632f636f6e74726163742e72730000000000000000000000000000000000000000000000000000000000000000007372632f6c69622e72732f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f636f756e63696c2f7372632f6c69622e7273636f753a6e7874636f753a76636f636f753a76626f636f753a767273636f753a617072636f753a6c616374617267657420666f7220696e616374697669747920636c65616e7570206d75737420626520616374697665636f753a766770636f753a63616e616c6c206974656d7320696e2063616e64696461746573206c697374206172652072656769737465726564636f753a726567636f753a63626f636f753a636e6363616e6e6f742070726573656e74206f757473696465206f662070726573656e746174696f6e20706572696f64636f753a737373636f753a707373636f753a77696e6c6561646572626f617264206d757374206578697374207768696c652070726573656e7420706861736520616374697665636f753a61637470726573656e7465642063616e646964617465206d7573742062652063757272656e7463616e646964617465206d757374206e6f7420666f726d2061206475706c696361746564206d656d62657220696620656c656374656463616e646964617465206e6f7420776f72746879206f66206c6561646572626f61726470726573656e746572206d75737420686176652073756666696369656e7420736c61736861626c652066756e647300000000000000002f636865636b6f75742f7372632f6c6962636f72652f736c6963652f6d6f642e7273696e76616c69642063616e64696461746520736c6f7463616e64696461746520686173206e6f7420656e6f7567682066756e64736475706c69636174652063616e646964617465207375626d697373696f6e72657472616374696f6e20696e646578206d69736d6174636872657472616374696f6e20696e64657820696e76616c696463616e6e6f742072657472616374206e6f6e2d766f74657263616e6e6f742072657472616374207768656e2070726573656e74696e676261642074617267657420696e646578626164207265706f7274657220696e64657863616e6e6f74207265617020647572696e67206772616365207065726964766f746520696e646578206e6f742063757272656e74726561706572206d757374206265206120766f74657263616e6e6f74207265617020647572696e672070726573656e746174696f6e20706572696f64617373657274696f6e206661696c65643a202153656c663a3a70726573656e746174696f6e5f6163746976652829636f753a737473636f753a706475636f753a74726d636f753a706572636f753a63636f66696e616c6973652063616e206f6e6c792062652063616c6c656420616674657220612074616c6c7920697320737461727465642e72756e6e6572207570206d757374206265207265676973746572656400617474656d707420746f20646976696465206279207a65726f000000000000002f636865636b6f75742f7372632f6c6962636f72652f6f70732f61726974682e72730000000000000000000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f53746f7261676520726f6f74206d757374206d6174636820746861742063616c63756c617465642e2f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f6578656375746976652f7372632f6c69622e7273617373657274696f6e206661696c65643a206865616465722e6469676573742829203d3d20263c73797374656d3a3a4d6f64756c653c53797374656d3e3e3a3a6469676573742829416c6c207472616e73616374696f6e732073686f756c6420686176652074686520636f7272656374206e6f6e6365416c6c207472616e73616374696f6e732073686f756c642062652070726f7065726c79207369676e65645472616e73616374696f6e207472696520726f6f74206d7573742062652076616c69642e506172656e7420686173682073686f756c642062652076616c69642e7374726f616765206973206e6f74206e756c6c2c207468657265666f7265206d75737420626520612076616c696420747970656c6962636f72652f726573756c742e727373657269616c697a656420617267732073686f756c642062652070726f7669646564206279207468652072756e74696d653b0a090909636f72726563746c792073657269616c697a656420646174612073686f756c6420626520646573657269616c697a61626c653b0a0909097165642f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652d73616e64626f782f7372632f2e2e2f776974686f75745f7374642e72732f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f7374616b696e672f7372632f6c69622e72737374613a6c65637374613a7370657374613a6572617374613a6e73657374613a77696c3a7374613a7661630000000000000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f000000000000002f636865636b6f75742f7372632f6c6962636f72652f6f70732f61726974682e72737374613a6c6f63617373657274696f6e206661696c65643a20746f5f62616c616e6365202b2076616c7565203e20746f5f62616c616e6365617373657274696f6e206661696c65643a203c426f6e646167653c543e3e3a3a676574287472616e736163746f7229203c3d203c426f6e646167653c543e3e3a3a676574286465737429617373657274696f6e206661696c65643a2066726f6d5f62616c616e6365203e3d2076616c756543616e6e6f7420756e7374616b65206966206e6f7420616c7265616479207374616b65642e43616e6e6f74207374616b6520696620616c7265616479207374616b65642e7374613a666565617474656d707420746f207472616e7361637420776974686f757420656e6f7567682066756e647320746f20706179206665657374613a746f74617373657274696f6e206661696c65643a20266465737420213d207472616e736163746f72617373657274696f6e206661696c65643a2062203e3d2076616c756573746f72616765206973206e6f74206e756c6c2c207468657265666f7265206d75737420626520612076616c6964207479706552657175697265642076616c756573206d75737420626520696e2073746f726167652f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f636f756e63696c2f7372632f766f74696e672e7273636f763a706572696f64636f763a70726f636f763a707273636f763a766f74653a636f763a766f746572733a636f763a636f6f6c6f6666636f763a7665746f3a70726f706f73616c206d75737420657869737420746f206265207665746f65646f6e6c7920636f756e63696c6c6f7273206d6179207665746f20636f756e63696c2070726f706f73616c73617373657274696f6e206661696c65643a202153656c663a3a69735f7665746f6564282670726f706f73616c5f68617368294e6f206475706c69636174652070726f706f73616c7320616c6c6f776564617373657274696f6e206661696c65643a2053656c663a3a77696c6c5f7374696c6c5f62655f636f756e63696c6c6f725f6174286175782e7265665f696e746f28292c2065787069727929616c6c207175657565642070726f706f73616c20686173686573206d7573742068617665206173736f6369617465642070726f706f73616c732f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f64656d6f63726163792f7372632f6c69622e727364656d3a6c617564656d3a707562416c6c2063757272656e74207075626c69632070726f706f73616c73206861766520616e20616d6f756e74206c6f636b65646465706f7369746f727320616c7761797320657869737420666f722063757272656e742070726f706f73616c7364656d3a70657264656d3a6e787464656d3a72636f43616e6e6f7420696e6a6563742061207265666572656e64756d207468617420656e6473206561726c696572207468616e2070726563656564696e67207265666572656e64756d63616c6c656420604f7074696f6e3a3a756e77726170282960206f6e206120604e6f6e65602076616c75656c6962636f72652f6f7074696f6e2e7273002f636865636b6f75742f7372632f6c6962636f72652f736c6963652f6d6f642e72730000000000000000000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f000000000000002f636865636b6f75742f7372632f6c6962636f72652f6f70732f61726974682e727364656d3a6d696e64656d3a70706363616e206f6e6c79207365636f6e6420616e206578697374696e672070726f706f73616c7472616e736163746f72206d75737420686176652062616c616e636520746f207369676e616c20617070726f76616c2e766f746520676976656e20666f7220696e76616c6964207265666572656e64756d2e617373657274696f6e206661696c65643a203c7374616b696e673a3a4d6f64756c653c543e3e3a3a6465647563745f756e626f6e646564286175782e7265665f696e746f28292c206465706f7369742e3029617373657274696f6e206661696c65643a203c7374616b696e673a3a4d6f64756c653c543e3e3a3a6465647563745f756e626f6e646564286175782e7265665f696e746f28292c2076616c756529617373657274696f6e206661696c65643a2076616c7565203e3d2053656c663a3a6d696e696d756d5f6465706f736974282900000000000000002f636865636b6f75742f7372632f6c6962636f72652f736c6963652f6d6f642e727300000000000000000000000000002f636865636b6f75742f7372632f6c6962616c6c6f632f736c6963652e7273696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f64652f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f636f6e73656e7375732f7372632f6c69622e72733a617574683a7379733a6f6c640000007379733a6e756d7379733a7068617379733a7478727379733a726e647379733a787469426c6f636b206e756d626572206d6179206e65766572206265207a65726f2f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f73797374656d2f7372632f6c69622e72737379733a6e6f6e7379733a7874647379733a6469676c656e5f5f5068616e746f6d4974656d2073686f756c64206e6576657220626520757365642e3a636f6465000000000000002f636865636b6f75742f7372632f6c6962636f72652f736c6963652f736f72742e7273617373657274696f6e206661696c65643a206d6964203c3d206c656e6c6962636f72652f736c6963652f6d6f642e7273000000000000000000000000002f636865636b6f75742f7372632f6c6962636f72652f736c6963652f6d6f642e7273617373657274696f6e206661696c65643a20696e646578203c3d206c656e6c6962616c6c6f632f7665632e7273617373657274696f6e206661696c65643a20696e646578203c206c656e0041ec300be0124f1600002800000000040000480000003300000001000000711700002300000000040000480000003300000001000000a0040000190000007004000022000000c50100002d000000c00400003900000070040000220000001a0200002d0000004f160000280000001f0e0000530000006f000000090000004f160000280000001f0e00005300000078000000090000009c050000110000008905000013000000e502000005000000df17000014000000d008000005000000df17000014000000d608000005000000fe130000110000009203000005000000b40500002b000000df0500004a0000004b000000030000007117000023000000df0500004a0000002b000000010000008e06000020000000df0500004a00000041000000030000005e06000030000000df0500004a0000004200000003000000300600002e000000df0500004a0000004300000003000000f00600004d0000008700000012000000f00600004d0000008800000012000000f00600004d000000890000000f000000f00600004d0000007000000019000000f00600004d0000007100000019000000f00600004d000000720000000f000000f00600004d0000005e00000016000000f00600004d0000005f00000012000000f00600004d0000003d00000016000000f00600004d0000003e00000018000000f00600004d0000003f000000130000004f16000028000000df0500004a0000002b000000010000005e0700000a000000a8000000020000004f1600002800000068070000480000006500000001000000711700002300000068070000480000006500000001000000ed0a00002e0000006807000048000000e3000000030000006807000048000000e400000003000000c70a0000260000006807000048000000f800000003000000b10a0000160000006807000048000000f9000000030000009b0a0000160000006807000048000000fb000000030000007d0a00001e0000006807000048000000fc000000030000008009000022000000200900000a0000006b0a000012000000680700004800000000010000030000005b0a000010000000680700004800000001010000030000003d0a00001e00000068070000480000001b01000003000000250a00001800000068070000480000001c010000030000000d0a00001800000068070000480000001f01000003000000f40900001900000068070000480000002001000003000000d60900001e00000068070000480000002901000003000000b80900001e00000068070000480000002a01000003000000a20900001600000068070000480000002f010000030000008009000022000000260900000e000000680700004800000044010000030000004a0900002e00000068070000480000004a01000003000000270900002300000068070000480000004d01000003000000f1080000360000006807000048000000500100000400000080090000220000003c02000023000000e00b000039000000b00b0000220000001a0200002d000000900b000019000000b00b000022000000c50100002d0000004f0d00001c000000410c00004a00000050000000030000002b0d000024000000410c00004a00000058000000030000008b0c000048000000410c00004a0000009c00000003000000190c000028000000410c00004a000000a400000003000000010d00002a000000410c00004a000000850000000e000000d30c00002e000000410c00004a0000008b000000040000009e0d000011000000b1030000050000004f160000280000001f0e00005300000008010000090000004f16000028000000720e0000480000005b00000001000000f00e000039000000300f0000220000001a0200002d000000201000001f000000720e000048000000c800000003000000fb0f000025000000720e000048000000d6000000040000007117000023000000720e0000480000005b00000001000000d40f000027000000720e00004800000030020000030000008a0f00004a000000720e0000480000003302000003000000590f000031000000720e00004800000034020000030000000600000000000000010000000700000008000000090000000a0000000b0000000c0000000d0000004610000033000000720e0000480000005702000003000000d40f000027000000720e00004800000016020000030000008010000025000000720e00004800000022020000030000000e00000018000000040000000f000000100000001100000012000000130000001400000015000000a51000001c000000720e00004800000015010000030000004f16000028000000161100004b0000001b000000010000007117000023000000161100004b0000001b000000010000003c1200004b000000161100004b0000004e000000030000001e1200001e000000161100004b0000005200000003000000ec11000032000000161100004b0000005300000003000000c11100002b000000161100004b0000006900000003000000a111000020000000161100004b0000006a000000030000004f16000028000000c01200004a0000003900000001000000401400003900000080140000220000001a0200002d00000010140000220000003c02000023000000d31300002b000000fe130000110000004f010000150000008c13000047000000c01200004a000000d9000000040000007117000023000000c01200004a0000003900000001000000c615000032000000c01200004a0000009300000003000000781500004e000000c01200004a00000094000000030000002615000052000000c01200004a000000a2000000030000000415000022000000c01200004a000000ac00000004000000d414000030000000c01200004a000000af000000040000000016000022000000200900000a0000000016000022000000260900000e000000301600001f000000b20200001e000000301600001f000000b5020000360000004f16000028000000771600004a0000003b00000001000000f41600001e00000012170000470000007d000000030000007117000023000000771600004a0000003b0000000100000000180000220000003d02000023000000c31700001c000000df17000014000000cc0100000d000000a017000023000000910200001d00000000180000220000003c02000023000000a017000023000000a70000003a000000a017000023000000ae00000030000000221800001e000000401800000f00000047030000090000004f1800001d000000401800000f0000006f03000009000000000c076c696e6b696e670302cc3b00ff8401046e616d6501f68401e40100146578745f6765745f73746f726167655f696e746f010a6578745f6d616c6c6f6302086578745f66726565030c6578745f74776f785f313238040f6578745f7365745f73746f7261676505116578745f636c6561725f73746f72616765060a6578745f6d656d636d7007186578745f656e756d6572617465645f747269655f726f6f74080e6578745f7072696e745f75746638090d6578745f7072696e745f6e756d0a0a6578745f6d656d6370790b0b6578745f6d656d6d6f76650c0a6578745f6d656d7365740d166578745f73616e64626f785f6d656d6f72795f6e65770e176578745f73616e64626f785f696e7374616e74696174650f126578745f73616e64626f785f696e766f6b6510166578745f73616e64626f785f6d656d6f72795f67657411166578745f73616e64626f785f6d656d6f72795f736574120e6578745f626c616b65325f323536130d6578745f7072696e745f68657814106578745f73746f726167655f726f6f7415126578745f656432353531395f76657269667916773c7375627374726174655f72756e74696d655f7072696d6974697665733a3a67656e657269633a3a4469676573743c4974656d3e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a686366613333306530633737643531613517066d656d73657418393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a6838313936363666396265663463633931194b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68646339636565313232303362623835621a4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68353632363038323130343238623465631b4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68653335663962326562366332393066621c24616c6c6f633a3a616c6c6f633a3a6f6f6d3a3a68613732396634666436376436376633391d8b013c7375627374726174655f72756e74696d655f7072696d6974697665733a3a67656e657269633a3a4865616465723c4e756d6265722c20486173682c204469676573744974656d3e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a68306561356233376164373865313636341e066d656d6370791f573c616c6c6f633a3a7665633a3a5665633c75383e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a683135633166653139313338396266313020a0013c7375627374726174655f72756e74696d655f7072696d6974697665733a3a67656e657269633a3a556e636865636b656445787472696e7369633c4163636f756e7449642c20496e6465782c2043616c6c2c205369676e61747572653e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a686666343637646332363738333264373321583c616c6c6f633a3a626f7865643a3a426f783c543e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a683733356130396161356431326165663322345f5a4e34636f726533707472313364726f705f696e5f706c61636531376834616536316365303665356638316331452e3138363723393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a6835646661343736643064326634353464244b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6831623238376135353263616531393734252b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a683461653631636530366535663831633126a0013c7375627374726174655f72756e74696d655f7072696d6974697665733a3a67656e657269633a3a556e636865636b656445787472696e7369633c4163636f756e7449642c20496e6465782c2043616c6c2c205369676e61747572653e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a656e636f64653a3a6862346461326637656565363934383334273a3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a726573657276653a3a6861623665336266623631626431356231285a3c706f6c6b61646f745f72756e74696d653a3a43616c6c206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a656e636f64653a3a68393931323239363862316130396334322934636f72653a3a736c6963653a3a736c6963655f696e6465785f6c656e5f6661696c3a3a68363938393263393438396363616162622a363c5420617320636f72653a3a636f6e766572743a3a496e746f3c553e3e3a3a696e746f3a3a68353666353936643634373237343833632b8d015f5a4e34395f244c5424616c6c6f632e2e7261775f7665632e2e526177566563244c54245424432424753230244124475424244754243131616c6c6f636174655f696e32385f24753762242475376224636c6f737572652475376424247537642431376838343739373131363565646633646537452e6c6c766d2e3632303339333138363734383337373033382c493c7375627374726174655f72756e74696d655f73657373696f6e3a3a4d6f64756c653c543e3e3a3a726f746174655f73657373696f6e3a3a68663938353764613535613230616562632d2e636f72653a3a6f7074696f6e3a3a6578706563745f6661696c65643a3a68653163323536643932353565393632662e463c7375627374726174655f72756e74696d655f73797374656d3a3a4d6f64756c653c543e3e3a3a626c6f636b5f6e756d6265723a3a68313635316433343866326134346235372f527375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653a3a726571756972653a3a6861313164373161613165393864646363304b3c54206173207375627374726174655f636f6465633a3a6b657965647665633a3a4b657965645665633e3a3a746f5f6b657965645f7665633a3a6866346339626432626430633262303964314f7375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765745f6f725f64656661756c743a3a6837623835343430353965333637333638324b3c54206173207375627374726174655f636f6465633a3a6b657965647665633a3a4b657965645665633e3a3a746f5f6b657965645f7665633a3a686466633130663239626637643964313133523c636f72653a3a697465723a3a436c6f6e65643c493e20617320636f72653a3a697465723a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a683032316562386262636530636661323334583c28412c204229206173207375627374726174655f72756e74696d655f7072696d6974697665733a3a7472616974733a3a45786563757461626c653e3a3a657865637574653a3a6863373034616135306561623165643139359f017375627374726174655f72756e74696d655f636f756e63696c3a3a766f74696e673a3a3c696d706c207375627374726174655f72756e74696d655f7072696d6974697665733a3a7472616974733a3a45786563757461626c6520666f72207375627374726174655f72756e74696d655f636f756e63696c3a3a4d6f64756c653c543e3e3a3a657865637574653a3a683730353563353930613161356165386336597375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653a3a6765745f6f725f64656661756c743a3a686432656434346461383333643033393337473c7375627374726174655f72756e74696d655f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a6465706f7369745f6f663a3a6864356630353863656136333834623032382b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a683436373662323538363033663731396439076d656d6d6f76653a563c616c6c6f633a3a7665633a3a5665633c543e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a68653630626561346331643730393736643b29636f72653a3a70616e69636b696e673a3a70616e69633a3a68313137323734323133346465393231303c36636f72653a3a70616e69636b696e673a3a70616e69635f626f756e64735f636865636b3a3a68363630346666363535326232666562323d413c7375627374726174655f72756e74696d655f7374616b696e673a3a4d6f64756c653c543e3e3a3a726566756e643a3a68633362613564623165383537303661313e86013c7375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a52756e74696d6553746f72616765206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a68656161636164343939313263336335363f4e3c7375627374726174655f72756e74696d655f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a696e6a6563745f7265666572656e64756d3a3a6863653264346134373837396137323635404c3c7375627374726174655f72756e74696d655f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a7265666572656e64756d5f696e666f3a3a68356430386136656330613537303133384134616c6c6f633a3a7261775f7665633a3a63617061636974795f6f766572666c6f773a3a686334316261316636346437363033373942473c7375627374726174655f72756e74696d655f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a766f746572735f666f723a3a686539303831303936616133363162333843473c7375627374726174655f72756e74696d655f7374616b696e673a3a4d6f64756c653c543e3e3a3a667265655f62616c616e63653a3a6862653837643063316262386365323731444b3c7375627374726174655f72756e74696d655f7374616b696e673a3a4d6f64756c653c543e3e3a3a72657365727665645f62616c616e63653a3a6865623966656232366134653538343433453e7375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653a3a656e636f64653a3a6835666661663632366231656464306238464d3c7375627374726174655f72756e74696d655f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a636c6561725f7265666572656e64756d3a3a683065326261346565363332393465346547597375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653a3a6765745f6f725f64656661756c743a3a686364633932303862653939363865303148423c7375627374726174655f72756e74696d655f7374616b696e673a3a4d6f64756c653c543e3e3a3a6e65775f6572613a3a6834333536343534386630353530373663493a3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a726573657276653a3a68666363653264376532363234386132664a86013c7375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a52756e74696d6553746f72616765206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a68383237346662353239326530653935384b345f5a4e34636f726533707472313364726f705f696e5f706c61636531376834616536316365303665356638316331452e313933304c6d3c7375627374726174655f72756e74696d655f696f3a3a426c616b6554776f323536206173207375627374726174655f72756e74696d655f696f3a3a48617368696e673e3a3a656e756d6572617465645f747269655f726f6f743a3a68373531363037396363363934643362344d11727573745f626567696e5f756e77696e644e08727573745f6f6f6d4f393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a683934323963666464366239343939316550463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a686638333437636630333536663137633751573c616c6c6f633a3a7665633a3a5665633c75383e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a656e636f64653a3a683562613039363631356162393163653352066d616c6c6f63530466726565542d636f72653a3a70616e69636b696e673a3a70616e69635f666d743a3a68343066313034346338363430636537655536636f72653a3a736c6963653a3a736c6963655f696e6465785f6f726465725f6661696c3a3a6838313330343432303532386232613865564b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6832653739643730623164373537336236574b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6834333337316334333361323734393066584b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6835653639393561353131376336316261594b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68393332616436626561643261373838325a4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68643335646131306634323134323937335b4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68306464323861643233626338353865665c4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68323236353666303366323931393738325d4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68626461366634636434623039663433665e4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68303139363230336638363464396133345f4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6862396532346165643662353163376566604b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6863613166626538323365653436383431614b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6862323236663235303162633264306264624b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6836333364303435386436356363393863634b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6866616563633135353361633333613835644b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6861356133316562653333306639326635654b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6832376361366365373461626664666264664b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6836323932333830613439323131383638674b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a686163306336633862333061653039663768393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a683063653362633633326336616364326169463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68376636633966373761363663373937636a393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a68343038373662383637653261396330396b463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68383863616164303861633361623961646c393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a68353262366336626163626135633061386d463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68623437366264373632363935623330336e463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68326132353062613265323263336337396f393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a683636323532376436666130383237343470463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a683365363965636439633766616165306371393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a683764313835303766636661646366353972463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a686335663366366638303064303431353273463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a683738366438643636323036316564613074393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a686261353735613734386133306233306375463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a686532653262373435333764623266386476393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a686461363738663731646162613761666577463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a683863323961323539383931333766343978393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a686463356361653038383331346337376679463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68326161633766383935303734356563397a393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a68646433633635373262343532613031347b463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68626462393236656664376432346539387c393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a68653333366232306266663138383930347d463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68346633396332623430636437333963347e393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a68653338643736373866303134323236317f463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68363862383536613030333235623134628001393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a68656330653961326130616435633466648101463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a683838636134306365646335303261316282013a3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a726573657276653a3a683534343836366335623963663730373583013a3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a726573657276653a3a683734393131616635323537633037393784013a3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a726573657276653a3a683735663262666638613830643365623985013a3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a726573657276653a3a683863616636616537333938376436346386013a3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a726573657276653a3a68653033623365323432663733346433308701503c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68393537643736623535353030646266348801c3013c616c6c6f633a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75743c27613e2c204b2c20562c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4c6561663e2c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3e3a3a696e736572743a3a68353731386465393136646662313737328901c3013c616c6c6f633a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75743c27613e2c204b2c20562c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4c6561663e2c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3e3a3a696e736572743a3a68373463373532366661626363646564358a01c7013c616c6c6f633a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75743c27613e2c204b2c20562c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a496e7465726e616c3e2c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3e3a3a696e736572743a3a68343437336564333066636136316137308b01cb013c616c6c6f633a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75743c27613e2c204b2c20562c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a496e7465726e616c3e2c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3e3a3a696e736572745f6669743a3a68326333636630383765623331663734338c01c7013c616c6c6f633a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75743c27613e2c204b2c20562c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a496e7465726e616c3e2c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3e3a3a696e736572743a3a68386365653235383631313166343439668d01cb013c616c6c6f633a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75743c27613e2c204b2c20562c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a496e7465726e616c3e2c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3e3a3a696e736572745f6669743a3a68663630346163643262623861646636648e013f7375627374726174655f72756e74696d655f7374616b696e673a3a636f6e74726163743a3a657865637574653a3a68666332303937306166616238363265658f01507375627374726174655f72756e74696d655f7374616b696e673a3a636f6e74726163743a3a657865637574653a3a6578745f7365745f73746f726167653a3a68633235623630316631346635383463389001507375627374726174655f72756e74696d655f7374616b696e673a3a636f6e74726163743a3a657865637574653a3a6578745f6765745f73746f726167653a3a683736613962653764306632343937316491014d7375627374726174655f72756e74696d655f7374616b696e673a3a636f6e74726163743a3a657865637574653a3a6578745f7472616e736665723a3a683632326464636435333464616431363892014b7375627374726174655f72756e74696d655f7374616b696e673a3a636f6e74726163743a3a657865637574653a3a6578745f6372656174653a3a68396363303263356565333664303032379301417375627374726174655f72756e74696d655f73616e64626f783a3a696d703a3a64697370617463685f7468756e6b3a3a683939386139316165306131663037633594017f3c7375627374726174655f72756e74696d655f7374616b696e673a3a4f7665726c61794163636f756e7444623c27612c20543e206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a7365745f73746f726167653a3a683035373136666235306661623636643395017f3c7375627374726174655f72756e74696d655f7374616b696e673a3a4f7665726c61794163636f756e7444623c27612c20543e206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a683031326363613031653639396364643996013b3c616c6c6f633a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e3e3a3a6765743a3a6865383334633533623431306361303264970134616c6c6f633a3a62747265653a3a7365617263683a3a7365617263685f747265653a3a68613435343266643037623530613430349801653c616c6c6f633a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e20617320636f72653a3a697465723a3a7472616974733a3a496e746f4974657261746f723e3a3a696e746f5f697465723a3a68323337613934396465633834333065369901553c616c6c6f633a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68663765393037343761386636613332309a01453c616c6c6f633a3a62747265653a3a6d61703a3a566163616e74456e7472793c27612c204b2c20563e3e3a3a696e736572743a3a68616639316138373166656365356538369b017c3c7375627374726174655f72756e74696d655f7374616b696e673a3a4f7665726c61794163636f756e7444623c27612c20543e206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6765745f636f64653a3a68636634333438326462356135353864349c01793c7375627374726174655f72756e74696d655f7374616b696e673a3a4f7665726c61794163636f756e7444623c27612c20543e206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6d657267653a3a68306134623934346339646231343665329d01653c616c6c6f633a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e20617320636f72653a3a697465723a3a7472616974733a3a496e746f4974657261746f723e3a3a696e746f5f697465723a3a68336331666362643134643933623735619e01553c616c6c6f633a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68626262323936373561396334396234399f012e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a6866313734613335313966343639373764a0016c3c7375627374726174655f72756e74696d655f64656d6f63726163793a3a5072697643616c6c3c543e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a6836313935643931346137663363333636a1010b617574686f726974696573a201563c616c6c6f633a3a7665633a3a5665633c543e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a656e636f64653a3a6834663037313434396230306561366362a30110696e697469616c6973655f626c6f636ba401443c7375627374726174655f72756e74696d655f73797374656d3a3a4d6f64756c653c543e3e3a3a696e697469616c6973653a3a6832326337643330356130373863393035a5010f6170706c795f65787472696e736963a601783c7375627374726174655f72756e74696d655f6578656375746976653a3a4578656375746976653c53797374656d2c20426c6f636b2c205061796d656e742c2046696e616c69736174696f6e3e3e3a3a6170706c795f65787472696e7369635f696e6e65723a3a6836303438333536646465653962326663a7010d657865637574655f626c6f636ba801443c7375627374726174655f72756e74696d655f73797374656d3a3a4d6f64756c653c543e3e3a3a626c6f636b5f686173683a3a6838333036626630323533366265386266a901523c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20493e3e3a3a66726f6d5f697465723a3a6863383933623037366263653438356361aa01423c7375627374726174655f72756e74696d655f73797374656d3a3a4d6f64756c653c543e3e3a3a66696e616c6973653a3a6835643638333133636232646637366465ab010e66696e616c6973655f626c6f636bac010f76616c696461746f725f636f756e74ad010a76616c696461746f7273ae01793c7375627374726174655f72756e74696d655f636f756e63696c3a3a43616c6c3c543e206173207375627374726174655f72756e74696d655f737570706f72743a3a64697370617463683a3a417578446973706174636861626c653e3a3a64697370617463683a3a6836363435303363376332313138323333af01563c55206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a6578697374733a3a6837323366316130366637356338376235b001473c7375627374726174655f72756e74696d655f636f756e63696c3a3a4d6f64756c653c543e3e3a3a72656d6f76655f766f7465723a3a6837326137643235373861356638346333b101563c55206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6830396163353435653961376538333833b2014a3c7375627374726174655f72756e74696d655f7374616b696e673a3a4d6f64756c653c543e3e3a3a6465647563745f756e626f6e6465643a3a6835366234393235363039633261333763b3014c3c7375627374726174655f72756e74696d655f636f756e63696c3a3a4d6f64756c653c543e3e3a3a766f7465725f6c6173745f6163746976653a3a6862336538666236373336303764663063b401473c7375627374726174655f72756e74696d655f636f756e63696c3a3a4d6f64756c653c543e3e3a3a617070726f76616c735f6f663a3a6865333163643561323839663761303839b5014d3c7375627374726174655f72756e74696d655f636f756e63696c3a3a4d6f64756c653c543e3e3a3a63616e6469646174655f7265675f696e666f3a3a6866303561313635613136333135646633b601563c616c6c6f633a3a7665633a3a5665633c543e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a6831613262363530646163366431306537b70186013c7375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a52756e74696d6553746f72616765206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a6866373862303163316265363933623132b801563c616c6c6f633a3a7665633a3a5665633c543e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a656e636f64653a3a6862636662316161343963386239396538b901543c636f72653a3a697465723a3a436861696e3c412c20423e20617320636f72653a3a697465723a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6839313464643736343236613933323338ba01563c7375627374726174655f72756e74696d655f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a696e7465726e616c5f73746172745f7265666572656e64756d3a3a6864663562353935316539353236643238bb01527375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653a3a726571756972653a3a6862646338666238653461356339396261bc0186013c7375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a52756e74696d6553746f72616765206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a6836363231356566633664633732336432bd015e3c706f6c6b61646f745f72756e74696d653a3a5072697643616c6c206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a6836636664343364363366653539376139be013e7375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653a3a656e636f64653a3a6834356437316332383730346338366538bf01345f5a4e34636f726533707472313364726f705f696e5f706c61636531376834616536316365303665356638316331452e31383434c001473c7375627374726174655f72756e74696d655f73797374656d3a3a4d6f64756c653c543e3e3a3a6163636f756e745f696e6465783a3a6830663032313835306531326631353532c1016d3c706f6c6b61646f745f72756e74696d653a3a43616c6c206173207375627374726174655f72756e74696d655f737570706f72743a3a64697370617463683a3a417578446973706174636861626c653e3a3a64697370617463683a3a6862353365306137383562356439313664c2012e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a6835636361383862626431396436663637c3012e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a6861636366363539333334346266343932c4012d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6865653866663861633636343163366337c501563c55206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6836643335643961613335663530373466c601773c7375627374726174655f72756e74696d655f7374616b696e673a3a4469726563744163636f756e744462206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6839366364653364613533393430373432c701713c7375627374726174655f72756e74696d655f7374616b696e673a3a4469726563744163636f756e744462206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6d657267653a3a6863386138646538333035626335356661c8015e3c616c6c6f633a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a697465723a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6839663430373961306139316533623539c901563c55206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6839633838336432616334356335643565ca015e3c616c6c6f633a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a697465723a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6831353032303864643239373239616232cb013e7375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653a3a656e636f64653a3a6866653733303335653834393636616231cc012b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6837313232393564313131373938333732cd01773c7375627374726174655f72756e74696d655f7374616b696e673a3a4469726563744163636f756e744462206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a6865626533633663393533393837616132ce01743c7375627374726174655f72756e74696d655f7374616b696e673a3a4469726563744163636f756e744462206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6765745f636f64653a3a6837376330653737383334326563333934cf01773c7375627374726174655f72756e74696d655f7374616b696e673a3a4469726563744163636f756e744462206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a7365745f73746f726167653a3a6862663865653331383633303066393130d001743c7375627374726174655f72756e74696d655f7374616b696e673a3a4469726563744163636f756e744462206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a7365745f636f64653a3a6834393266643631333433343565656533d101773c7375627374726174655f72756e74696d655f7374616b696e673a3a4469726563744163636f756e744462206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a7365745f62616c616e63653a3a6861303936363266636534323061373632d2013e3c616c6c6f633a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e3e3a3a696e736572743a3a6863313238323330343366616132306235d3012b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6862623666313834333462363831646364d4017f3c7375627374726174655f72756e74696d655f7374616b696e673a3a4f7665726c61794163636f756e7444623c27612c20543e206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6864333339636666326536626431326136d5017c3c7375627374726174655f72756e74696d655f7374616b696e673a3a4f7665726c61794163636f756e7444623c27612c20543e206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a7365745f636f64653a3a6832353031306366393163383531653633d6017f3c7375627374726174655f72756e74696d655f7374616b696e673a3a4f7665726c61794163636f756e7444623c27612c20543e206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a7365745f62616c616e63653a3a6835663038363634343266663639663034d70186013c7375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a52756e74696d6553746f72616765206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a6833663831363961656164316536306634d8015e3c706f6c6b61646f745f72756e74696d653a3a5072697643616c6c206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a656e636f64653a3a6864323261663136323532663732653865d901587375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653a3a74616b655f6f725f70616e69633a3a6865373635393838373032386265316365da01597375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653a3a6765745f6f725f64656661756c743a3a6834623732396637663566373061363932db0181013c7375627374726174655f72756e74696d655f636f756e63696c3a3a766f74696e673a3a43616c6c3c543e206173207375627374726174655f72756e74696d655f737570706f72743a3a64697370617463683a3a417578446973706174636861626c653e3a3a64697370617463683a3a6830653834363332383930313361343764dc014a3c7375627374726174655f72756e74696d655f636f756e63696c3a3a766f74696e673a3a4d6f64756c653c543e3e3a3a7665746f5f6f663a3a6862306633653061333063356237626537dd01563c55206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6834336534383363363337326338613963de01563c55206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6866323533306336323935613261646262df01563c55206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6863373164346434623063343438383037e0014c3c706f6c6b61646f745f72756e74696d653a3a5072697643616c6c20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6833623430356561333864626335613735e10134636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6836346333343639613537386236366265e2012e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6830386534373738303065643562646365e3013c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6838643731323265613337623036313336", -"0x0346fb0f1ce64e1a02c4959d38ebad38": "0x00000000"} diff --git a/polkadot/cli/src/chain_spec.rs b/polkadot/cli/src/chain_spec.rs index 3092bcd4a9192..7298a4cdff98a 100644 --- a/polkadot/cli/src/chain_spec.rs +++ b/polkadot/cli/src/chain_spec.rs @@ -16,6 +16,8 @@ //! Predefined chains. +use service; + /// The chain specification (this should eventually be replaced by a more general JSON-based chain /// specification). #[derive(Clone, Debug)] @@ -24,50 +26,32 @@ pub enum ChainSpec { Development, /// Whatever the current runtime is, with simple Alice/Bob auths. LocalTestnet, - /// The PoC-1 testnet. - PoC1Testnet, - /// The PoC-2 testnet. - PoC2Testnet, - /// Custom Genesis file. - Custom(String), + /// The PoC-1 & PoC-2 era testnet. + KrummeLanke, + /// Whatever the current runtime is with the "global testnet" defaults. + StagingTestnet, } -impl<'a> From<&'a str> for ChainSpec { - fn from(s: &'a str) -> Self { - match s { - "dev" => ChainSpec::Development, - "local" => ChainSpec::LocalTestnet, - "poc-1" => ChainSpec::PoC1Testnet, - "poc-2" => ChainSpec::PoC2Testnet, - s => ChainSpec::Custom(s.into()), - } +/// Get a chain config from a spec setting. +impl ChainSpec { + pub(crate) fn load(self) -> Result { + Ok(match self { + ChainSpec::KrummeLanke => service::chain_spec::poc_1_testnet_config()?, + ChainSpec::Development => service::chain_spec::development_config(), + ChainSpec::LocalTestnet => service::chain_spec::local_testnet_config(), + ChainSpec::StagingTestnet => service::chain_spec::staging_testnet_config(), + }) } -} -impl From for String { - fn from(s: ChainSpec) -> String { + pub(crate) fn from(s: &str) -> Option { match s { - ChainSpec::Development => "dev".into(), - ChainSpec::LocalTestnet => "local".into(), - ChainSpec::PoC1Testnet => "poc-1".into(), - ChainSpec::PoC2Testnet => "poc-2".into(), - ChainSpec::Custom(f) => format!("custom ({})", f), + "dev" => Some(ChainSpec::Development), + "local" => Some(ChainSpec::LocalTestnet), + "poc-1" => Some(ChainSpec::KrummeLanke), + "" | "krummelanke" => Some(ChainSpec::KrummeLanke), + "staging" => Some(ChainSpec::StagingTestnet), + _ => None, } } } -impl ::std::fmt::Display for ChainSpec { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - if let ChainSpec::Custom(n) = self { - write!(f, "Custom ({})", n) - } else { - write!(f, "{}", match *self { - ChainSpec::Development => "Development", - ChainSpec::LocalTestnet => "Local Testnet", - ChainSpec::PoC1Testnet => "PoC-1 Testnet", - ChainSpec::PoC2Testnet => "PoC-2 Testnet", - _ => unreachable!(), - }) - } - } -} diff --git a/polkadot/cli/src/cli.yml b/polkadot/cli/src/cli.yml deleted file mode 100644 index 49ccd36d5d166..0000000000000 --- a/polkadot/cli/src/cli.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: polkadot -author: "Parity Team " -about: Polkadot Node Rust Implementation -args: - - log: - short: l - long: log - value_name: LOG_PATTERN - help: Sets a custom logging filter - takes_value: true - - base-path: - long: base-path - short: d - value_name: PATH - help: Specify custom base path - takes_value: true - - keystore-path: - long: keystore-path - value_name: PATH - help: Specify custom keystore path - takes_value: true - - key: - long: key - value_name: STRING - help: Specify additional key seed - takes_value: true - - node-key: - long: node-key - value_name: KEY - help: Specify node secret key (64-character hex string) - takes_value: true - - collator: - long: collator - help: Enable collator mode - takes_value: false - - validator: - long: validator - help: Enable validator mode - takes_value: false - - light: - long: light - help: Run in light client mode - takes_value: false - - dev: - long: dev - help: Run in development mode; implies --chain=dev --validator --key Alice - takes_value: false - - build-genesis: - long: build-genesis - help: Build a genesis.json file, outputing to stdout - takes_value: false - - port: - long: port - value_name: PORT - help: Specify p2p protocol TCP port - takes_value: true - - rpc-port: - long: rpc-port - value_name: PORT - help: Specify HTTP RPC server TCP port - takes_value: true - - ws-port: - long: ws-port - value_name: PORT - help: Specify WebSockets RPC server TCP port - takes_value: true - - bootnodes: - long: bootnodes - value_name: URL - help: Specify a list of bootnodes - takes_value: true - multiple: true - - chain: - long: chain - value_name: CHAIN_SPEC - help: Specify the chain specification (one of dev, local or poc-2) - takes_value: true - - name: - long: name - value_name: NAME - help: The human-readable name for this node, as reported to the telemetry server, if enabled - takes_value: true - - telemetry: - short: t - long: telemetry - help: Should connect to the Polkadot telemetry server (off by default) - takes_value: false - - telemetry-url: - long: telemetry-url - value_name: TELEMETRY_URL - help: The URL of the telemetry server. Implies --telemetry - takes_value: true -subcommands: diff --git a/polkadot/cli/src/lib.rs b/polkadot/cli/src/lib.rs index d70b0cff9cd41..b2da24ee10394 100644 --- a/polkadot/cli/src/lib.rs +++ b/polkadot/cli/src/lib.rs @@ -17,101 +17,55 @@ //! Polkadot CLI library. #![warn(missing_docs)] +#![warn(unused_extern_crates)] -extern crate app_dirs; -extern crate env_logger; -extern crate atty; -extern crate ansi_term; -extern crate regex; -extern crate time; extern crate futures; -extern crate tokio_core; -extern crate ctrlc; -extern crate fdlimit; -extern crate ed25519; -extern crate triehash; -extern crate parking_lot; -extern crate serde; -extern crate serde_json; +extern crate tokio; -extern crate substrate_primitives; -extern crate substrate_state_machine as state_machine; -extern crate substrate_client as client; -extern crate substrate_network as network; -extern crate substrate_rpc; -extern crate substrate_rpc_servers as rpc; -extern crate substrate_runtime_primitives as runtime_primitives; -extern crate polkadot_primitives; -extern crate polkadot_runtime; +extern crate substrate_cli as cli; extern crate polkadot_service as service; -#[macro_use] -extern crate slog; // needed until we can reexport `slog_info` from `substrate_telemetry` -#[macro_use] -extern crate substrate_telemetry; -extern crate polkadot_transaction_pool as txpool; +extern crate exit_future; -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate clap; -#[macro_use] -extern crate error_chain; #[macro_use] extern crate log; -#[macro_use] -extern crate hex_literal; -pub mod error; -mod informant; mod chain_spec; -mod preset_config; - -pub use chain_spec::ChainSpec; -pub use preset_config::PresetConfig; -use std::io; -use std::fs::File; -use std::net::SocketAddr; -use std::path::{Path, PathBuf}; -use std::collections::HashMap; -use substrate_primitives::hexdisplay::HexDisplay; -use substrate_primitives::storage::{StorageData, StorageKey}; -use substrate_telemetry::{init_telemetry, TelemetryConfig}; -use runtime_primitives::StorageMap; -use polkadot_primitives::Block; +pub use cli::error; -use futures::sync::mpsc; -use futures::{Sink, Future, Stream}; -use tokio_core::reactor; +use chain_spec::ChainSpec; -const DEFAULT_TELEMETRY_URL: &str = "ws://telemetry.polkadot.io:1024"; +use futures::Future; +use tokio::runtime::Runtime; +pub use service::{Components as ServiceComponents, Service, CustomConfiguration}; +pub use cli::{VersionInfo, IntoExit}; -#[derive(Clone)] -struct SystemConfiguration { - chain_name: String, +fn load_spec(id: &str) -> Result, String> { + Ok(match ChainSpec::from(id) { + Some(spec) => Some(spec.load()?), + None => None, + }) } -impl substrate_rpc::system::SystemApi for SystemConfiguration { - fn system_name(&self) -> substrate_rpc::system::error::Result { - Ok("parity-polkadot".into()) - } - - fn system_version(&self) -> substrate_rpc::system::error::Result { - Ok(crate_version!().into()) - } - - fn system_chain(&self) -> substrate_rpc::system::error::Result { - Ok(self.chain_name.clone()) - } -} - -fn read_storage_json(filename: &str) -> Option { - let file = File::open(PathBuf::from(filename)).ok()?; - let h: HashMap = ::serde_json::from_reader(&file).ok()?; - Some(h.into_iter().map(|(k, v)| (k.0, v.0)).collect()) +/// Additional worker making use of the node, to run asynchronously before shutdown. +/// +/// This will be invoked with the service and spawn a future that resolves +/// when complete. +pub trait Worker: IntoExit { + /// A future that resolves when the work is done or the node should exit. + /// This will be run on a tokio runtime. + type Work: Future + Send + 'static; + + /// Return configuration for the polkadot node. + // TODO: make this the full configuration, so embedded nodes don't need + // string CLI args + fn configuration(&self) -> service::CustomConfiguration { Default::default() } + + /// Do work and schedule exit. + fn work(self, service: &service::Service) -> Self::Work; } -/// Parse command line arguments and start the node. +/// Parse command line arguments into service configuration. /// /// IANA unassigned port ranges that we could use: /// 6717-6766 Unassigned @@ -119,292 +73,49 @@ fn read_storage_json(filename: &str) -> Option { /// 9556-9591 Unassigned /// 9803-9874 Unassigned /// 9926-9949 Unassigned -pub fn run(args: I) -> error::Result<()> where +pub fn run(args: I, worker: W, version: cli::VersionInfo) -> error::Result<()> where I: IntoIterator, T: Into + Clone, + W: Worker, { - let core = reactor::Core::new().expect("tokio::Core could not be created"); - - let yaml = load_yaml!("./cli.yml"); - let matches = match clap::App::from_yaml(yaml).version(crate_version!()).get_matches_from_safe(args) { - Ok(m) => m, - Err(ref e) if e.kind == clap::ErrorKind::VersionDisplayed => return Ok(()), - Err(ref e) if e.kind == clap::ErrorKind::HelpDisplayed || e.kind == clap::ErrorKind::VersionDisplayed => { - let _ = clap::App::from_yaml(yaml).print_long_help(); - return Ok(()); - } - Err(e) => return Err(e.into()), - }; - - // TODO [ToDr] Split parameters parsing from actual execution. - let log_pattern = matches.value_of("log").unwrap_or(""); - init_logger(log_pattern); - fdlimit::raise_fd_limit(); - - info!("Parity ·:· Polkadot"); - info!(" version {}", crate_version!()); - info!(" by Parity Technologies, 2017, 2018"); - let mut config = service::Configuration::default(); - - if let Some(name) = matches.value_of("name") { - config.name = name.into(); - info!("Node name: {}", config.name); - } - - let chain_spec = matches.value_of("chain") - .map(ChainSpec::from) - .unwrap_or_else(|| if matches.is_present("dev") { ChainSpec::Development } else { ChainSpec::PoC2Testnet }); - info!("Chain specification: {}", chain_spec); - - config.chain_name = chain_spec.clone().into(); - - let _guard = if matches.is_present("telemetry") || matches.value_of("telemetry-url").is_some() { - let name = config.name.clone(); - let chain_name = config.chain_name.clone(); - Some(init_telemetry(TelemetryConfig { - url: matches.value_of("telemetry-url").unwrap_or(DEFAULT_TELEMETRY_URL).into(), - on_connect: Box::new(move || { - telemetry!("system.connected"; - "name" => name.clone(), - "implementation" => "parity-polkadot", - "version" => crate_version!(), - "config" => "", - "chain" => chain_name.clone(), - ); - }), - })) - } else { - None - }; - - let base_path = matches.value_of("base-path") - .map(|x| Path::new(x).to_owned()) - .unwrap_or_else(default_base_path); - - config.keystore_path = matches.value_of("keystore") - .map(|x| Path::new(x).to_owned()) - .unwrap_or_else(|| keystore_path(&base_path)) - .to_string_lossy() - .into(); - - config.database_path = db_path(&base_path).to_string_lossy().into(); - - let (mut genesis_storage, boot_nodes) = PresetConfig::from_spec(chain_spec) - .map(PresetConfig::deconstruct) - .unwrap_or_else(|f| (Box::new(move || - read_storage_json(&f) - .map(|s| { info!("{} storage items read from {}", s.len(), f); s }) - .unwrap_or_else(|| panic!("Bad genesis state file: {}", f)) - ), vec![])); - - if matches.is_present("build-genesis") { - info!("Building genesis"); - for (i, (k, v)) in genesis_storage().iter().enumerate() { - print!("{}\n\"0x{}\": \"0x{}\"", if i > 0 {','} else {'{'}, HexDisplay::from(k), HexDisplay::from(v)); + match cli::prepare_execution::(args, worker, version, load_spec, "parity-polkadot")? { + cli::Action::ExecutedInternally => (), + cli::Action::RunService((mut config, worker)) => { + info!("Parity ·:· Polkadot"); + info!(" version {}", config.full_version()); + info!(" by Parity Technologies, 2017, 2018"); + info!("Chain specification: {}", config.chain_spec.name()); + info!("Node name: {}", config.name); + info!("Roles: {:?}", config.roles); + config.custom = worker.configuration(); + let mut runtime = Runtime::new()?; + let executor = runtime.executor(); + match config.roles == service::Roles::LIGHT { + true => run_until_exit(&mut runtime, service::new_light(config, executor)?, worker)?, + false => run_until_exit(&mut runtime, service::new_full(config, executor)?, worker)?, + } + // TODO: hard exit if this stalls? + runtime.shutdown_on_idle().wait().expect("failed to shut down event loop"); } - println!("\n}}"); - return Ok(()) - } - - config.genesis_storage = genesis_storage; - - let role = - if matches.is_present("collator") { - info!("Starting collator"); - service::Role::COLLATOR - } else if matches.is_present("light") { - info!("Starting (light)"); - service::Role::LIGHT - } else if matches.is_present("validator") || matches.is_present("dev") { - info!("Starting validator"); - service::Role::VALIDATOR - } else { - info!("Starting (heavy)"); - service::Role::FULL - }; - - config.roles = role; - { - config.network.boot_nodes = matches - .values_of("bootnodes") - .map_or(Default::default(), |v| v.map(|n| n.to_owned()).collect()); - config.network.boot_nodes.extend(boot_nodes); - config.network.config_path = Some(network_path(&base_path).to_string_lossy().into()); - config.network.net_config_path = config.network.config_path.clone(); - - let port = match matches.value_of("port") { - Some(port) => port.parse().expect("Invalid p2p port value specified."), - None => 30333, - }; - config.network.listen_address = Some(SocketAddr::new("0.0.0.0".parse().unwrap(), port)); - config.network.public_address = None; - config.network.client_version = format!("parity-polkadot/{}", crate_version!()); - config.network.use_secret = match matches.value_of("node-key").map(|s| s.parse()) { - Some(Ok(secret)) => Some(secret), - Some(Err(err)) => return Err(format!("Error parsing node key: {}", err).into()), - None => None, - }; - } - - config.keys = matches.values_of("key").unwrap_or_default().map(str::to_owned).collect(); - if matches.is_present("dev") { - config.keys.push("Alice".into()); - } - - let sys_conf = SystemConfiguration { - chain_name: config.chain_name.clone(), - }; - - match role == service::Role::LIGHT { - true => run_until_exit(core, service::new_light(config)?, &matches, sys_conf), - false => run_until_exit(core, service::new_full(config)?, &matches, sys_conf), } + Ok(()) } - -fn run_until_exit(mut core: reactor::Core, service: service::Service, matches: &clap::ArgMatches, sys_conf: SystemConfiguration) -> error::Result<()> +fn run_until_exit( + runtime: &mut Runtime, + service: service::Service, + worker: W, +) -> error::Result<()> where C: service::Components, - client::error::Error: From<<<::Backend as client::backend::Backend>::State as state_machine::Backend>::Error>, + W: Worker, { - let exit = { - // can't use signal directly here because CtrlC takes only `Fn`. - let (exit_send, exit) = mpsc::channel(1); - ctrlc::CtrlC::set_handler(move || { - exit_send.clone().send(()).wait().expect("Error sending exit notification"); - }); - - exit - }; - - informant::start(&service, core.handle()); - - let _rpc_servers = { - let http_address = parse_address("127.0.0.1:9933", "rpc-port", matches)?; - let ws_address = parse_address("127.0.0.1:9944", "ws-port", matches)?; + let (exit_send, exit) = exit_future::signal(); - let handler = || { - let chain = rpc::apis::chain::Chain::new(service.client(), core.remote()); - rpc::rpc_handler::( - service.client(), - chain, - service.transaction_pool(), - sys_conf.clone(), - ) - }; - ( - start_server(http_address, |address| rpc::start_http(address, handler())), - start_server(ws_address, |address| rpc::start_ws(address, handler())), - ) - }; + let executor = runtime.executor(); + cli::informant::start(&service, exit.clone(), executor.clone()); - core.run(exit.into_future()).expect("Error running informant event loop"); + let _ = runtime.block_on(worker.work(&service)); + exit_send.fire(); Ok(()) } - -fn start_server(mut address: SocketAddr, start: F) -> Result where - F: Fn(&SocketAddr) -> Result, -{ - start(&address) - .or_else(|e| match e.kind() { - io::ErrorKind::AddrInUse | - io::ErrorKind::PermissionDenied => { - warn!("Unable to bind server to {}. Trying random port.", address); - address.set_port(0); - start(&address) - }, - _ => Err(e), - }) -} - -fn parse_address(default: &str, port_param: &str, matches: &clap::ArgMatches) -> Result { - let mut address: SocketAddr = default.parse().ok().ok_or(format!("Invalid address specified for --{}.", port_param))?; - if let Some(port) = matches.value_of(port_param) { - let port: u16 = port.parse().ok().ok_or(format!("Invalid port for --{} specified.", port_param))?; - address.set_port(port); - } - - Ok(address) -} - -fn keystore_path(base_path: &Path) -> PathBuf { - let mut path = base_path.to_owned(); - path.push("keystore"); - path -} - -fn db_path(base_path: &Path) -> PathBuf { - let mut path = base_path.to_owned(); - path.push("db"); - path -} - -fn network_path(base_path: &Path) -> PathBuf { - let mut path = base_path.to_owned(); - path.push("network"); - path -} - -fn default_base_path() -> PathBuf { - use app_dirs::{AppInfo, AppDataType}; - - let app_info = AppInfo { - name: "Polkadot", - author: "Parity Technologies", - }; - - app_dirs::get_app_root( - AppDataType::UserData, - &app_info, - ).expect("app directories exist on all supported platforms; qed") -} - -fn init_logger(pattern: &str) { - use ansi_term::Colour; - - let mut builder = env_logger::LogBuilder::new(); - // Disable info logging by default for some modules: - builder.filter(Some("ws"), log::LogLevelFilter::Warn); - builder.filter(Some("hyper"), log::LogLevelFilter::Warn); - // Enable info for others. - builder.filter(None, log::LogLevelFilter::Info); - - if let Ok(lvl) = std::env::var("RUST_LOG") { - builder.parse(&lvl); - } - - builder.parse(pattern); - let isatty = atty::is(atty::Stream::Stderr); - let enable_color = isatty; - - let format = move |record: &log::LogRecord| { - let timestamp = time::strftime("%Y-%m-%d %H:%M:%S", &time::now()).expect("Error formatting log timestamp"); - - let mut output = if log::max_log_level() <= log::LogLevelFilter::Info { - format!("{} {}", Colour::Black.bold().paint(timestamp), record.args()) - } else { - let name = ::std::thread::current().name().map_or_else(Default::default, |x| format!("{}", Colour::Blue.bold().paint(x))); - format!("{} {} {} {} {}", Colour::Black.bold().paint(timestamp), name, record.level(), record.target(), record.args()) - }; - - if !enable_color { - output = kill_color(output.as_ref()); - } - - if !isatty && record.level() <= log::LogLevel::Info && atty::is(atty::Stream::Stdout) { - // duplicate INFO/WARN output to console - println!("{}", output); - } - output - }; - builder.format(format); - - builder.init().expect("Logger initialized only once."); -} - -fn kill_color(s: &str) -> String { - lazy_static! { - static ref RE: regex::Regex = regex::Regex::new("\x1b\\[[^m]+m").expect("Error initializing color regex"); - } - RE.replace_all(s, "").to_string() -} diff --git a/polkadot/cli/src/preset_config.rs b/polkadot/cli/src/preset_config.rs deleted file mode 100644 index e1a914073ee81..0000000000000 --- a/polkadot/cli/src/preset_config.rs +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Polkadot chain configurations. - -use std::collections::HashMap; -use ed25519; -use serde_json; -use substrate_primitives::{AuthorityId, storage::{StorageKey, StorageData}}; -use runtime_primitives::{MakeStorage, BuildStorage, StorageMap}; -use polkadot_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfig, - SessionConfig, StakingConfig}; -use chain_spec::ChainSpec; - -enum Config { - Local(GenesisConfig), - Raw(&'static [u8]), -} - -/// A configuration of a chain. Can be used to build a genesis block. -pub struct PresetConfig { - genesis_config: Config, - pub(crate) boot_nodes: Vec, -} - -impl BuildStorage for Config { - fn build_storage(self) -> StorageMap { - match self { - Config::Local(gc) => gc.build_storage(), - Config::Raw(json) => { - let h: HashMap = serde_json::from_slice(json).expect("Data is from an internal source and is guaranteed to be of the correct format"); - h.into_iter().map(|(k, v)| (k.0, v.0)).collect() - } - } - } -} - -impl PresetConfig { - /// Get a chain config from a spec, if it's predefined. - pub fn from_spec(chain_spec: ChainSpec) -> Result { - Ok(match chain_spec { - ChainSpec::PoC1Testnet => Self::poc_1_testnet_config(), - ChainSpec::Development => Self::development_config(), - ChainSpec::LocalTestnet => Self::local_testnet_config(), - ChainSpec::PoC2Testnet => Self::poc_2_testnet_config(), - ChainSpec::Custom(f) => return Err(f), - }) - } - - /// Provide the boot nodes and a storage-builder function. - // TODO: Change return type to FnOnce as soon as Box is callable or BoxFn is stablised. - pub fn deconstruct(self) -> (MakeStorage, Vec) { - let mut gc = Some(self.genesis_config); - let f = move || gc.take().map(BuildStorage::build_storage).unwrap_or_default(); - (Box::new(f), self.boot_nodes) - } - - /// PoC-1 testnet config. - fn poc_1_testnet_config() -> Self { - let genesis_config = Config::Raw(include_bytes!("../poc-1.json")); - let boot_nodes = vec![ - "enode://a93a29fa68d965452bf0ff8c1910f5992fe2273a72a1ee8d3a3482f68512a61974211ba32bb33f051ceb1530b8ba3527fc36224ba6b9910329025e6d9153cf50@104.211.54.233:30333".into(), - "enode://051b18f63a316c4c5fef4631f8c550ae0adba179153588406fac3e5bbbbf534ebeda1bf475dceda27a531f6cdef3846ab6a010a269aa643a1fec7bff51af66bd@104.211.48.51:30333".into(), - "enode://c831ec9011d2c02d2c4620fc88db6d897a40d2f88fd75f47b9e4cf3b243999acb6f01b7b7343474650b34eeb1363041a422a91f1fc3850e43482983ee15aa582@104.211.48.247:30333".into(), - ]; - PresetConfig { genesis_config, boot_nodes } - } - - /// PoC-2 testnet config. - fn poc_2_testnet_config() -> Self { - let initial_authorities = vec![ - hex!["82c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf5"].into(), - hex!["4de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7"].into(), - hex!["063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca5"].into(), - hex!["8101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c"].into(), - ]; - let endowed_accounts = vec![ - hex!["f295940fa750df68a686fcf4abd4111c8a9c5a5a5a83c4c8639c451a94a7adfd"].into(), - ]; - let genesis_config = Config::Local(GenesisConfig { - consensus: Some(ConsensusConfig { - code: include_bytes!("../../runtime/wasm/genesis.wasm").to_vec(), // TODO change - authorities: initial_authorities.clone(), - }), - system: None, - session: Some(SessionConfig { - validators: initial_authorities.iter().cloned().map(Into::into).collect(), - session_length: 720, // that's 1 hour per session. - }), - staking: Some(StakingConfig { - current_era: 0, - intentions: initial_authorities.iter().cloned().map(Into::into).collect(), - transaction_base_fee: 100, - transaction_byte_fee: 1, - existential_deposit: 500, - transfer_fee: 0, - creation_fee: 0, - contract_fee: 0, - reclaim_rebate: 0, - balances: endowed_accounts.iter().map(|&k|(k, 1u128 << 60)).collect(), - validator_count: 12, - sessions_per_era: 24, // 24 hours per era. - bonding_duration: 90, // 90 days per bond. - }), - democracy: Some(DemocracyConfig { - launch_period: 120 * 24 * 14, // 2 weeks per public referendum - voting_period: 120 * 24 * 28, // 4 weeks to discuss & vote on an active referendum - minimum_deposit: 1000, // 1000 as the minimum deposit for a referendum - }), - council: Some(CouncilConfig { - active_council: vec![], - candidacy_bond: 1000, // 1000 to become a council candidate - voter_bond: 100, // 100 down to vote for a candidate - present_slash_per_voter: 1, // slash by 1 per voter for an invalid presentation. - carry_count: 24, // carry over the 24 runners-up to the next council election - presentation_duration: 120 * 24, // one day for presenting winners. - approval_voting_period: 7 * 120 * 24, // one week period between possible council elections. - term_duration: 180 * 120 * 24, // 180 day term duration for the council. - desired_seats: 0, // start with no council: we'll raise this once the stake has been dispersed a bit. - inactive_grace_period: 1, // one addition vote should go by before an inactive voter can be reaped. - - cooloff_period: 90 * 120 * 24, // 90 day cooling off period if council member vetoes a proposal. - voting_period: 7 * 120 * 24, // 7 day voting period for council members. - }), - parachains: Some(Default::default()), - }); - let boot_nodes = vec![ - "enode://a93a29fa68d965452bf0ff8c1910f5992fe2273a72a1ee8d3a3482f68512a61974211ba32bb33f051ceb1530b8ba3527fc36224ba6b9910329025e6d9153cf50@104.211.54.233:30333".into(), - "enode://051b18f63a316c4c5fef4631f8c550ae0adba179153588406fac3e5bbbbf534ebeda1bf475dceda27a531f6cdef3846ab6a010a269aa643a1fec7bff51af66bd@104.211.48.51:30333".into(), - "enode://c831ec9011d2c02d2c4620fc88db6d897a40d2f88fd75f47b9e4cf3b243999acb6f01b7b7343474650b34eeb1363041a422a91f1fc3850e43482983ee15aa582@104.211.48.247:30333".into(), - ]; - PresetConfig { genesis_config, boot_nodes } - } - - fn testnet_config(initial_authorities: Vec) -> PresetConfig { - let endowed_accounts = vec![ - ed25519::Pair::from_seed(b"Alice ").public().0.into(), - ed25519::Pair::from_seed(b"Bob ").public().0.into(), - ed25519::Pair::from_seed(b"Charlie ").public().0.into(), - ed25519::Pair::from_seed(b"Dave ").public().0.into(), - ed25519::Pair::from_seed(b"Eve ").public().0.into(), - ed25519::Pair::from_seed(b"Ferdie ").public().0.into(), - ]; - let genesis_config = Config::Local(GenesisConfig { - consensus: Some(ConsensusConfig { - code: include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm").to_vec(), - authorities: initial_authorities.clone(), - }), - system: None, - session: Some(SessionConfig { - validators: initial_authorities.iter().cloned().map(Into::into).collect(), - session_length: 10, - }), - staking: Some(StakingConfig { - current_era: 0, - intentions: initial_authorities.iter().cloned().map(Into::into).collect(), - transaction_base_fee: 1, - transaction_byte_fee: 0, - existential_deposit: 500, - transfer_fee: 0, - creation_fee: 0, - contract_fee: 0, - reclaim_rebate: 0, - balances: endowed_accounts.iter().map(|&k|(k, (1u128 << 60))).collect(), - validator_count: 2, - sessions_per_era: 5, - bonding_duration: 2, - }), - democracy: Some(DemocracyConfig { - launch_period: 9, - voting_period: 18, - minimum_deposit: 10, - }), - council: Some(CouncilConfig { - active_council: endowed_accounts.iter().filter(|a| initial_authorities.iter().find(|&b| &a.0 == b).is_none()).map(|a| (a.clone(), 1000000)).collect(), - candidacy_bond: 10, - voter_bond: 2, - present_slash_per_voter: 1, - carry_count: 4, - presentation_duration: 10, - approval_voting_period: 20, - term_duration: 1000000, - desired_seats: (endowed_accounts.len() - initial_authorities.len()) as u32, - inactive_grace_period: 1, - - cooloff_period: 75, - voting_period: 20, - }), - parachains: Some(Default::default()), - }); - let boot_nodes = Vec::new(); - PresetConfig { genesis_config, boot_nodes } - } - - /// Development config (single validator Alice) - fn development_config() -> Self { - Self::testnet_config(vec![ - ed25519::Pair::from_seed(b"Alice ").public().into(), - ]) - } - - /// Local testnet config (multivalidator Alice + Bob) - fn local_testnet_config() -> Self { - Self::testnet_config(vec![ - ed25519::Pair::from_seed(b"Alice ").public().into(), - ed25519::Pair::from_seed(b"Bob ").public().into(), - ]) - } -} diff --git a/polkadot/collator/Cargo.toml b/polkadot/collator/Cargo.toml index 161121eefad0b..122261e3f65b7 100644 --- a/polkadot/collator/Cargo.toml +++ b/polkadot/collator/Cargo.toml @@ -2,12 +2,17 @@ name = "polkadot-collator" version = "0.1.0" authors = ["Parity Technologies "] -description = "Abstract collation logic" +description = "Collator node implementation" [dependencies] futures = "0.1.17" +substrate-client = { path = "../../substrate/client" } substrate-codec = { path = "../../substrate/codec", version = "0.1" } substrate-primitives = { path = "../../substrate/primitives", version = "0.1" } +polkadot-api = { path = "../api" } polkadot-runtime = { path = "../runtime", version = "0.1" } -polkadot-parachain = { path = "../parachain", version = "0.1" } polkadot-primitives = { path = "../primitives", version = "0.1" } +polkadot-cli = { path = "../cli" } +log = "0.4" +ed25519 = { path = "../../substrate/ed25519" } +tokio = "0.1.7" diff --git a/polkadot/collator/README.adoc b/polkadot/collator/README.adoc new file mode 100644 index 0000000000000..3a5408b489e02 --- /dev/null +++ b/polkadot/collator/README.adoc @@ -0,0 +1,5 @@ + += Polkadot Collator + +placeholder +//TODO Write content :) diff --git a/polkadot/collator/src/lib.rs b/polkadot/collator/src/lib.rs index 55eca734d269b..37428495d9d38 100644 --- a/polkadot/collator/src/lib.rs +++ b/polkadot/collator/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! Collation Logic. +//! Collation node logic. //! //! A collator node lives on a distinct parachain and submits a proposal for //! a state transition, along with a proof for its validity @@ -28,7 +28,7 @@ //! destination B as egress(X)[A -> B] //! //! On every block, each parachain will be intended to route messages from some -//! subset of all the other parachains. +//! subset of all the other parachains. (NOTE: in practice this is not done until PoC-3) //! //! Since the egress information is unique to every block, when routing from a //! parachain a collator must gather all egress posts from that parachain @@ -45,25 +45,46 @@ //! to be performed, as the collation logic itself. extern crate futures; +extern crate substrate_client as client; extern crate substrate_codec as codec; extern crate substrate_primitives as primitives; +extern crate ed25519; +extern crate tokio; + +extern crate polkadot_api; +extern crate polkadot_cli; extern crate polkadot_runtime; extern crate polkadot_primitives; -use std::collections::{BTreeSet, BTreeMap}; +#[macro_use] +extern crate log; + +use std::collections::{BTreeSet, BTreeMap, HashSet}; +use std::sync::Arc; +use std::time::{Duration, Instant}; + +use futures::{future, stream, Stream, Future, IntoFuture}; +use client::BlockchainEvents; +use polkadot_api::PolkadotApi; +use polkadot_primitives::{AccountId, BlockId, SessionKey}; +use polkadot_primitives::parachain::{self, BlockData, DutyRoster, HeadData, ConsolidatedIngress, Message, Id as ParaId}; +use polkadot_cli::{ServiceComponents, Service, CustomConfiguration, VersionInfo}; +use polkadot_cli::{Worker, IntoExit}; +use tokio::timer::Deadline; -use futures::{stream, Stream, Future, IntoFuture}; -use polkadot_primitives::parachain::{self, CandidateSignature, ConsolidatedIngress, Message, Id as ParaId}; +const COLLATION_TIMEOUT: Duration = Duration::from_secs(30); /// Parachain context needed for collation. /// /// This can be implemented through an externally attached service or a stub. -pub trait ParachainContext { - /// Produce a candidate, given the latest ingress queue information. +/// This is expected to be a lightweight, shared type like an Arc. +pub trait ParachainContext: Clone { + /// Produce a candidate, given the latest ingress queue information and the last parachain head. fn produce_candidate>( &self, + last_head: HeadData, ingress: I, - ) -> (parachain::BlockData, polkadot_primitives::AccountId, CandidateSignature); + ) -> (BlockData, HeadData); } /// Relay chain context needed to collate. @@ -83,9 +104,14 @@ pub trait RelayChainContext { fn unrouted_egress(&self, id: ParaId) -> Self::FutureEgress; } +fn key_to_account_id(key: &ed25519::Pair) -> AccountId { + let pubkey_bytes: [u8; 32] = key.public().into(); + pubkey_bytes.into() +} + /// Collate the necessary ingress queue using the given context. pub fn collate_ingress<'a, R>(relay_context: R) - -> Box + 'a> + -> impl Future + 'a where R: RelayChainContext, R::Error: 'a, @@ -106,7 +132,7 @@ pub fn collate_ingress<'a, R>(relay_context: R) // and then by the parachain ID. // // then transform that into the consolidated egress queue. - Box::new(stream::futures_unordered(egress_fetch) + stream::futures_unordered(egress_fetch) .fold(BTreeMap::new(), |mut map, (routing_id, egresses)| { for (depth, egress) in egresses.into_iter().rev().enumerate() { let depth = -(depth as i64); @@ -117,30 +143,200 @@ pub fn collate_ingress<'a, R>(relay_context: R) }) .map(|ordered| ordered.into_iter().map(|((_, id), egress)| (id, egress))) .map(|i| i.collect::>()) - .map(ConsolidatedIngress)) + .map(ConsolidatedIngress) } -/// Produce a candidate for the parachain. -pub fn collate<'a, R, P>(local_id: ParaId, relay_context: R, para_context: P) - -> Box + 'a> +/// Produce a candidate for the parachain, with given contexts, parent head, and signing key. +pub fn collate<'a, R, P>( + local_id: ParaId, + last_head: HeadData, + relay_context: R, + para_context: P, + key: Arc, +) + -> impl Future + 'a where - R: RelayChainContext, - R::Error: 'a, + R: RelayChainContext + 'a, + R::Error: 'a, R::FutureEgress: 'a, P: ParachainContext + 'a, { - Box::new(collate_ingress(relay_context).map(move |ingress| { - let (block_data, _, signature) = para_context.produce_candidate( + collate_ingress(relay_context).map(move |ingress| { + let (block_data, head_data) = para_context.produce_candidate( + last_head, ingress.0.iter().flat_map(|&(id, ref msgs)| msgs.iter().cloned().map(move |msg| (id, msg))) ); - parachain::Candidate { + let block_data_hash = block_data.hash(); + let signature = key.sign(&block_data_hash.0[..]).into(); + + let receipt = parachain::CandidateReceipt { parachain_index: local_id, - collator_signature: signature, - block: block_data, - unprocessed_ingress: ingress, + collator: key_to_account_id(&*key), + signature, + head_data, + balance_uploads: Vec::new(), + egress_queue_roots: Vec::new(), + fees: 0, + block_data_hash, + }; + + parachain::Collation { + receipt, + block_data, } - })) + }) +} + +/// Polkadot-api context. +struct ApiContext; + +impl RelayChainContext for ApiContext { + type Error = ::polkadot_api::Error; + type FutureEgress = Result>, Self::Error>; + + fn routing_parachains(&self) -> BTreeSet { + BTreeSet::new() + } + + fn unrouted_egress(&self, _id: ParaId) -> Self::FutureEgress { + Ok(Vec::new()) + } +} + +struct CollationNode { + parachain_context: P, + exit: E, + para_id: ParaId, + key: Arc, +} + +impl IntoExit for CollationNode where + P: ParachainContext + Send + 'static, + E: Future + Send + 'static +{ + type Exit = E; + fn into_exit(self) -> Self::Exit { + self.exit + } +} + +impl Worker for CollationNode where + P: ParachainContext + Send + 'static, + E: Future + Send + 'static +{ + type Work = Box + Send>; + + fn configuration(&self) -> CustomConfiguration { + let mut config = CustomConfiguration::default(); + config.collating_for = Some(( + key_to_account_id(&*self.key), + self.para_id.clone(), + )); + config + } + + fn work(self, service: &Service) -> Self::Work { + let CollationNode { parachain_context, exit, para_id, key } = self; + let client = service.client(); + let api = service.api(); + let network = service.network(); + + let work = client.import_notification_stream() + .for_each(move |notification| { + macro_rules! try_fr { + ($e:expr) => { + match $e { + Ok(x) => x, + Err(e) => return future::Either::A(future::err(e)), + } + } + } + + let relay_parent = notification.hash; + let id = BlockId::hash(relay_parent); + + let network = network.clone(); + let api = api.clone(); + let key = key.clone(); + let parachain_context = parachain_context.clone(); + + let work = future::lazy(move || { + let last_head = match try_fr!(api.parachain_head(&id, para_id)) { + Some(last_head) => last_head, + None => return future::Either::A(future::ok(())), + }; + + let targets = compute_targets( + para_id, + try_fr!(api.session_keys(&id)).as_slice(), + try_fr!(api.duty_roster(&id)), + ); + + let collation_work = collate( + para_id, + HeadData(last_head), + ApiContext, + parachain_context, + key, + ).map(move |collation| { + network.with_spec(|spec, ctx| spec.add_local_collation( + ctx, + relay_parent, + targets, + collation, + )); + }); + + future::Either::B(collation_work) + }); + let deadlined = Deadline::new(work, Instant::now() + COLLATION_TIMEOUT); + let silenced = deadlined.then(|res| match res { + Ok(()) => Ok(()), + Err(e) => { + warn!("Collation failure: {}", e); + Ok(()) + } + }); + + tokio::spawn(silenced); + Ok(()) + }); + + let work_and_exit = work.select(exit).then(|_| Ok(())); + Box::new(work_and_exit) as Box<_> + } +} + +fn compute_targets(para_id: ParaId, session_keys: &[SessionKey], roster: DutyRoster) -> HashSet { + use polkadot_primitives::parachain::Chain; + + roster.validator_duty.iter().enumerate() + .filter(|&(_, c)| c == &Chain::Parachain(para_id)) + .filter_map(|(i, _)| session_keys.get(i)) + .cloned() + .collect() +} + +/// Run a collator node with the given `RelayChainContext` and `ParachainContext` and +/// arguments to the underlying polkadot node. +/// +/// Provide a future which resolves when the node should exit. +/// This function blocks until done. +pub fn run_collator( + parachain_context: P, + para_id: ParaId, + exit: E, + key: Arc, + args: Vec<::std::ffi::OsString>, + version: VersionInfo, +) -> polkadot_cli::error::Result<()> where + P: ParachainContext + Send + 'static, + E: IntoFuture, + E::Future: Send + Clone + 'static, +{ + let node_logic = CollationNode { parachain_context, exit: exit.into_future(), para_id, key }; + polkadot_cli::run(args, node_logic, version) } #[cfg(test)] @@ -170,7 +366,7 @@ mod tests { } } - #[test] + #[test] fn collates_ingress() { let route_from = |x: &[ParaId]| { let mut set = BTreeSet::new(); diff --git a/polkadot/consensus/Cargo.toml b/polkadot/consensus/Cargo.toml index 9941a21b33a7a..68ad8265518e4 100644 --- a/polkadot/consensus/Cargo.toml +++ b/polkadot/consensus/Cargo.toml @@ -6,13 +6,13 @@ authors = ["Parity Technologies "] [dependencies] futures = "0.1.17" parking_lot = "0.4" -tokio-core = "0.1.12" +tokio = "0.1.7" ed25519 = { path = "../../substrate/ed25519" } -error-chain = "0.11" +error-chain = "0.12" log = "0.3" exit-future = "0.1" +rhododendron = "0.2" polkadot-api = { path = "../api" } -polkadot-collator = { path = "../collator" } polkadot-parachain = { path = "../parachain" } polkadot-primitives = { path = "../primitives" } polkadot-runtime = { path = "../runtime" } @@ -22,7 +22,8 @@ substrate-bft = { path = "../../substrate/bft" } substrate-codec = { path = "../../substrate/codec" } substrate-primitives = { path = "../../substrate/primitives" } substrate-runtime-support = { path = "../../substrate/runtime-support" } -substrate-network = { path = "../../substrate/network" } -substrate-keyring = { path = "../../substrate/keyring" } substrate-client = { path = "../../substrate/client" } substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" } + +[dev-dependencies] +substrate-keyring = { path = "../../substrate/keyring" } diff --git a/polkadot/consensus/README.adoc b/polkadot/consensus/README.adoc new file mode 100644 index 0000000000000..a3ac5f631c38c --- /dev/null +++ b/polkadot/consensus/README.adoc @@ -0,0 +1,5 @@ + += Polkadot Consensus + +placeholder +//TODO Write content :) diff --git a/polkadot/consensus/src/collation.rs b/polkadot/consensus/src/collation.rs index 3738ae900413a..f7db48db619bb 100644 --- a/polkadot/consensus/src/collation.rs +++ b/polkadot/consensus/src/collation.rs @@ -22,19 +22,11 @@ use std::sync::Arc; use polkadot_api::PolkadotApi; -use polkadot_primitives::{Hash, AccountId}; -use polkadot_primitives::parachain::{Id as ParaId, Chain, BlockData, Extrinsic, CandidateReceipt}; +use polkadot_primitives::{Hash, AccountId, BlockId}; +use polkadot_primitives::parachain::{Id as ParaId, Collation, Extrinsic}; use futures::prelude::*; -/// A full collation. -pub struct Collation { - /// Block data. - pub block_data: BlockData, - /// The candidate receipt itself. - pub receipt: CandidateReceipt, -} - /// Encapsulates connections to collators and allows collation on any parachain. /// /// This is expected to be a lightweight, shared type like an `Arc`. @@ -45,6 +37,12 @@ pub trait Collators: Clone { type Collation: IntoFuture; /// Collate on a specific parachain, building on a given relay chain parent hash. + /// + /// The returned collation should be checked for basic validity in the signature + /// and will be checked for state-transition validity by the consumer of this trait. + /// + /// This does not have to guarantee local availability, as a valid collation + /// will be passed to the `TableRouter` instance. fn collate(&self, parachain: ParaId, relay_parent: Hash) -> Self::Collation; /// Note a bad collator. TODO: take proof @@ -55,9 +53,9 @@ pub trait Collators: Clone { /// /// This future is fused. pub struct CollationFetch { - parachain: Option, + parachain: ParaId, relay_parent_hash: Hash, - relay_parent: P::CheckedBlockId, + relay_parent: BlockId, collators: C, live_fetch: Option<::Future>, client: Arc

, @@ -65,16 +63,13 @@ pub struct CollationFetch { impl CollationFetch { /// Create a new collation fetcher for the given chain. - pub fn new(parachain: Chain, relay_parent: P::CheckedBlockId, relay_parent_hash: Hash, collators: C, client: Arc

) -> Self { + pub fn new(parachain: ParaId, relay_parent: BlockId, relay_parent_hash: Hash, collators: C, client: Arc

) -> Self { CollationFetch { relay_parent_hash, relay_parent, collators, client, - parachain: match parachain { - Chain::Parachain(id) => Some(id), - Chain::Relay => None, - }, + parachain, live_fetch: None, } } @@ -85,26 +80,19 @@ impl Future for CollationFetch { type Error = C::Error; fn poll(&mut self) -> Poll<(Collation, Extrinsic), C::Error> { - let parachain = match self.parachain.as_ref() { - Some(p) => p.clone(), - None => return Ok(Async::NotReady), - }; - loop { let x = { + let parachain = self.parachain.clone(); let (r, c) = (self.relay_parent_hash, &self.collators); let poll = self.live_fetch .get_or_insert_with(move || c.collate(parachain, r).into_future()) .poll(); - if let Err(_) = poll { self.parachain = None } try_ready!(poll) }; match validate_collation(&*self.client, &self.relay_parent, &x) { Ok(()) => { - self.parachain = None; - // TODO: generate extrinsic while verifying. return Ok(Async::Ready((x, Extrinsic))); } @@ -145,7 +133,7 @@ error_chain! { } /// Check whether a given collation is valid. Returns `Ok` on success, error otherwise. -pub fn validate_collation(client: &P, relay_parent: &P::CheckedBlockId, collation: &Collation) -> Result<(), Error> { +pub fn validate_collation(client: &P, relay_parent: &BlockId, collation: &Collation) -> Result<(), Error> { use parachain::{self, ValidationParams}; let para_id = collation.receipt.parachain_index; diff --git a/polkadot/consensus/src/dynamic_inclusion.rs b/polkadot/consensus/src/dynamic_inclusion.rs index d48e486274598..bec2bd0fa80e3 100644 --- a/polkadot/consensus/src/dynamic_inclusion.rs +++ b/polkadot/consensus/src/dynamic_inclusion.rs @@ -61,7 +61,7 @@ impl DynamicInclusion { /// would be enough, or `None` if it is sufficient now. /// /// Panics if `now` is earlier than the `start`. - pub fn acceptable_in(&self, now: Instant, included: usize) -> Option { + pub fn acceptable_in(&self, now: Instant, included: usize) -> Option { let elapsed = now.duration_since(self.start); let elapsed = duration_to_micros(&elapsed); @@ -70,7 +70,8 @@ impl DynamicInclusion { if elapsed >= valid_after { None } else { - Some(Duration::from_millis((valid_after - elapsed) as u64 / 1000)) + let until = Duration::from_millis((valid_after - elapsed) as u64 / 1000); + Some(now + until) } } } @@ -104,7 +105,7 @@ mod tests { Duration::from_millis(4000), ); - assert_eq!(dynamic.acceptable_in(now, 5), Some(Duration::from_millis(2000))); + assert_eq!(dynamic.acceptable_in(now, 5), Some(now + Duration::from_millis(2000))); assert!(dynamic.acceptable_in(now + Duration::from_millis(2000), 5).is_none()); assert!(dynamic.acceptable_in(now + Duration::from_millis(3000), 5).is_none()); assert!(dynamic.acceptable_in(now + Duration::from_millis(4000), 5).is_none()); diff --git a/polkadot/consensus/src/error.rs b/polkadot/consensus/src/error.rs index acafa88f5e426..397fdee52ce9c 100644 --- a/polkadot/consensus/src/error.rs +++ b/polkadot/consensus/src/error.rs @@ -37,7 +37,7 @@ error_chain! { description("Proposer destroyed before finishing proposing or evaluating"), display("Proposer destroyed before finishing proposing or evaluating"), } - Timer(e: String) { + Timer(e: ::tokio::timer::Error) { description("Failed to register or resolve async timer."), display("Timer failed: {}", e), } diff --git a/polkadot/consensus/src/evaluation.rs b/polkadot/consensus/src/evaluation.rs index c7c4fe2c25dcc..d843e79de471e 100644 --- a/polkadot/consensus/src/evaluation.rs +++ b/polkadot/consensus/src/evaluation.rs @@ -18,7 +18,7 @@ use super::MAX_TRANSACTIONS_SIZE; -use codec::Slicable; +use codec::{Decode, Encode}; use polkadot_runtime::{Block as PolkadotGenericBlock, CheckedBlock}; use polkadot_primitives::{Block, Hash, BlockNumber, Timestamp}; use polkadot_primitives::parachain::Id as ParaId; @@ -78,13 +78,13 @@ pub fn evaluate_initial( ) -> Result { const MAX_TIMESTAMP_DRIFT: Timestamp = 60; - let encoded = Slicable::encode(proposal); + let encoded = Encode::encode(proposal); let proposal = PolkadotGenericBlock::decode(&mut &encoded[..]) .and_then(|b| CheckedBlock::new(b).ok()) .ok_or_else(|| ErrorKind::ProposalNotForPolkadot)?; let transactions_size = proposal.extrinsics.iter().fold(0, |a, tx| { - a + Slicable::encode(tx).len() + a + Encode::encode(tx).len() }); if transactions_size > MAX_TRANSACTIONS_SIZE { diff --git a/polkadot/consensus/src/lib.rs b/polkadot/consensus/src/lib.rs index 6146e6d87da90..4aee785def5b2 100644 --- a/polkadot/consensus/src/lib.rs +++ b/polkadot/consensus/src/lib.rs @@ -32,7 +32,6 @@ extern crate ed25519; extern crate parking_lot; extern crate polkadot_api; -extern crate polkadot_collator as collator; extern crate polkadot_statement_table as table; extern crate polkadot_parachain as parachain; extern crate polkadot_transaction_pool as transaction_pool; @@ -44,11 +43,11 @@ extern crate substrate_codec as codec; extern crate substrate_primitives as primitives; extern crate substrate_runtime_support as runtime_support; extern crate substrate_runtime_primitives as runtime_primitives; -extern crate substrate_network; +extern crate substrate_client as client; extern crate exit_future; -extern crate tokio_core; -extern crate substrate_client as client; +extern crate tokio; +extern crate rhododendron; #[macro_use] extern crate error_chain; @@ -66,34 +65,33 @@ use std::collections::{HashMap, HashSet}; use std::sync::Arc; use std::time::{Duration, Instant}; -use codec::Slicable; -use table::generic::Statement as GenericStatement; -use runtime_support::Hashable; +use codec::{Decode, Encode}; use polkadot_api::PolkadotApi; -use polkadot_primitives::{Hash, Block, BlockId, BlockNumber, Header, Timestamp}; -use polkadot_primitives::parachain::{Id as ParaId, Chain, DutyRoster, BlockData, Extrinsic as ParachainExtrinsic, CandidateReceipt}; -use polkadot_runtime::BareExtrinsic; +use polkadot_primitives::{Hash, Block, BlockId, BlockNumber, Header, Timestamp, SessionKey}; +use polkadot_primitives::parachain::{Id as ParaId, Chain, DutyRoster, BlockData, Extrinsic as ParachainExtrinsic, CandidateReceipt, CandidateSignature}; use primitives::AuthorityId; -use transaction_pool::{Ready, TransactionPool}; -use tokio_core::reactor::{Handle, Timeout, Interval}; +use transaction_pool::TransactionPool; +use tokio::runtime::TaskExecutor; +use tokio::timer::{Delay, Interval}; use futures::prelude::*; -use futures::future::{self, Shared}; +use futures::future; use collation::CollationFetch; use dynamic_inclusion::DynamicInclusion; -pub use self::collation::{Collators, Collation}; +pub use self::collation::{validate_collation, Collators}; pub use self::error::{ErrorKind, Error}; -pub use self::shared_table::{SharedTable, StatementSource, StatementProducer, ProducedStatements}; +pub use self::shared_table::{SharedTable, StatementProducer, ProducedStatements, Statement, SignedStatement, GenericStatement}; pub use service::Service; -mod collation; mod dynamic_inclusion; mod evaluation; mod error; mod service; mod shared_table; +pub mod collation; + // block size limit. const MAX_TRANSACTIONS_SIZE: usize = 4 * 1024 * 1024; @@ -108,8 +106,9 @@ pub trait TableRouter: Clone { /// Future that resolves when extrinsic candidate data is fetched. type FetchExtrinsic: IntoFuture; - /// Note local candidate data, making it available on the network to other validators. - fn local_candidate_data(&self, hash: Hash, block_data: BlockData, extrinsic: ParachainExtrinsic); + /// Call with local candidate data. This will make the data available on the network, + /// and sign, import, and broadcast a statement about the candidate. + fn local_candidate(&self, candidate: CandidateReceipt, block_data: BlockData, extrinsic: ParachainExtrinsic); /// Fetch block data for a specific candidate. fn fetch_block_data(&self, candidate: &CandidateReceipt) -> Self::FetchCandidate; @@ -118,23 +117,28 @@ pub trait TableRouter: Clone { fn fetch_extrinsic_data(&self, candidate: &CandidateReceipt) -> Self::FetchExtrinsic; } -/// A long-lived network which can create statement table routing instances. +/// A long-lived network which can create parachain statement and BFT message routing processes on demand. pub trait Network { /// The table router type. This should handle importing of any statements, /// routing statements to peers, and driving completion of any `StatementProducers`. type TableRouter: TableRouter; - - /// Instantiate a table router using the given shared table. - fn table_router(&self, table: Arc) -> Self::TableRouter; + /// The input stream of BFT messages. Should never logically conclude. + type Input: Stream,Error=Error>; + /// The output sink of BFT messages. Messages sent here should eventually pass to all + /// current authorities. + type Output: Sink,SinkError=Error>; + + /// Instantiate a table router using the given shared table and task executor. + fn communication_for(&self, validators: &[SessionKey], table: Arc, task_executor: TaskExecutor) -> (Self::TableRouter, Self::Input, Self::Output); } /// Information about a specific group. #[derive(Debug, Clone, Default)] pub struct GroupInfo { /// Authorities meant to check validity of candidates. - pub validity_guarantors: HashSet, + pub validity_guarantors: HashSet, /// Authorities meant to check availability of candidate data. - pub availability_guarantors: HashSet, + pub availability_guarantors: HashSet, /// Number of votes needed for validity. pub needed_validity: usize, /// Number of votes needed for availability. @@ -144,20 +148,21 @@ pub struct GroupInfo { /// Sign a table statement against a parent hash. /// The actual message signed is the encoded statement concatenated with the /// parent hash. -pub fn sign_table_statement(statement: &table::Statement, key: &ed25519::Pair, parent_hash: &Hash) -> ed25519::Signature { - use polkadot_primitives::parachain::Statement as RawStatement; +pub fn sign_table_statement(statement: &Statement, key: &ed25519::Pair, parent_hash: &Hash) -> CandidateSignature { + let mut encoded = statement.encode(); + encoded.extend(&parent_hash.0); + + key.sign(&encoded).into() +} - let raw = match *statement { - GenericStatement::Candidate(ref c) => RawStatement::Candidate(c.clone()), - GenericStatement::Valid(h) => RawStatement::Valid(h), - GenericStatement::Invalid(h) => RawStatement::Invalid(h), - GenericStatement::Available(h) => RawStatement::Available(h), - }; +/// Check signature on table statement. +pub fn check_statement(statement: &Statement, signature: &CandidateSignature, signer: SessionKey, parent_hash: &Hash) -> bool { + use runtime_primitives::traits::Verify; - let mut encoded = raw.encode(); + let mut encoded = statement.encode(); encoded.extend(&parent_hash.0); - key.sign(&encoded) + signature.verify(&encoded[..], &signer.into()) } fn make_group_info(roster: DutyRoster, authorities: &[AuthorityId], local_id: AuthorityId) -> Result<(HashMap, LocalDuty), Error> { @@ -217,120 +222,171 @@ fn make_group_info(roster: DutyRoster, authorities: &[AuthorityId], local_id: Au } } -fn timer_error(e: &::std::io::Error) -> Error { - ErrorKind::Timer(format!("{}", e)).into() -} - /// Polkadot proposer factory. pub struct ProposerFactory { /// The client instance. - pub client: Arc, + pub client: Arc

, /// The transaction pool. - pub transaction_pool: Arc, + pub transaction_pool: Arc>, /// The backing network handle. pub network: N, /// Parachain collators. - pub collators: P, - /// The timer used to schedule proposal intervals. - pub handle: Handle, + pub collators: C, + /// handle to remote task executor + pub handle: TaskExecutor, /// The duration after which parachain-empty blocks will be allowed. pub parachain_empty_duration: Duration, } -impl bft::ProposerFactory for ProposerFactory +impl bft::Environment for ProposerFactory where - C: PolkadotApi, + C: Collators + Send + 'static, N: Network, - P: Collators, + P: PolkadotApi + Send + Sync + 'static, + ::Future: Send + 'static, + N::TableRouter: Send + 'static, { - type Proposer = Proposer; + type Proposer = Proposer

; + type Input = N::Input; + type Output = N::Output; type Error = Error; - fn init(&self, parent_header: &Header, authorities: &[AuthorityId], sign_with: Arc) -> Result { - use std::time::Duration; + fn init(&self, + parent_header: &Header, + authorities: &[AuthorityId], + sign_with: Arc + ) -> Result<(Self::Proposer, Self::Input, Self::Output), Error> { + use runtime_primitives::traits::{Hash as HashT, BlakeTwo256}; const DELAY_UNTIL: Duration = Duration::from_millis(5000); - let parent_hash = parent_header.blake2_256().into(); + let parent_hash = parent_header.hash().into(); - let checked_id = self.client.check_id(BlockId::hash(parent_hash))?; - let duty_roster = self.client.duty_roster(&checked_id)?; - let random_seed = self.client.random_seed(&checked_id)?; + let id = BlockId::hash(parent_hash); + let duty_roster = self.client.duty_roster(&id)?; + let random_seed = self.client.random_seed(&id)?; + let random_seed = BlakeTwo256::hash(&*random_seed); let (group_info, local_duty) = make_group_info( duty_roster, authorities, - sign_with.public().0, + sign_with.public().into(), )?; - let active_parachains = self.client.active_parachains(&checked_id)?; + let active_parachains = self.client.active_parachains(&id)?; let n_parachains = active_parachains.len(); let table = Arc::new(SharedTable::new(group_info, sign_with.clone(), parent_hash)); - let router = self.network.table_router(table.clone()); + let (router, input, output) = self.network.communication_for( + authorities, + table.clone(), + self.handle.clone() + ); + + let now = Instant::now(); let dynamic_inclusion = DynamicInclusion::new( n_parachains, - Instant::now(), + now, self.parachain_empty_duration.clone(), ); - let timeout = Timeout::new(DELAY_UNTIL, &self.handle) - .map_err(|e| timer_error(&e))?; - debug!(target: "bft", "Initialising consensus proposer. Refusing to evaluate for {:?} from now.", DELAY_UNTIL); - // TODO [PoC-2]: kick off collation process. - Ok(Proposer { + let validation_para = match local_duty.validation { + Chain::Relay => None, + Chain::Parachain(id) => Some(id), + }; + + let collation_work = validation_para.map(|para| CollationFetch::new( + para, + id.clone(), + parent_hash.clone(), + self.collators.clone(), + self.client.clone(), + )); + let drop_signal = dispatch_collation_work( + router.clone(), + &self.handle, + collation_work, + ); + + let proposer = Proposer { client: self.client.clone(), - collators: self.collators.clone(), - delay: timeout.shared(), - handle: self.handle.clone(), dynamic_inclusion, - local_duty, local_key: sign_with, + minimum_delay: now + DELAY_UNTIL, parent_hash, - parent_id: checked_id, + parent_id: id, parent_number: parent_header.number, random_seed, - router, table, transaction_pool: self.transaction_pool.clone(), - }) + _drop_signal: drop_signal, + }; + + Ok((proposer, input, output)) } } +// dispatch collation work to be done in the background. returns a signal object +// that should fire when the collation work is no longer necessary (e.g. when the proposer object is dropped) +fn dispatch_collation_work( + router: R, + handle: &TaskExecutor, + work: Option>, +) -> exit_future::Signal where + C: Collators + Send + 'static, + P: PolkadotApi + Send + Sync + 'static, + ::Future: Send + 'static, + R: TableRouter + Send + 'static, +{ + let (signal, exit) = exit_future::signal(); + let handled_work = work.then(move |result| match result { + Ok(Some((collation, extrinsic))) => { + router.local_candidate(collation.receipt, collation.block_data, extrinsic); + Ok(()) + } + Ok(None) => Ok(()), + Err(_e) => { + warn!(target: "consensus", "Failed to collate candidate"); + Ok(()) + } + }); + + let cancellable_work = handled_work.select(exit).then(|_| Ok(())); + + // spawn onto thread pool. + handle.spawn(cancellable_work); + signal +} + struct LocalDuty { validation: Chain, } /// The Polkadot proposer logic. -pub struct Proposer { +pub struct Proposer { client: Arc, - collators: P, - delay: Shared, dynamic_inclusion: DynamicInclusion, - handle: Handle, - local_duty: LocalDuty, local_key: Arc, + minimum_delay: Instant, parent_hash: Hash, - parent_id: C::CheckedBlockId, + parent_id: BlockId, parent_number: BlockNumber, random_seed: Hash, - router: R, table: Arc, - transaction_pool: Arc, + transaction_pool: Arc>, + _drop_signal: exit_future::Signal, } -impl bft::Proposer for Proposer +impl bft::Proposer for Proposer where - C: PolkadotApi, - R: TableRouter, - P: Collators, + C: PolkadotApi + Send + Sync, { type Error = Error; type Create = future::Either< - CreateProposal, + CreateProposal, future::FutureResult, >; type Evaluate = Box>; @@ -339,32 +395,24 @@ impl bft::Proposer for Proposer const ATTEMPT_PROPOSE_EVERY: Duration = Duration::from_millis(100); let initial_included = self.table.includable_count(); + let now = Instant::now(); let enough_candidates = self.dynamic_inclusion.acceptable_in( - Instant::now(), + now, initial_included, - ).unwrap_or_default(); - - let timing = { - let delay = self.delay.clone(); - let dynamic_inclusion = self.dynamic_inclusion.clone(); - let make_timing = move |handle| -> Result { - let attempt_propose = Interval::new(ATTEMPT_PROPOSE_EVERY, handle)?; - let enough_candidates = Timeout::new(enough_candidates, handle)?; - Ok(ProposalTiming { - attempt_propose, - enough_candidates, - dynamic_inclusion, - minimum_delay: Some(delay), - last_included: initial_included, - }) - }; + ).unwrap_or_else(|| now + Duration::from_millis(1)); - match make_timing(&self.handle) { - Ok(timing) => timing, - Err(e) => { - return future::Either::B(future::err(timer_error(&e))); - } - } + let minimum_delay = if self.minimum_delay > now + ATTEMPT_PROPOSE_EVERY { + Some(Delay::new(self.minimum_delay)) + } else { + None + }; + + let timing = ProposalTiming { + attempt_propose: Interval::new(now + ATTEMPT_PROPOSE_EVERY, ATTEMPT_PROPOSE_EVERY), + enough_candidates: Delay::new(enough_candidates), + dynamic_inclusion: self.dynamic_inclusion.clone(), + minimum_delay, + last_included: initial_included, }; future::Either::A(CreateProposal { @@ -373,15 +421,7 @@ impl bft::Proposer for Proposer parent_id: self.parent_id.clone(), client: self.client.clone(), transaction_pool: self.transaction_pool.clone(), - collation: CollationFetch::new( - self.local_duty.validation, - self.parent_id.clone(), - self.parent_hash.clone(), - self.collators.clone(), - self.client.clone() - ), table: self.table.clone(), - router: self.router.clone(), timing, }) } @@ -415,9 +455,7 @@ impl bft::Proposer for Proposer }; let vote_delays = { - // delay casting vote until able (according to minimum block time) - let minimum_delay = self.delay.clone() - .map_err(|e| timer_error(&*e)); + let now = Instant::now(); let included_candidate_hashes = proposal .parachain_heads() @@ -431,33 +469,35 @@ impl bft::Proposer for Proposer // the duration at which the given number of parachains is acceptable. let count_delay = self.dynamic_inclusion.acceptable_in( - Instant::now(), + now, proposal.parachain_heads().len(), ); // the duration until the given timestamp is current let proposed_timestamp = proposal.timestamp(); let timestamp_delay = if proposed_timestamp > current_timestamp { - Some(Duration::from_secs(proposed_timestamp - current_timestamp)) + Some(now + Duration::from_secs(proposed_timestamp - current_timestamp)) } else { None }; + // delay casting vote until able according to minimum block time, + // timestamp delay, and count delay. // construct a future from the maximum of the two durations. - let temporary_delay = match ::std::cmp::max(timestamp_delay, count_delay) { - Some(duration) => { - let maybe_timeout = Timeout::new(duration, &self.handle); - - let f = future::result(maybe_timeout) - .and_then(|timeout| timeout) - .map_err(|e| timer_error(&e)); - - future::Either::A(f) - } + let max_delay = [timestamp_delay, count_delay, Some(self.minimum_delay)] + .iter() + .cloned() + .max() + .expect("iterator not empty; thus max returns `Some`; qed"); + + let temporary_delay = match max_delay { + Some(duration) => future::Either::A( + Delay::new(duration).map_err(|e| Error::from(ErrorKind::Timer(e))) + ), None => future::Either::B(future::ok(())), }; - minimum_delay.join3(includability_tracker, temporary_delay) + includability_tracker.join(temporary_delay) }; // evaluate whether the block is actually valid. @@ -488,21 +528,20 @@ impl bft::Proposer for Proposer let offset = offset.low_u64() as usize + round_number; let proposer = authorities[offset % authorities.len()].clone(); - trace!(target: "bft", "proposer for round {} is {}", round_number, Hash::from(proposer)); + trace!(target: "bft", "proposer for round {} is {}", round_number, proposer); proposer } fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, bft::Misbehavior)>) { - use bft::generic::Misbehavior as GenericMisbehavior; + use rhododendron::Misbehavior as GenericMisbehavior; use runtime_primitives::bft::{MisbehaviorKind, MisbehaviorReport}; use runtime_primitives::MaybeUnsigned; - use polkadot_runtime::{Call, Extrinsic, UncheckedExtrinsic, ConsensusCall}; + use polkadot_runtime::{Call, Extrinsic, BareExtrinsic, UncheckedExtrinsic, ConsensusCall}; let local_id = self.local_key.public().0.into(); let mut next_index = { - let readiness_evaluator = Ready::create(self.parent_id.clone(), &*self.client); - let cur_index = self.transaction_pool.cull_and_get_pending(readiness_evaluator, |pending| pending + let cur_index = self.transaction_pool.cull_and_get_pending(BlockId::hash(self.parent_hash), |pending| pending .filter(|tx| tx.sender().map(|s| s == local_id).unwrap_or(false)) .last() .map(|tx| Ok(tx.index())) @@ -510,7 +549,11 @@ impl bft::Proposer for Proposer ); match cur_index { - Ok(cur_index) => cur_index + 1, + Ok(Ok(cur_index)) => cur_index + 1, + Ok(Err(e)) => { + warn!(target: "consensus", "Error computing next transaction index: {}", e); + return; + } Err(e) => { warn!(target: "consensus", "Error computing next transaction index: {}", e); return; @@ -549,7 +592,7 @@ impl bft::Proposer for Proposer }; let uxt = UncheckedExtrinsic::new(extrinsic, signature); - self.transaction_pool.import_unchecked_extrinsic(uxt) + self.transaction_pool.import_unchecked_extrinsic(BlockId::hash(self.parent_hash), uxt) .expect("locally signed extrinsic is valid; qed"); } } @@ -566,83 +609,70 @@ fn current_timestamp() -> Timestamp { struct ProposalTiming { attempt_propose: Interval, dynamic_inclusion: DynamicInclusion, - enough_candidates: Timeout, - minimum_delay: Option>, + enough_candidates: Delay, + minimum_delay: Option, last_included: usize, } impl ProposalTiming { // whether it's time to attempt a proposal. // shouldn't be called outside of the context of a task. - fn poll(&mut self, included: usize) -> Poll<(), Error> { + fn poll(&mut self, included: usize) -> Poll<(), ErrorKind> { // first drain from the interval so when the minimum delay is up // we don't have any notifications built up. // // this interval is just meant to produce periodic task wakeups // that lead to the `dynamic_inclusion` getting updated as necessary. - if let Async::Ready(x) = self.attempt_propose.poll() - .map_err(|e| timer_error(&e))? - { + if let Async::Ready(x) = self.attempt_propose.poll().map_err(ErrorKind::Timer)? { x.expect("timer still alive; intervals never end; qed"); } if let Some(ref mut min) = self.minimum_delay { - try_ready!(min.poll().map_err(|e| timer_error(&*e))); + try_ready!(min.poll().map_err(ErrorKind::Timer)); } self.minimum_delay = None; // after this point, the future must have completed. if included == self.last_included { - return self.enough_candidates.poll().map_err(|e| timer_error(&e)); + return self.enough_candidates.poll().map_err(ErrorKind::Timer); } // the amount of includable candidates has changed. schedule a wakeup // if it's not sufficient anymore. - let now = Instant::now(); - match self.dynamic_inclusion.acceptable_in(now, included) { - Some(duration) => { + match self.dynamic_inclusion.acceptable_in(Instant::now(), included) { + Some(instant) => { self.last_included = included; - self.enough_candidates.reset(now + duration); - self.enough_candidates.poll().map_err(|e| timer_error(&e)) - } - None => { - Ok(Async::Ready(())) + self.enough_candidates.reset(instant); + self.enough_candidates.poll().map_err(ErrorKind::Timer) } + None => Ok(Async::Ready(())), } } } /// Future which resolves upon the creation of a proposal. -pub struct CreateProposal { +pub struct CreateProposal { parent_hash: Hash, parent_number: BlockNumber, - parent_id: C::CheckedBlockId, + parent_id: BlockId, client: Arc, - transaction_pool: Arc, - collation: CollationFetch, - router: R, + transaction_pool: Arc>, table: Arc, timing: ProposalTiming, } -impl CreateProposal - where - C: PolkadotApi, - R: TableRouter, - P: Collators, -{ +impl CreateProposal where C: PolkadotApi { fn propose_with(&self, candidates: Vec) -> Result { use polkadot_api::BlockBuilder; - use runtime_primitives::traits::{Hashing, BlakeTwo256}; + use runtime_primitives::traits::{Hash as HashT, BlakeTwo256}; // TODO: handle case when current timestamp behind that in state. let timestamp = current_timestamp(); let mut block_builder = self.client.build_block(&self.parent_id, timestamp, candidates)?; { - let readiness_evaluator = Ready::create(self.parent_id.clone(), &*self.client); let mut unqueue_invalid = Vec::new(); - self.transaction_pool.cull_and_get_pending(readiness_evaluator, |pending_iterator| { + let result = self.transaction_pool.cull_and_get_pending(BlockId::hash(self.parent_hash), |pending_iterator| { let mut pending_size = 0; for pending in pending_iterator { // skip and cull transactions which are too large. @@ -664,6 +694,9 @@ impl CreateProposal } } }); + if let Err(e) = result { + warn!("Unable to get the pending set: {:?}", e); + } self.transaction_pool.remove(&unqueue_invalid, false); } @@ -680,7 +713,7 @@ impl CreateProposal .join(", ") ); - let substrate_block = Slicable::decode(&mut polkadot_block.encode().as_slice()) + let substrate_block = Decode::decode(&mut polkadot_block.encode().as_slice()) .expect("polkadot blocks defined to serialize to substrate blocks correctly; qed"); // TODO: full re-evaluation @@ -697,35 +730,17 @@ impl CreateProposal } } -impl Future for CreateProposal - where - C: PolkadotApi, - R: TableRouter, - P: Collators, -{ +impl Future for CreateProposal where C: PolkadotApi { type Item = Block; type Error = Error; fn poll(&mut self) -> Poll { - // 1. poll local collation future. - match self.collation.poll() { - Ok(Async::Ready((collation, extrinsic))) => { - let hash = collation.receipt.hash(); - self.router.local_candidate_data(hash, collation.block_data, extrinsic); - - // TODO: if we are an availability guarantor also, we should produce an availability statement. - self.table.sign_and_import(&self.router, GenericStatement::Candidate(collation.receipt)); - } - Ok(Async::NotReady) => {}, - Err(_) => {}, // TODO: handle this failure to collate. - } - - // 2. try to propose if we have enough includable candidates and other + // 1. try to propose if we have enough includable candidates and other // delays have concluded. let included = self.table.includable_count(); try_ready!(self.timing.poll(included)); - // 3. propose + // 2. propose let proposed_candidates = self.table.with_proposal(|proposed_set| { proposed_set.into_iter().cloned().collect() }); @@ -733,3 +748,21 @@ impl Future for CreateProposal self.propose_with(proposed_candidates).map(Async::Ready) } } + +#[cfg(test)] +mod tests { + use super::*; + use substrate_keyring::Keyring; + + #[test] + fn sign_and_check_statement() { + let statement: Statement = GenericStatement::Valid([1; 32].into()); + let parent_hash = [2; 32].into(); + + let sig = sign_table_statement(&statement, &Keyring::Alice.pair(), &parent_hash); + + assert!(check_statement(&statement, &sig, Keyring::Alice.to_raw_public().into(), &parent_hash)); + assert!(!check_statement(&statement, &sig, Keyring::Alice.to_raw_public().into(), &[0xff; 32].into())); + assert!(!check_statement(&statement, &sig, Keyring::Bob.to_raw_public().into(), &parent_hash)); + } +} diff --git a/polkadot/consensus/src/service.rs b/polkadot/consensus/src/service.rs index f1ee7f49fe3b2..c577a98e96979 100644 --- a/polkadot/consensus/src/service.rs +++ b/polkadot/consensus/src/service.rs @@ -18,6 +18,10 @@ /// Consensus service. A long runnung service that manages BFT agreement and parachain /// candidate agreement over the network. +/// +/// This uses a handle to an underlying thread pool to dispatch heavy work +/// such as candidate verification while performing event-driven work +/// on a local event loop. use std::thread; use std::time::{Duration, Instant}; @@ -27,199 +31,40 @@ use bft::{self, BftService}; use client::{BlockchainEvents, ChainHead}; use ed25519; use futures::prelude::*; -use futures::{future, Canceled}; use polkadot_api::LocalPolkadotApi; -use polkadot_primitives::{BlockId, Block, Header, Hash, AccountId}; -use polkadot_primitives::parachain::{Id as ParaId, BlockData, Extrinsic, CandidateReceipt}; -use primitives::AuthorityId; -use runtime_support::Hashable; -use substrate_network as net; -use tokio_core::reactor; +use polkadot_primitives::{Block, Header}; use transaction_pool::TransactionPool; -use super::{TableRouter, SharedTable, ProposerFactory}; +use tokio::executor::current_thread::TaskExecutor as LocalThreadHandle; +use tokio::runtime::TaskExecutor as ThreadPoolHandle; +use tokio::runtime::current_thread::Runtime as LocalRuntime; +use tokio::timer::Interval; + +use super::{Network, Collators, ProposerFactory}; use error; const TIMER_DELAY_MS: u64 = 5000; const TIMER_INTERVAL_MS: u64 = 500; -struct BftSink { - network: Arc>, - parent_hash: Hash, - _e: ::std::marker::PhantomData, -} - -struct Messages { - network_stream: net::BftMessageStream, - local_id: AuthorityId, - authorities: Vec, -} - -impl Stream for Messages { - type Item = bft::Communication; - type Error = bft::Error; - - fn poll(&mut self) -> Poll, Self::Error> { - // check the network - loop { - match self.network_stream.poll() { - Err(_) => return Err(bft::InputStreamConcluded.into()), - Ok(Async::NotReady) => return Ok(Async::NotReady), - Ok(Async::Ready(None)) => return Ok(Async::NotReady), // the input stream for agreements is never meant to logically end. - Ok(Async::Ready(Some(message))) => { - match process_message(message, &self.local_id, &self.authorities) { - Ok(Some(message)) => return Ok(Async::Ready(Some(message))), - Ok(None) => {} // ignored local message. - Err(e) => { - debug!("Message validation failed: {:?}", e); - } - } - } - } - } - } -} - -fn process_message(msg: net::LocalizedBftMessage, local_id: &AuthorityId, authorities: &[AuthorityId]) -> Result>, bft::Error> { - Ok(Some(match msg.message { - net::generic_message::BftMessage::Consensus(c) => bft::generic::Communication::Consensus(match c { - net::generic_message::SignedConsensusMessage::Propose(proposal) => bft::generic::LocalizedMessage::Propose({ - if &proposal.sender == local_id { return Ok(None) } - let proposal = bft::generic::LocalizedProposal { - round_number: proposal.round_number as usize, - proposal: proposal.proposal, - digest: proposal.digest, - sender: proposal.sender, - digest_signature: ed25519::LocalizedSignature { - signature: proposal.digest_signature, - signer: ed25519::Public(proposal.sender), - }, - full_signature: ed25519::LocalizedSignature { - signature: proposal.full_signature, - signer: ed25519::Public(proposal.sender), - } - }; - bft::check_proposal(authorities, &msg.parent_hash, &proposal)?; - - trace!(target: "bft", "importing proposal message for round {} from {}", proposal.round_number, Hash::from(proposal.sender)); - proposal - }), - net::generic_message::SignedConsensusMessage::Vote(vote) => bft::generic::LocalizedMessage::Vote({ - if &vote.sender == local_id { return Ok(None) } - let vote = bft::generic::LocalizedVote { - sender: vote.sender, - signature: ed25519::LocalizedSignature { - signature: vote.signature, - signer: ed25519::Public(vote.sender), - }, - vote: match vote.vote { - net::generic_message::ConsensusVote::Prepare(r, h) => bft::generic::Vote::Prepare(r as usize, h), - net::generic_message::ConsensusVote::Commit(r, h) => bft::generic::Vote::Commit(r as usize, h), - net::generic_message::ConsensusVote::AdvanceRound(r) => bft::generic::Vote::AdvanceRound(r as usize), - } - }; - bft::check_vote::(authorities, &msg.parent_hash, &vote)?; - - trace!(target: "bft", "importing vote {:?} from {}", vote.vote, Hash::from(vote.sender)); - vote - }), - }), - net::generic_message::BftMessage::Auxiliary(a) => { - let justification = bft::UncheckedJustification::::from(a); - // TODO: get proper error - let justification: Result<_, bft::Error> = bft::check_prepare_justification::(authorities, msg.parent_hash, justification) - .map_err(|_| bft::ErrorKind::InvalidJustification.into()); - bft::generic::Communication::Auxiliary(justification?) - }, - })) -} - -impl Sink for BftSink { - type SinkItem = bft::Communication; - // TODO: replace this with the ! type when that's stabilized - type SinkError = E; - - fn start_send(&mut self, message: bft::Communication) -> ::futures::StartSend, E> { - let network_message = net::generic_message::LocalizedBftMessage { - message: match message { - bft::generic::Communication::Consensus(c) => net::generic_message::BftMessage::Consensus(match c { - bft::generic::LocalizedMessage::Propose(proposal) => net::generic_message::SignedConsensusMessage::Propose(net::generic_message::SignedConsensusProposal { - round_number: proposal.round_number as u32, - proposal: proposal.proposal, - digest: proposal.digest, - sender: proposal.sender, - digest_signature: proposal.digest_signature.signature, - full_signature: proposal.full_signature.signature, - }), - bft::generic::LocalizedMessage::Vote(vote) => net::generic_message::SignedConsensusMessage::Vote(net::generic_message::SignedConsensusVote { - sender: vote.sender, - signature: vote.signature.signature, - vote: match vote.vote { - bft::generic::Vote::Prepare(r, h) => net::generic_message::ConsensusVote::Prepare(r as u32, h), - bft::generic::Vote::Commit(r, h) => net::generic_message::ConsensusVote::Commit(r as u32, h), - bft::generic::Vote::AdvanceRound(r) => net::generic_message::ConsensusVote::AdvanceRound(r as u32), - } - }), - }), - bft::generic::Communication::Auxiliary(justification) => net::generic_message::BftMessage::Auxiliary(justification.uncheck().into()), - }, - parent_hash: self.parent_hash, - }; - self.network.send_bft_message(network_message); - Ok(::futures::AsyncSink::Ready) - } - - fn poll_complete(&mut self) -> ::futures::Poll<(), E> { - Ok(Async::Ready(())) - } -} - -struct Network(Arc>); - -impl super::Network for Network { - type TableRouter = Router; - fn table_router(&self, _table: Arc) -> Self::TableRouter { - Router { - network: self.0.clone() - } - } -} - +// spin up an instance of BFT agreement on the current thread's executor. +// panics if there is no current thread executor. fn start_bft( header: &Header, - handle: reactor::Handle, - client: &bft::Authorities, - network: Arc>, bft_service: &BftService, ) where - F: bft::ProposerFactory + 'static, + F: bft::Environment + 'static, C: bft::BlockImport + bft::Authorities + 'static, - >::Error: ::std::fmt::Debug, + F::Error: ::std::fmt::Debug, >::Error: ::std::fmt::Display + Into, + >::Error: ::std::fmt::Display { - let parent_hash = header.hash(); - if bft_service.live_agreement().map_or(false, |h| h == parent_hash) { - return; - } - let authorities = match client.authorities(&BlockId::hash(parent_hash)) { - Ok(authorities) => authorities, - Err(e) => { - debug!("Error reading authorities: {:?}", e); - return; - } - }; - - let input = Messages { - network_stream: network.bft_messages(parent_hash), - local_id: bft_service.local_id(), - authorities, - }; - - let output = BftSink { network: network, parent_hash: parent_hash, _e: Default::default() }; - match bft_service.build_upon(&header, input.map_err(Into::into), output) { - Ok(Some(bft)) => handle.spawn(bft), + let mut handle = LocalThreadHandle::current(); + match bft_service.build_upon(&header) { + Ok(Some(bft)) => if let Err(e) = handle.spawn_local(Box::new(bft)) { + debug!(target: "bft", "Couldn't initialize BFT agreement: {:?}", e); + }, Ok(None) => {}, - Err(e) => debug!(target: "bft", "BFT agreement error: {:?}", e), + Err(e) => warn!(target: "bft", "BFT agreement error: {}", e), } } @@ -231,54 +76,56 @@ pub struct Service { impl Service { /// Create and start a new instance. - pub fn new( + pub fn new( client: Arc, api: Arc, - network: Arc>, - transaction_pool: Arc, + network: N, + transaction_pool: Arc>, + thread_pool: ThreadPoolHandle, parachain_empty_duration: Duration, key: ed25519::Pair, ) -> Service where A: LocalPolkadotApi + Send + Sync + 'static, C: BlockchainEvents + ChainHead + bft::BlockImport + bft::Authorities + Send + Sync + 'static, + N: Network + Collators + Send + 'static, + N::TableRouter: Send + 'static, + ::Future: Send + 'static, { let (signal, exit) = ::exit_future::signal(); let thread = thread::spawn(move || { - let mut core = reactor::Core::new().expect("tokio::Core could not be created"); + let mut runtime = LocalRuntime::new().expect("Could not create local runtime"); let key = Arc::new(key); let factory = ProposerFactory { client: api.clone(), transaction_pool: transaction_pool.clone(), - network: Network(network.clone()), - collators: NoCollators, + collators: network.clone(), + network, parachain_empty_duration, - handle: core.handle(), + handle: thread_pool, }; let bft_service = Arc::new(BftService::new(client.clone(), key, factory)); let notifications = { - let handle = core.handle(); - let network = network.clone(); let client = client.clone(); let bft_service = bft_service.clone(); client.import_notification_stream().for_each(move |notification| { if notification.is_new_best { - start_bft(¬ification.header, handle.clone(), &*client, network.clone(), &*bft_service); + start_bft(¬ification.header, &*bft_service); } Ok(()) }) }; - let interval = reactor::Interval::new_at( + let interval = Interval::new( Instant::now() + Duration::from_millis(TIMER_DELAY_MS), Duration::from_millis(TIMER_INTERVAL_MS), - &core.handle(), - ).expect("it is always possible to create an interval with valid params"); + ); + let mut prev_best = match client.best_block_header() { - Ok(header) => header.blake2_256(), + Ok(header) => header.hash(), Err(e) => { warn!("Cant's start consensus service. Error reading best block header: {:?}", e); return; @@ -288,15 +135,13 @@ impl Service { let timed = { let c = client.clone(); let s = bft_service.clone(); - let n = network.clone(); - let handle = core.handle(); interval.map_err(|e| debug!("Timer error: {:?}", e)).for_each(move |_| { if let Ok(best_block) = c.best_block_header() { - let hash = best_block.blake2_256(); + let hash = best_block.hash(); if hash == prev_best { debug!("Starting consensus round after a timeout"); - start_bft(&best_block, handle.clone(), &*c, n.clone(), &*s); + start_bft(&best_block, &*s); } prev_best = hash; } @@ -304,9 +149,9 @@ impl Service { }) }; - core.handle().spawn(notifications); - core.handle().spawn(timed); - if let Err(e) = core.run(exit) { + runtime.spawn(notifications); + runtime.spawn(timed); + if let Err(e) = runtime.block_on(exit) { debug!("BFT event loop error {:?}", e); } }); @@ -328,42 +173,3 @@ impl Drop for Service { } } } - -// Collators implementation which never collates anything. -// TODO: do a real implementation. -#[derive(Clone, Copy)] -struct NoCollators; - -impl ::collation::Collators for NoCollators { - type Error = (); - type Collation = future::Empty<::collation::Collation, ()>; - - fn collate(&self, _parachain: ParaId, _relay_parent: Hash) -> Self::Collation { - future::empty() - } - - fn note_bad_collator(&self, _collator: AccountId) { } -} - -#[derive(Clone)] -struct Router { - network: Arc>, -} - -impl TableRouter for Router { - type Error = Canceled; - type FetchCandidate = future::Empty; - type FetchExtrinsic = future::FutureResult; - - fn local_candidate_data(&self, _hash: Hash, _block_data: BlockData, _extrinsic: Extrinsic) { - // TODO - } - - fn fetch_block_data(&self, _candidate: &CandidateReceipt) -> Self::FetchCandidate { - future::empty() - } - - fn fetch_extrinsic_data(&self, _candidate: &CandidateReceipt) -> Self::FetchExtrinsic { - future::ok(Extrinsic) - } -} diff --git a/polkadot/consensus/src/shared_table/mod.rs b/polkadot/consensus/src/shared_table/mod.rs index 120fbb7fec365..21919dd4a4869 100644 --- a/polkadot/consensus/src/shared_table/mod.rs +++ b/polkadot/consensus/src/shared_table/mod.rs @@ -14,18 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! Parachain statement table meant to to shared with a message router +//! Parachain statement table meant to be shared with a message router //! and a consensus proposer. use std::collections::{HashMap, HashSet}; use std::sync::Arc; use table::{self, Table, Context as TableContextTrait}; -use table::generic::Statement as GenericStatement; -use collation::Collation; -use polkadot_primitives::Hash; -use polkadot_primitives::parachain::{Id as ParaId, BlockData, Extrinsic, CandidateReceipt}; -use primitives::AuthorityId; +use polkadot_primitives::{Hash, SessionKey}; +use polkadot_primitives::parachain::{Id as ParaId, BlockData, Collation, Extrinsic, CandidateReceipt}; use parking_lot::Mutex; use futures::{future, prelude::*}; @@ -36,6 +33,8 @@ use self::includable::IncludabilitySender; mod includable; pub use self::includable::Includable; +pub use table::{SignedStatement, Statement}; +pub use table::generic::Statement as GenericStatement; struct TableContext { parent_hash: Hash, @@ -44,11 +43,11 @@ struct TableContext { } impl table::Context for TableContext { - fn is_member_of(&self, authority: &AuthorityId, group: &ParaId) -> bool { + fn is_member_of(&self, authority: &SessionKey, group: &ParaId) -> bool { self.groups.get(group).map_or(false, |g| g.validity_guarantors.contains(authority)) } - fn is_availability_guarantor_of(&self, authority: &AuthorityId, group: &ParaId) -> bool { + fn is_availability_guarantor_of(&self, authority: &SessionKey, group: &ParaId) -> bool { self.groups.get(group).map_or(false, |g| g.availability_guarantors.contains(authority)) } @@ -61,30 +60,21 @@ impl table::Context for TableContext { } impl TableContext { - fn local_id(&self) -> AuthorityId { - self.key.public().0 + fn local_id(&self) -> SessionKey { + self.key.public().into() } fn sign_statement(&self, statement: table::Statement) -> table::SignedStatement { let signature = ::sign_table_statement(&statement, &self.key, &self.parent_hash).into(); - let local_id = self.key.public().0; table::SignedStatement { statement, signature, - sender: local_id, + sender: self.local_id(), } } } -/// Source of statements -pub enum StatementSource { - /// Locally produced statement. - Local, - /// Received statement from remote source, with optional sender. - Remote(Option), -} - // A shared table object. struct SharedTableInner { table: Table, @@ -97,28 +87,21 @@ struct SharedTableInner { impl SharedTableInner { // Import a single statement. Provide a handle to a table router and a function // used to determine if a referenced candidate is valid. - fn import_statement bool>( + // + // the statement producer, if any, will produce only statements concerning the same candidate + // as the one just imported + fn import_remote_statement( &mut self, context: &TableContext, router: &R, statement: table::SignedStatement, - statement_source: StatementSource, - check_candidate: C, - ) -> StatementProducer< + ) -> Option::Future, ::Future, - C, - > { - // this blank producer does nothing until we attach some futures - // and set a candidate digest. - let received_from = match statement_source { - StatementSource::Local => return Default::default(), - StatementSource::Remote(from) => from, - }; - - let summary = match self.table.import_statement(context, statement, received_from) { + >> { + let summary = match self.table.import_statement(context, statement) { Some(summary) => summary, - None => return Default::default(), + None => return None, }; self.update_trackers(&summary.candidate, context); @@ -160,7 +143,6 @@ impl SharedTableInner { fetch_block_data, fetch_extrinsic, evaluate: checking_validity, - check_candidate, }) } } @@ -168,10 +150,10 @@ impl SharedTableInner { None }; - StatementProducer { + work.map(|work| StatementProducer { produced_statements: Default::default(), - work, - } + work + }) } fn update_trackers(&mut self, candidate: &Hash, context: &TableContext) { @@ -200,71 +182,78 @@ pub struct ProducedStatements { } /// Future that produces statements about a specific candidate. -pub struct StatementProducer { +pub struct StatementProducer { produced_statements: ProducedStatements, - work: Option>, + work: Work, +} + +impl StatementProducer { + /// Attach a function for verifying fetched collation to the statement producer. + /// This will transform it into a future. + /// + /// The collation-checking function should return `true` if known to be valid, + /// `false` if known to be invalid, and `None` if unable to determine. + pub fn prime Option>(self, check_candidate: C) -> PrimedStatementProducer { + PrimedStatementProducer { + inner: self, + check_candidate, + } + } } -struct Work { +struct Work { candidate_receipt: CandidateReceipt, fetch_block_data: future::Fuse, fetch_extrinsic: Option>, evaluate: bool, - check_candidate: C } -impl Default for StatementProducer { - fn default() -> Self { - StatementProducer { - produced_statements: Default::default(), - work: None, - } - } +/// Primed statement producer. +pub struct PrimedStatementProducer { + inner: StatementProducer, + check_candidate: C, } -impl Future for StatementProducer +impl Future for PrimedStatementProducer where D: Future, E: Future, - C: FnMut(Collation) -> bool, + C: FnMut(Collation) -> Option, { type Item = ProducedStatements; type Error = Err; fn poll(&mut self) -> Poll { - let work = match self.work { - Some(ref mut work) => work, - None => return Ok(Async::Ready(::std::mem::replace(&mut self.produced_statements, Default::default()))), - }; + let work = &mut self.inner.work; if let Async::Ready(block_data) = work.fetch_block_data.poll()? { - self.produced_statements.block_data = Some(block_data.clone()); + self.inner.produced_statements.block_data = Some(block_data.clone()); if work.evaluate { - let is_good = (work.check_candidate)(Collation { + let is_good = (self.check_candidate)(Collation { block_data, receipt: work.candidate_receipt.clone(), }); let hash = work.candidate_receipt.hash(); - self.produced_statements.validity = Some(if is_good { - GenericStatement::Valid(hash) - } else { - GenericStatement::Invalid(hash) - }); + self.inner.produced_statements.validity = match is_good { + Some(true) => Some(GenericStatement::Valid(hash)), + Some(false) => Some(GenericStatement::Invalid(hash)), + None => None, + }; } } if let Some(ref mut fetch_extrinsic) = work.fetch_extrinsic { if let Async::Ready(extrinsic) = fetch_extrinsic.poll()? { - self.produced_statements.extrinsic = Some(extrinsic); + self.inner.produced_statements.extrinsic = Some(extrinsic); } } - let done = self.produced_statements.block_data.is_some() && { + let done = self.inner.produced_statements.block_data.is_some() && { if work.evaluate { true - } else if self.produced_statements.extrinsic.is_some() { - self.produced_statements.availability = + } else if self.inner.produced_statements.extrinsic.is_some() { + self.inner.produced_statements.availability = Some(GenericStatement::Available(work.candidate_receipt.hash())); true @@ -274,7 +263,7 @@ impl Future for StatementProducer }; if done { - Ok(Async::Ready(::std::mem::replace(&mut self.produced_statements, Default::default()))) + Ok(Async::Ready(::std::mem::replace(&mut self.inner.produced_statements, Default::default()))) } else { Ok(Async::NotReady) } @@ -314,29 +303,60 @@ impl SharedTable { } } + /// Get the parent hash this table should hold statements localized to. + pub fn consensus_parent_hash(&self) -> &Hash { + &self.context.parent_hash + } + + /// Get the local validator session key. + pub fn session_key(&self) -> SessionKey { + self.context.local_id() + } + /// Get group info. pub fn group_info(&self) -> &HashMap { &self.context.groups } - /// Import a single statement. Provide a handle to a table router - /// for dispatching any other requests which come up. - pub fn import_statement bool>( + /// Import a single statement with remote source, whose signature has already been checked. + /// + /// The statement producer, if any, will produce only statements concerning the same candidate + /// as the one just imported + pub fn import_remote_statement( &self, router: &R, statement: table::SignedStatement, - received_from: StatementSource, - check_candidate: C, - ) -> StatementProducer<::Future, ::Future, C> { - self.inner.lock().import_statement(&*self.context, router, statement, received_from, check_candidate) + ) -> Option::Future, + ::Future, + >> { + self.inner.lock().import_remote_statement(&*self.context, router, statement) + } + + /// Import many statements at once. + /// + /// Provide an iterator yielding remote, pre-checked statements. + /// + /// The statement producer, if any, will produce only statements concerning the same candidate + /// as the one just imported + pub fn import_remote_statements(&self, router: &R, iterable: I) -> U + where + R: TableRouter, + I: IntoIterator, + U: ::std::iter::FromIterator::Future, + ::Future, + >>>, + { + let mut inner = self.inner.lock(); + + iterable.into_iter().map(move |statement| { + inner.import_remote_statement(&*self.context, router, statement) + }).collect() } /// Sign and import a local statement. - pub fn sign_and_import( - &self, - router: &R, - statement: table::Statement, - ) { + pub fn sign_and_import(&self, statement: table::Statement) -> SignedStatement { let proposed_digest = match statement { GenericStatement::Candidate(ref c) => Some(c.hash()), _ => None, @@ -349,36 +369,8 @@ impl SharedTable { inner.proposed_digest = proposed_digest; } - let producer = inner.import_statement( - &*self.context, - router, - signed_statement, - StatementSource::Local, - |_| true, - ); - - assert!(producer.work.is_none(), "local statement import never leads to additional work; qed"); - } - - /// Import many statements at once. - /// - /// Provide an iterator yielding pairs of (statement, statement_source). - pub fn import_statements(&self, router: &R, iterable: I) -> U - where - R: TableRouter, - I: IntoIterator, - C: FnMut(Collation) -> bool, - U: ::std::iter::FromIterator::Future, - ::Future, - C, - >>, - { - let mut inner = self.inner.lock(); - - iterable.into_iter().map(move |(statement, statement_source, check_candidate)| { - inner.import_statement(&*self.context, router, statement, statement_source, check_candidate) - }).collect() + inner.table.import_statement(&*self.context, signed_statement.clone()); + signed_statement } /// Execute a closure using a specific candidate. @@ -407,15 +399,10 @@ impl SharedTable { } /// Get all witnessed misbehavior. - pub fn get_misbehavior(&self) -> HashMap { + pub fn get_misbehavior(&self) -> HashMap { self.inner.lock().table.get_misbehavior().clone() } - /// Fill a statement batch. - pub fn fill_batch(&self, batch: &mut B) { - self.inner.lock().table.fill_batch(batch); - } - /// Track includability of a given set of candidate hashes. pub fn track_includability(&self, iterable: I) -> Includable where I: IntoIterator @@ -447,17 +434,12 @@ mod tests { type FetchCandidate = ::futures::future::Empty; type FetchExtrinsic = ::futures::future::Empty; - /// Note local candidate data, making it available on the network to other validators. - fn local_candidate_data(&self, _hash: Hash, _block_data: BlockData, _extrinsic: Extrinsic) { + fn local_candidate(&self, _candidate: CandidateReceipt, _block_data: BlockData, _extrinsic: Extrinsic) { } - - /// Fetch block data for a specific candidate. fn fetch_block_data(&self, _candidate: &CandidateReceipt) -> Self::FetchCandidate { ::futures::future::empty() } - - /// Fetch extrinsic data for a specific candidate. fn fetch_extrinsic_data(&self, _candidate: &CandidateReceipt) -> Self::FetchExtrinsic { ::futures::future::empty() } @@ -468,10 +450,10 @@ mod tests { let mut groups = HashMap::new(); let para_id = ParaId::from(1); - let local_id = Keyring::Alice.to_raw_public(); + let local_id = Keyring::Alice.to_raw_public().into(); let local_key = Arc::new(Keyring::Alice.pair()); - let validity_other = Keyring::Bob.to_raw_public(); + let validity_other = Keyring::Bob.to_raw_public().into(); let validity_other_key = Keyring::Bob.pair(); let parent_hash = Default::default(); @@ -487,10 +469,12 @@ mod tests { let candidate = CandidateReceipt { parachain_index: para_id, collator: [1; 32].into(), + signature: Default::default(), head_data: ::polkadot_primitives::parachain::HeadData(vec![1, 2, 3, 4]), balance_uploads: Vec::new(), egress_queue_roots: Vec::new(), fees: 1_000_000, + block_data_hash: [2; 32].into(), }; let candidate_statement = GenericStatement::Candidate(candidate); @@ -502,15 +486,13 @@ mod tests { sender: validity_other, }; - let producer = shared_table.import_statement( + let producer = shared_table.import_remote_statement( &DummyRouter, signed_statement, - StatementSource::Remote(None), - |_| true, - ); + ).expect("candidate and local validity group are same"); - assert!(producer.work.is_some(), "candidate and local validity group are same"); - assert!(producer.work.as_ref().unwrap().evaluate, "should evaluate validity"); + assert!(producer.work.evaluate, "should evaluate validity"); + assert!(producer.work.fetch_extrinsic.is_none(), "should not fetch extrinsic"); } #[test] @@ -518,10 +500,10 @@ mod tests { let mut groups = HashMap::new(); let para_id = ParaId::from(1); - let local_id = Keyring::Alice.to_raw_public(); + let local_id = Keyring::Alice.to_raw_public().into(); let local_key = Arc::new(Keyring::Alice.pair()); - let validity_other = Keyring::Bob.to_raw_public(); + let validity_other = Keyring::Bob.to_raw_public().into(); let validity_other_key = Keyring::Bob.pair(); let parent_hash = Default::default(); @@ -537,10 +519,12 @@ mod tests { let candidate = CandidateReceipt { parachain_index: para_id, collator: [1; 32].into(), + signature: Default::default(), head_data: ::polkadot_primitives::parachain::HeadData(vec![1, 2, 3, 4]), balance_uploads: Vec::new(), egress_queue_roots: Vec::new(), fees: 1_000_000, + block_data_hash: [2; 32].into(), }; let candidate_statement = GenericStatement::Candidate(candidate); @@ -552,15 +536,12 @@ mod tests { sender: validity_other, }; - let producer = shared_table.import_statement( + let producer = shared_table.import_remote_statement( &DummyRouter, signed_statement, - StatementSource::Remote(None), - |_| true, - ); + ).expect("should produce work"); - assert!(producer.work.is_some(), "candidate and local availability group are same"); - assert!(producer.work.as_ref().unwrap().fetch_extrinsic.is_some(), "should fetch extrinsic when guaranteeing availability"); - assert!(!producer.work.as_ref().unwrap().evaluate, "should not evaluate validity"); + assert!(producer.work.fetch_extrinsic.is_some(), "should fetch extrinsic when guaranteeing availability"); + assert!(!producer.work.evaluate, "should not evaluate validity"); } } diff --git a/polkadot/executor/README.adoc b/polkadot/executor/README.adoc new file mode 100644 index 0000000000000..1c91cccab5fac --- /dev/null +++ b/polkadot/executor/README.adoc @@ -0,0 +1,5 @@ + += Polkadot Executor + +placeholder +//TODO Write content :) diff --git a/polkadot/executor/src/lib.rs b/polkadot/executor/src/lib.rs index be44d8afbae9e..82cd5cd47851c 100644 --- a/polkadot/executor/src/lib.rs +++ b/polkadot/executor/src/lib.rs @@ -20,4 +20,4 @@ extern crate polkadot_runtime; #[macro_use] extern crate substrate_executor; -native_executor_instance!(pub Executor, polkadot_runtime::api::dispatch, include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm")); +native_executor_instance!(pub Executor, polkadot_runtime::api::dispatch, polkadot_runtime::VERSION, include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm")); diff --git a/polkadot/network/Cargo.toml b/polkadot/network/Cargo.toml new file mode 100644 index 0000000000000..37d36ea205e50 --- /dev/null +++ b/polkadot/network/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "polkadot-network" +version = "0.1.0" +authors = ["Parity Technologies "] +description = "Polkadot-specific networking protocol" + +[dependencies] +parking_lot = "0.4" +polkadot-api = { path = "../api" } +polkadot-consensus = { path = "../consensus" } +polkadot-primitives = { path = "../primitives" } +substrate-bft = { path = "../../substrate/bft" } +substrate-codec = { path = "../../substrate/codec" } +substrate-network = { path = "../../substrate/network" } +substrate-primitives = { path = "../../substrate/primitives" } +ed25519 = { path = "../../substrate/ed25519" } +futures = "0.1" +tokio = "0.1.7" +log = "0.4" +rhododendron = "0.2" diff --git a/polkadot/network/README.adoc b/polkadot/network/README.adoc new file mode 100644 index 0000000000000..1c2ad29b1b098 --- /dev/null +++ b/polkadot/network/README.adoc @@ -0,0 +1,5 @@ + += Polkadot Network + +placeholder +//TODO Write content :) diff --git a/polkadot/network/src/collator_pool.rs b/polkadot/network/src/collator_pool.rs new file mode 100644 index 0000000000000..7070eece88c20 --- /dev/null +++ b/polkadot/network/src/collator_pool.rs @@ -0,0 +1,337 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Bridge between the network and consensus service for getting collations to it. + +use polkadot_primitives::{AccountId, Hash}; +use polkadot_primitives::parachain::{Id as ParaId, Collation}; +use codec; + +use futures::sync::oneshot; + +use std::collections::hash_map::{HashMap, Entry}; +use std::time::{Duration, Instant}; + +const COLLATION_LIFETIME: Duration = Duration::from_secs(60 * 5); + +/// The role of the collator. Whether they're the primary or backup for this parachain. +#[derive(PartialEq, Debug, Clone, Copy)] +pub enum Role { + /// Primary collators should send collations whenever it's time. + Primary = 0, + /// Backup collators should not. + Backup = 1, +} + +impl codec::Encode for Role { + fn encode_to(&self, dest: &mut T) { + dest.push_byte(*self as u8); + } +} + +impl codec::Decode for Role { + fn decode(input: &mut I) -> Option { + match input.read_byte()? { + x if x == Role::Primary as u8 => Some(Role::Primary), + x if x == Role::Backup as u8 => Some(Role::Backup), + _ => None, + } + } +} + +/// A maintenance action for the collator set. +#[derive(PartialEq, Debug)] +#[allow(dead_code)] +pub enum Action { + /// Disconnect the given collator. + Disconnect(AccountId), + /// Give the collator a new role. + NewRole(AccountId, Role), +} + +struct CollationSlot { + live_at: Instant, + entries: SlotEntries, +} + +impl CollationSlot { + fn blank_now() -> Self { + CollationSlot { + live_at: Instant::now(), + entries: SlotEntries::Blank, + } + } + + fn stay_alive(&self, now: Instant) -> bool { + self.live_at + COLLATION_LIFETIME > now + } +} + +enum SlotEntries { + Blank, + // not queried yet + Pending(Vec), + // waiting for next to arrive. + Awaiting(Vec>), +} + +impl SlotEntries { + fn received_collation(&mut self, collation: Collation) { + *self = match ::std::mem::replace(self, SlotEntries::Blank) { + SlotEntries::Blank => SlotEntries::Pending(vec![collation]), + SlotEntries::Pending(mut cs) => { + cs.push(collation); + SlotEntries::Pending(cs) + } + SlotEntries::Awaiting(senders) => { + for sender in senders { + let _ = sender.send(collation.clone()); + } + + SlotEntries::Blank + } + }; + } + + fn await_with(&mut self, sender: oneshot::Sender) { + *self = match ::std::mem::replace(self, SlotEntries::Blank) { + SlotEntries::Blank => SlotEntries::Awaiting(vec![sender]), + SlotEntries::Awaiting(mut senders) => { + senders.push(sender); + SlotEntries::Awaiting(senders) + } + SlotEntries::Pending(mut cs) => { + let next_collation = cs.pop().expect("empty variant is always `Blank`; qed"); + let _ = sender.send(next_collation); + + if cs.is_empty() { + SlotEntries::Blank + } else { + SlotEntries::Pending(cs) + } + } + }; + } +} + +struct ParachainCollators { + primary: AccountId, + backup: Vec, +} + +/// Manages connected collators and role assignments from the perspective of a validator. +pub struct CollatorPool { + collators: HashMap, + parachain_collators: HashMap, + collations: HashMap<(Hash, ParaId), CollationSlot>, +} + +impl CollatorPool { + /// Create a new `CollatorPool` object. + pub fn new() -> Self { + CollatorPool { + collators: HashMap::new(), + parachain_collators: HashMap::new(), + collations: HashMap::new(), + } + } + + /// Call when a new collator is authenticated. Returns the role. + pub fn on_new_collator(&mut self, account_id: AccountId, para_id: ParaId) -> Role { + self.collators.insert(account_id.clone(), para_id); + match self.parachain_collators.entry(para_id) { + Entry::Vacant(vacant) => { + vacant.insert(ParachainCollators { + primary: account_id, + backup: Vec::new(), + }); + + Role::Primary + }, + Entry::Occupied(mut occupied) => { + occupied.get_mut().backup.push(account_id); + + Role::Backup + } + } + } + + /// Called when a collator disconnects. If it was the primary, returns a new primary for that + /// parachain. + pub fn on_disconnect(&mut self, account_id: AccountId) -> Option { + self.collators.remove(&account_id).and_then(|para_id| match self.parachain_collators.entry(para_id) { + Entry::Vacant(_) => None, + Entry::Occupied(mut occ) => { + if occ.get().primary == account_id { + if occ.get().backup.is_empty() { + occ.remove(); + None + } else { + let mut collators = occ.get_mut(); + collators.primary = collators.backup.pop().expect("backup non-empty; qed"); + Some(collators.primary) + } + } else { + let pos = occ.get().backup.iter().position(|a| a == &account_id) + .expect("registered collator always present in backup if not primary; qed"); + + occ.get_mut().backup.remove(pos); + None + } + } + }) + } + + /// Called when a collation is received. + /// The collator should be registered for the parachain of the collation as a precondition of this function. + /// The collation should have been checked for integrity of signature before passing to this function. + pub fn on_collation(&mut self, account_id: AccountId, relay_parent: Hash, collation: Collation) { + if let Some(para_id) = self.collators.get(&account_id) { + debug_assert_eq!(para_id, &collation.receipt.parachain_index); + + // TODO: punish if not primary? + + self.collations.entry((relay_parent, para_id.clone())) + .or_insert_with(CollationSlot::blank_now) + .entries + .received_collation(collation); + } + } + + /// Wait for a collation from a parachain. + pub fn await_collation(&mut self, relay_parent: Hash, para_id: ParaId, sender: oneshot::Sender) { + self.collations.entry((relay_parent, para_id)) + .or_insert_with(CollationSlot::blank_now) + .entries + .await_with(sender); + } + + /// Call periodically to perform collator set maintenance. + /// Returns a set of actions to perform on the network level. + pub fn maintain_peers(&mut self) -> Vec { + // TODO: rearrange periodically to new primary, evaluate based on latency etc. + Vec::new() + } + + /// called when a block with given hash has been imported. + pub fn collect_garbage(&mut self, chain_head: Option<&Hash>) { + let now = Instant::now(); + self.collations.retain(|&(ref h, _), slot| chain_head != Some(h) && slot.stay_alive(now)); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use polkadot_primitives::parachain::{CandidateReceipt, BlockData, HeadData}; + use substrate_primitives::H512; + use futures::Future; + + #[test] + fn disconnect_primary_gives_new_primary() { + let mut pool = CollatorPool::new(); + let para_id: ParaId = 5.into(); + let bad_primary = [0; 32].into(); + let good_backup = [1; 32].into(); + + assert_eq!(pool.on_new_collator(bad_primary, para_id.clone()), Role::Primary); + assert_eq!(pool.on_new_collator(good_backup, para_id.clone()), Role::Backup); + assert_eq!(pool.on_disconnect(bad_primary), Some(good_backup)); + assert_eq!(pool.on_disconnect(good_backup), None); + } + + #[test] + fn disconnect_backup_removes_from_pool() { + let mut pool = CollatorPool::new(); + let para_id: ParaId = 5.into(); + let primary = [0; 32].into(); + let backup = [1; 32].into(); + + assert_eq!(pool.on_new_collator(primary, para_id.clone()), Role::Primary); + assert_eq!(pool.on_new_collator(backup, para_id.clone()), Role::Backup); + assert_eq!(pool.on_disconnect(backup), None); + assert!(pool.parachain_collators.get(¶_id).unwrap().backup.is_empty()); + } + + #[test] + fn await_before_collation() { + let mut pool = CollatorPool::new(); + let para_id: ParaId = 5.into(); + let primary = [0; 32].into(); + let relay_parent = [1; 32].into(); + + assert_eq!(pool.on_new_collator(primary, para_id.clone()), Role::Primary); + let (tx1, rx1) = oneshot::channel(); + let (tx2, rx2) = oneshot::channel(); + pool.await_collation(relay_parent, para_id, tx1); + pool.await_collation(relay_parent, para_id, tx2); + pool.on_collation(primary, relay_parent, Collation { + receipt: CandidateReceipt { + parachain_index: para_id, + collator: primary.into(), + signature: H512::from([2; 64]).into(), + head_data: HeadData(vec![1, 2, 3]), + balance_uploads: vec![], + egress_queue_roots: vec![], + fees: 0, + block_data_hash: [3; 32].into(), + }, + block_data: BlockData(vec![4, 5, 6]), + }); + + rx1.wait().unwrap(); + rx2.wait().unwrap(); + } + + #[test] + fn collate_before_await() { + let mut pool = CollatorPool::new(); + let para_id: ParaId = 5.into(); + let primary = [0; 32].into(); + let relay_parent = [1; 32].into(); + + assert_eq!(pool.on_new_collator(primary, para_id.clone()), Role::Primary); + + pool.on_collation(primary, relay_parent, Collation { + receipt: CandidateReceipt { + parachain_index: para_id, + collator: primary.into(), + signature: H512::from([2; 64]).into(), + head_data: HeadData(vec![1, 2, 3]), + balance_uploads: vec![], + egress_queue_roots: vec![], + fees: 0, + block_data_hash: [3; 32].into(), + }, + block_data: BlockData(vec![4, 5, 6]), + }); + + let (tx, rx) = oneshot::channel(); + pool.await_collation(relay_parent, para_id, tx); + rx.wait().unwrap(); + } + + #[test] + fn slot_stay_alive() { + let slot = CollationSlot::blank_now(); + let now = slot.live_at; + + assert!(slot.stay_alive(now)); + assert!(slot.stay_alive(now + Duration::from_secs(10))); + assert!(!slot.stay_alive(now + COLLATION_LIFETIME)); + assert!(!slot.stay_alive(now + COLLATION_LIFETIME + Duration::from_secs(10))); + } +} diff --git a/polkadot/network/src/consensus.rs b/polkadot/network/src/consensus.rs new file mode 100644 index 0000000000000..4f29899100350 --- /dev/null +++ b/polkadot/network/src/consensus.rs @@ -0,0 +1,341 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! The "consensus" networking code built on top of the base network service. +//! This fulfills the `polkadot_consensus::Network` trait, providing a hook to be called +//! each time consensus begins on a new chain head. + +use bft; +use ed25519; +use substrate_network::{self as net, generic_message as msg}; +use substrate_network::consensus_gossip::ConsensusMessage; +use polkadot_api::{PolkadotApi, LocalPolkadotApi}; +use polkadot_consensus::{Network, SharedTable, Collators}; +use polkadot_primitives::{AccountId, Block, Hash, SessionKey}; +use polkadot_primitives::parachain::{Id as ParaId, Collation}; +use codec::Decode; + +use futures::prelude::*; +use futures::sync::mpsc; + +use std::sync::Arc; + +use tokio::runtime::TaskExecutor; +use parking_lot::Mutex; + +use super::{Message, NetworkService, Knowledge, CurrentConsensus}; +use router::Router; + +/// Sink for output BFT messages. +pub struct BftSink { + network: Arc, + parent_hash: Hash, + _marker: ::std::marker::PhantomData, +} + +impl Sink for BftSink { + type SinkItem = bft::Communication; + // TODO: replace this with the ! type when that's stabilized + type SinkError = E; + + fn start_send(&mut self, message: bft::Communication) -> ::futures::StartSend, E> { + let network_message = net::LocalizedBftMessage { + message: match message { + ::rhododendron::Communication::Consensus(c) => msg::BftMessage::Consensus(match c { + ::rhododendron::LocalizedMessage::Propose(proposal) => msg::SignedConsensusMessage::Propose(msg::SignedConsensusProposal { + round_number: proposal.round_number as u32, + proposal: proposal.proposal, + digest: proposal.digest, + sender: proposal.sender, + digest_signature: proposal.digest_signature.signature, + full_signature: proposal.full_signature.signature, + }), + ::rhododendron::LocalizedMessage::Vote(vote) => msg::SignedConsensusMessage::Vote(msg::SignedConsensusVote { + sender: vote.sender, + signature: vote.signature.signature, + vote: match vote.vote { + ::rhododendron::Vote::Prepare(r, h) => msg::ConsensusVote::Prepare(r as u32, h), + ::rhododendron::Vote::Commit(r, h) => msg::ConsensusVote::Commit(r as u32, h), + ::rhododendron::Vote::AdvanceRound(r) => msg::ConsensusVote::AdvanceRound(r as u32), + } + }), + }), + ::rhododendron::Communication::Auxiliary(justification) => { + let unchecked: bft::UncheckedJustification<_> = justification.uncheck().into(); + msg::BftMessage::Auxiliary(unchecked.into()) + } + }, + parent_hash: self.parent_hash, + }; + self.network.with_spec( + move |spec, ctx| spec.consensus_gossip.multicast_bft_message(ctx, network_message) + ); + Ok(::futures::AsyncSink::Ready) + } + + fn poll_complete(&mut self) -> ::futures::Poll<(), E> { + Ok(Async::Ready(())) + } +} + +// check signature and authority validity of message. +fn process_bft_message(msg: msg::LocalizedBftMessage, local_id: &SessionKey, authorities: &[SessionKey]) -> Result>, bft::Error> { + Ok(Some(match msg.message { + msg::BftMessage::Consensus(c) => ::rhododendron::Communication::Consensus(match c { + msg::SignedConsensusMessage::Propose(proposal) => ::rhododendron::LocalizedMessage::Propose({ + if &proposal.sender == local_id { return Ok(None) } + let proposal = ::rhododendron::LocalizedProposal { + round_number: proposal.round_number as usize, + proposal: proposal.proposal, + digest: proposal.digest, + sender: proposal.sender, + digest_signature: ed25519::LocalizedSignature { + signature: proposal.digest_signature, + signer: ed25519::Public(proposal.sender.into()), + }, + full_signature: ed25519::LocalizedSignature { + signature: proposal.full_signature, + signer: ed25519::Public(proposal.sender.into()), + } + }; + bft::check_proposal(authorities, &msg.parent_hash, &proposal)?; + + trace!(target: "bft", "importing proposal message for round {} from {}", proposal.round_number, Hash::from(proposal.sender.0)); + proposal + }), + msg::SignedConsensusMessage::Vote(vote) => ::rhododendron::LocalizedMessage::Vote({ + if &vote.sender == local_id { return Ok(None) } + let vote = ::rhododendron::LocalizedVote { + sender: vote.sender, + signature: ed25519::LocalizedSignature { + signature: vote.signature, + signer: ed25519::Public(vote.sender.0), + }, + vote: match vote.vote { + msg::ConsensusVote::Prepare(r, h) => ::rhododendron::Vote::Prepare(r as usize, h), + msg::ConsensusVote::Commit(r, h) => ::rhododendron::Vote::Commit(r as usize, h), + msg::ConsensusVote::AdvanceRound(r) => ::rhododendron::Vote::AdvanceRound(r as usize), + } + }; + bft::check_vote::(authorities, &msg.parent_hash, &vote)?; + + trace!(target: "bft", "importing vote {:?} from {}", vote.vote, Hash::from(vote.sender.0)); + vote + }), + }), + msg::BftMessage::Auxiliary(a) => { + let justification = bft::UncheckedJustification::from(a); + // TODO: get proper error + let justification: Result<_, bft::Error> = bft::check_prepare_justification::(authorities, msg.parent_hash, justification) + .map_err(|_| bft::ErrorKind::InvalidJustification.into()); + ::rhododendron::Communication::Auxiliary(justification?) + }, + })) +} + +// task that processes all gossipped consensus messages, +// checking signatures +struct MessageProcessTask { + inner_stream: mpsc::UnboundedReceiver>, + bft_messages: mpsc::UnboundedSender>, + validators: Vec, + table_router: Router

, +} + +impl MessageProcessTask

{ + fn process_message(&self, msg: ConsensusMessage) -> Option> { + match msg { + ConsensusMessage::Bft(msg) => { + let local_id = self.table_router.session_key(); + match process_bft_message(msg, &local_id, &self.validators[..]) { + Ok(Some(msg)) => { + if let Err(_) = self.bft_messages.unbounded_send(msg) { + // if the BFT receiving stream has ended then + // we should just bail. + trace!(target: "bft", "BFT message stream appears to have closed"); + return Some(Async::Ready(())); + } + } + Ok(None) => {} // ignored local message + Err(e) => { + debug!("Message validation failed: {:?}", e); + } + } + } + ConsensusMessage::ChainSpecific(msg, _) => { + if let Some(Message::Statement(parent_hash, statement)) = Decode::decode(&mut msg.as_slice()) { + if ::polkadot_consensus::check_statement(&statement.statement, &statement.signature, statement.sender, &parent_hash) { + self.table_router.import_statement(statement); + } + } + } + } + + None + } +} + +impl Future for MessageProcessTask

{ + type Item = (); + type Error = (); + + fn poll(&mut self) -> Poll<(), ()> { + loop { + match self.inner_stream.poll() { + Ok(Async::Ready(Some(val))) => if let Some(async) = self.process_message(val) { + return Ok(async); + }, + Ok(Async::Ready(None)) => return Ok(Async::Ready(())), + Ok(Async::NotReady) => return Ok(Async::NotReady), + Err(e) => debug!(target: "p_net", "Error getting consensus message: {:?}", e), + } + } + } +} + +/// Input stream from the consensus network. +pub struct InputAdapter { + input: mpsc::UnboundedReceiver>, +} + +impl Stream for InputAdapter { + type Item = bft::Communication; + type Error = ::polkadot_consensus::Error; + + fn poll(&mut self) -> Poll, Self::Error> { + match self.input.poll() { + Err(_) | Ok(Async::Ready(None)) => Err(bft::InputStreamConcluded.into()), + Ok(x) => Ok(x) + } + } +} + +/// Wrapper around the network service +pub struct ConsensusNetwork

{ + network: Arc, + api: Arc

, +} + +impl

ConsensusNetwork

{ + /// Create a new consensus networking object. + pub fn new(network: Arc, api: Arc

) -> Self { + ConsensusNetwork { network, api } + } +} + +impl

Clone for ConsensusNetwork

{ + fn clone(&self) -> Self { + ConsensusNetwork { + network: self.network.clone(), + api: self.api.clone(), + } + } +} + +/// A long-lived network which can create parachain statement and BFT message routing processes on demand. +impl Network for ConsensusNetwork

{ + type TableRouter = Router

; + /// The input stream of BFT messages. Should never logically conclude. + type Input = InputAdapter; + /// The output sink of BFT messages. Messages sent here should eventually pass to all + /// current validators. + type Output = BftSink<::polkadot_consensus::Error>; + + /// Instantiate a table router using the given shared table. + fn communication_for(&self, validators: &[SessionKey], table: Arc, task_executor: TaskExecutor) -> (Self::TableRouter, Self::Input, Self::Output) { + let parent_hash = table.consensus_parent_hash().clone(); + + let sink = BftSink { + network: self.network.clone(), + parent_hash, + _marker: Default::default(), + }; + + let (bft_send, bft_recv) = mpsc::unbounded(); + + let knowledge = Arc::new(Mutex::new(Knowledge::new())); + + let local_session_key = table.session_key(); + let table_router = Router::new( + table, + self.network.clone(), + self.api.clone(), + task_executor.clone(), + parent_hash, + knowledge.clone(), + ); + + // spin up a task in the background that processes all incoming statements + // TODO: propagate statements on a timer? + let process_task = self.network.with_spec(|spec, ctx| { + spec.new_consensus(ctx, CurrentConsensus { + knowledge, + parent_hash, + local_session_key, + }); + + MessageProcessTask { + inner_stream: spec.consensus_gossip.messages_for(parent_hash), + bft_messages: bft_send, + validators: validators.to_vec(), + table_router: table_router.clone(), + } + }); + + match process_task { + Some(task) => task_executor.spawn(task), + None => warn!(target: "p_net", "Cannot process incoming messages: network appears to be down"), + } + + (table_router, InputAdapter { input: bft_recv }, sink) + } +} + +/// Error when the network appears to be down. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct NetworkDown; + +/// A future that resolves when a collation is received. +pub struct AwaitingCollation(Option<::futures::sync::oneshot::Receiver>); + +impl Future for AwaitingCollation { + type Item = Collation; + type Error = NetworkDown; + + fn poll(&mut self) -> Poll { + match self.0.poll().map_err(|_| NetworkDown)? { + Async::Ready(None) => Err(NetworkDown), + Async::Ready(Some(x)) => Ok(Async::Ready(x)), + Async::NotReady => Ok(Async::NotReady), + } + } +} + + +impl Collators for ConsensusNetwork

{ + type Error = NetworkDown; + type Collation = AwaitingCollation; + + fn collate(&self, parachain: ParaId, relay_parent: Hash) -> Self::Collation { + AwaitingCollation( + self.network.with_spec(|spec, _| spec.await_collation(relay_parent, parachain)) + ) + } + + fn note_bad_collator(&self, collator: AccountId) { + self.network.with_spec(|spec, ctx| spec.disconnect_bad_collator(ctx, collator)); + } +} diff --git a/polkadot/network/src/lib.rs b/polkadot/network/src/lib.rs new file mode 100644 index 0000000000000..8fbc6dba3a7b5 --- /dev/null +++ b/polkadot/network/src/lib.rs @@ -0,0 +1,683 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Polkadot-specific network implementation. +//! +//! This manages gossip of consensus messages for BFT and for parachain statements, +//! parachain block and extrinsic data fetching, communication between collators and validators, +//! and more. + +extern crate substrate_bft as bft; +extern crate substrate_codec as codec; +extern crate substrate_network; +extern crate substrate_primitives; + +extern crate polkadot_api; +extern crate polkadot_consensus; +extern crate polkadot_primitives; + +extern crate ed25519; +extern crate futures; +extern crate parking_lot; +extern crate tokio; +extern crate rhododendron; + +#[macro_use] +extern crate log; + +mod collator_pool; +mod local_collations; +mod router; +pub mod consensus; + +use codec::{Decode, Encode, Input, Output}; +use futures::sync::oneshot; +use parking_lot::Mutex; +use polkadot_consensus::{Statement, SignedStatement, GenericStatement}; +use polkadot_primitives::{AccountId, Block, SessionKey, Hash, Header}; +use polkadot_primitives::parachain::{Id as ParaId, BlockData, Extrinsic, CandidateReceipt, Collation}; +use substrate_network::{NodeIndex, RequestId, Context, Severity}; +use substrate_network::consensus_gossip::ConsensusGossip; +use substrate_network::{message, generic_message}; +use substrate_network::specialization::Specialization; +use substrate_network::StatusMessage as GenericFullStatus; +use self::collator_pool::{CollatorPool, Role, Action}; +use self::local_collations::LocalCollations; + +use std::collections::{HashMap, HashSet}; +use std::sync::Arc; + + +#[cfg(test)] +mod tests; + +/// Polkadot protocol id. +pub const DOT_PROTOCOL_ID: ::substrate_network::ProtocolId = *b"dot"; + +type FullStatus = GenericFullStatus; + +/// Specialization of the network service for the polkadot protocol. +pub type NetworkService = ::substrate_network::Service; + +/// Status of a Polkadot node. +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Status { + collating_for: Option<(AccountId, ParaId)>, +} + +impl Encode for Status { + fn encode_to(&self, dest: &mut T) { + match self.collating_for { + Some(ref details) => { + dest.push_byte(1); + dest.push(details); + } + None => { + dest.push_byte(0); + } + } + } +} + +impl Decode for Status { + fn decode(input: &mut I) -> Option { + let collating_for = match input.read_byte()? { + 0 => None, + 1 => Some(Decode::decode(input)?), + _ => return None, + }; + Some(Status { collating_for }) + } +} + +struct BlockDataRequest { + attempted_peers: HashSet, + consensus_parent: Hash, + candidate_hash: Hash, + block_data_hash: Hash, + sender: oneshot::Sender, +} + +struct PeerInfo { + collating_for: Option<(AccountId, ParaId)>, + validator_key: Option, + claimed_validator: bool, +} + +#[derive(Default)] +struct KnowledgeEntry { + knows_block_data: Vec, + knows_extrinsic: Vec, + block_data: Option, + extrinsic: Option, +} + +/// Tracks knowledge of peers. +struct Knowledge { + candidates: HashMap, +} + +impl Knowledge { + pub fn new() -> Self { + Knowledge { + candidates: HashMap::new(), + } + } + + fn note_statement(&mut self, from: SessionKey, statement: &Statement) { + match *statement { + GenericStatement::Candidate(ref c) => { + let mut entry = self.candidates.entry(c.hash()).or_insert_with(Default::default); + entry.knows_block_data.push(from); + entry.knows_extrinsic.push(from); + } + GenericStatement::Available(ref hash) => { + let mut entry = self.candidates.entry(*hash).or_insert_with(Default::default); + entry.knows_block_data.push(from); + entry.knows_extrinsic.push(from); + } + GenericStatement::Valid(ref hash) | GenericStatement::Invalid(ref hash) => self.candidates.entry(*hash) + .or_insert_with(Default::default) + .knows_block_data + .push(from), + } + } + + fn note_candidate(&mut self, hash: Hash, block_data: Option, extrinsic: Option) { + let entry = self.candidates.entry(hash).or_insert_with(Default::default); + entry.block_data = entry.block_data.take().or(block_data); + entry.extrinsic = entry.extrinsic.take().or(extrinsic); + } +} + +struct CurrentConsensus { + knowledge: Arc>, + parent_hash: Hash, + local_session_key: SessionKey, +} + +impl CurrentConsensus { + // get locally stored block data for a candidate. + fn block_data(&self, hash: &Hash) -> Option { + self.knowledge.lock().candidates.get(hash) + .and_then(|entry| entry.block_data.clone()) + } +} + +/// Polkadot-specific messages. +#[derive(Debug)] +pub enum Message { + /// signed statement and localized parent hash. + Statement(Hash, SignedStatement), + /// As a validator, tell the peer your current session key. + // TODO: do this with a cryptographic proof of some kind + SessionKey(SessionKey), + /// Requesting parachain block data by candidate hash. + RequestBlockData(RequestId, Hash), + /// Provide block data by candidate hash or nothing if unknown. + BlockData(RequestId, Option), + /// Tell a collator their role. + CollatorRole(Role), + /// A collation provided by a peer. Relay parent and collation. + Collation(Hash, Collation), +} + +impl Encode for Message { + fn encode_to(&self, dest: &mut T) { + match *self { + Message::Statement(ref h, ref s) => { + dest.push_byte(0); + dest.push(h); + dest.push(s); + } + Message::SessionKey(ref k) => { + dest.push_byte(1); + dest.push(k); + } + Message::RequestBlockData(ref id, ref d) => { + dest.push_byte(2); + dest.push(id); + dest.push(d); + } + Message::BlockData(ref id, ref d) => { + dest.push_byte(3); + dest.push(id); + dest.push(d); + } + Message::CollatorRole(ref r) => { + dest.push_byte(4); + dest.push(r); + } + Message::Collation(ref h, ref c) => { + dest.push_byte(5); + dest.push(h); + dest.push(c); + } + } + } +} + +impl Decode for Message { + fn decode(input: &mut I) -> Option { + match input.read_byte()? { + 0 => Some(Message::Statement(Decode::decode(input)?, Decode::decode(input)?)), + 1 => Some(Message::SessionKey(Decode::decode(input)?)), + 2 => Some(Message::RequestBlockData(Decode::decode(input)?, Decode::decode(input)?)), + 3 => Some(Message::BlockData(Decode::decode(input)?, Decode::decode(input)?)), + 4 => Some(Message::CollatorRole(Decode::decode(input)?)), + 5 => Some(Message::Collation(Decode::decode(input)?, Decode::decode(input)?)), + _ => None, + } + } +} + +fn send_polkadot_message(ctx: &mut Context, to: NodeIndex, message: Message) { + trace!(target: "p_net", "Sending polkadot message to {}: {:?}", to, message); + let encoded = message.encode(); + ctx.send_message(to, generic_message::Message::ChainSpecific(encoded)) +} + +/// Polkadot protocol attachment for substrate. +pub struct PolkadotProtocol { + peers: HashMap, + collating_for: Option<(AccountId, ParaId)>, + consensus_gossip: ConsensusGossip, + collators: CollatorPool, + validators: HashMap, + local_collations: LocalCollations, + live_consensus: Option, + in_flight: HashMap<(RequestId, NodeIndex), BlockDataRequest>, + pending: Vec, + next_req_id: u64, +} + +impl PolkadotProtocol { + /// Instantiate a polkadot protocol handler. + pub fn new(collating_for: Option<(AccountId, ParaId)>) -> Self { + PolkadotProtocol { + peers: HashMap::new(), + consensus_gossip: ConsensusGossip::new(), + collators: CollatorPool::new(), + collating_for, + validators: HashMap::new(), + local_collations: LocalCollations::new(), + live_consensus: None, + in_flight: HashMap::new(), + pending: Vec::new(), + next_req_id: 1, + } + } + + /// Send a statement to a validator. + fn send_statement(&mut self, ctx: &mut Context, _val: SessionKey, parent_hash: Hash, statement: SignedStatement) { + // TODO: something more targeted than gossip. + let raw = Message::Statement(parent_hash, statement).encode(); + self.consensus_gossip.multicast_chain_specific(ctx, raw, parent_hash); + } + + /// Fetch block data by candidate receipt. + fn fetch_block_data(&mut self, ctx: &mut Context, candidate: &CandidateReceipt, relay_parent: Hash) -> oneshot::Receiver { + let (tx, rx) = oneshot::channel(); + + self.pending.push(BlockDataRequest { + attempted_peers: Default::default(), + consensus_parent: relay_parent, + candidate_hash: candidate.hash(), + block_data_hash: candidate.block_data_hash, + sender: tx, + }); + + self.dispatch_pending_requests(ctx); + rx + } + + /// Note new consensus session. + fn new_consensus(&mut self, ctx: &mut Context, consensus: CurrentConsensus) { + let old_data = self.live_consensus.as_ref().map(|c| (c.parent_hash, c.local_session_key)); + + if Some(&consensus.local_session_key) != old_data.as_ref().map(|&(_, ref key)| key) { + for (id, _) in self.peers.iter() + .filter(|&(_, ref info)| info.claimed_validator || info.collating_for.is_some()) + { + send_polkadot_message( + ctx, + *id, + Message::SessionKey(consensus.local_session_key) + ); + } + } + + self.live_consensus = Some(consensus); + self.consensus_gossip.collect_garbage(old_data.as_ref().map(|&(ref hash, _)| hash)); + } + + fn dispatch_pending_requests(&mut self, ctx: &mut Context) { + let consensus = match self.live_consensus { + Some(ref mut c) => c, + None => { + self.pending.clear(); + return; + } + }; + + let knowledge = consensus.knowledge.lock(); + let mut new_pending = Vec::new(); + for mut pending in ::std::mem::replace(&mut self.pending, Vec::new()) { + if pending.consensus_parent != consensus.parent_hash { continue } + + if let Some(entry) = knowledge.candidates.get(&pending.candidate_hash) { + // answer locally + if let Some(ref data) = entry.block_data { + let _ = pending.sender.send(data.clone()); + continue; + } + + let validator_keys = &mut self.validators; + let next_peer = entry.knows_block_data.iter() + .filter_map(|x| validator_keys.get(x).map(|id| (*x, *id))) + .find(|&(ref key, _)| pending.attempted_peers.insert(*key)) + .map(|(_, id)| id); + + // dispatch to peer + if let Some(who) = next_peer { + let req_id = self.next_req_id; + self.next_req_id += 1; + + send_polkadot_message( + ctx, + who, + Message::RequestBlockData(req_id, pending.candidate_hash) + ); + + self.in_flight.insert((req_id, who), pending); + + continue; + } + } + + new_pending.push(pending); + } + + self.pending = new_pending; + } + + fn on_polkadot_message(&mut self, ctx: &mut Context, who: NodeIndex, raw: Vec, msg: Message) { + trace!(target: "p_net", "Polkadot message from {}: {:?}", who, msg); + match msg { + Message::Statement(parent_hash, _statement) => + self.consensus_gossip.on_chain_specific(ctx, who, raw, parent_hash), + Message::SessionKey(key) => self.on_session_key(ctx, who, key), + Message::RequestBlockData(req_id, hash) => { + let block_data = self.live_consensus.as_ref() + .and_then(|c| c.block_data(&hash)); + + send_polkadot_message(ctx, who, Message::BlockData(req_id, block_data)); + } + Message::BlockData(req_id, data) => self.on_block_data(ctx, who, req_id, data), + Message::Collation(relay_parent, collation) => self.on_collation(ctx, who, relay_parent, collation), + Message::CollatorRole(role) => self.on_new_role(ctx, who, role), + } + } + + fn on_session_key(&mut self, ctx: &mut Context, who: NodeIndex, key: SessionKey) { + { + let info = match self.peers.get_mut(&who) { + Some(peer) => peer, + None => { + trace!(target: "p_net", "Network inconsistency: message received from unconnected peer {}", who); + return + } + }; + + if !info.claimed_validator { + ctx.report_peer(who, Severity::Bad("Session key broadcasted without setting authority role")); + return; + } + + if let Some(old_key) = ::std::mem::replace(&mut info.validator_key, Some(key)) { + self.validators.remove(&old_key); + + for (relay_parent, collation) in self.local_collations.fresh_key(&old_key, &key) { + send_polkadot_message( + ctx, + who, + Message::Collation(relay_parent, collation), + ) + } + + } + self.validators.insert(key, who); + } + + self.dispatch_pending_requests(ctx); + } + + fn on_block_data(&mut self, ctx: &mut Context, who: NodeIndex, req_id: RequestId, data: Option) { + match self.in_flight.remove(&(req_id, who)) { + Some(req) => { + if let Some(data) = data { + if data.hash() == req.block_data_hash { + let _ = req.sender.send(data); + return + } + } + + self.pending.push(req); + self.dispatch_pending_requests(ctx); + } + None => ctx.report_peer(who, Severity::Bad("Unexpected block data response")), + } + } + + // when a validator sends us (a collator) a new role. + fn on_new_role(&mut self, ctx: &mut Context, who: NodeIndex, role: Role) { + let info = match self.peers.get(&who) { + Some(peer) => peer, + None => { + trace!(target: "p_net", "Network inconsistency: message received from unconnected peer {}", who); + return + } + }; + + match info.validator_key { + None => ctx.report_peer( + who, + Severity::Bad("Sent collator role without registering first as validator"), + ), + Some(key) => for (relay_parent, collation) in self.local_collations.note_validator_role(key, role) { + send_polkadot_message( + ctx, + who, + Message::Collation(relay_parent, collation), + ) + }, + } + } +} + +impl Specialization for PolkadotProtocol { + fn status(&self) -> Vec { + Status { collating_for: self.collating_for.clone() }.encode() + } + + fn on_connect(&mut self, ctx: &mut Context, who: NodeIndex, status: FullStatus) { + let local_status = match Status::decode(&mut &status.chain_status[..]) { + Some(status) => status, + None => { + Status { collating_for: None } + } + }; + + if let Some((ref acc_id, ref para_id)) = local_status.collating_for { + if self.collator_peer_id(acc_id.clone()).is_some() { + ctx.report_peer(who, Severity::Useless("Unknown Polkadot-specific reason")); + return + } + + let collator_role = self.collators.on_new_collator(acc_id.clone(), para_id.clone()); + send_polkadot_message( + ctx, + who, + Message::CollatorRole(collator_role), + ); + } + + let validator = status.roles.contains(substrate_network::Roles::AUTHORITY); + let send_key = validator || local_status.collating_for.is_some(); + + self.peers.insert(who, PeerInfo { + collating_for: local_status.collating_for, + validator_key: None, + claimed_validator: validator, + }); + + self.consensus_gossip.new_peer(ctx, who, status.roles); + if let (true, &Some(ref consensus)) = (send_key, &self.live_consensus) { + send_polkadot_message( + ctx, + who, + Message::SessionKey(consensus.local_session_key) + ); + } + + self.dispatch_pending_requests(ctx); + } + + fn on_disconnect(&mut self, ctx: &mut Context, who: NodeIndex) { + if let Some(info) = self.peers.remove(&who) { + if let Some((acc_id, _)) = info.collating_for { + let new_primary = self.collators.on_disconnect(acc_id) + .and_then(|new_primary| self.collator_peer_id(new_primary)); + + if let Some(new_primary) = new_primary { + send_polkadot_message( + ctx, + new_primary, + Message::CollatorRole(Role::Primary), + ) + } + } + + if let Some(validator_key) = info.validator_key { + self.validators.remove(&validator_key); + self.local_collations.on_disconnect(&validator_key); + } + + { + let pending = &mut self.pending; + self.in_flight.retain(|&(_, ref peer), val| { + let retain = peer != &who; + if !retain { + let (sender, _) = oneshot::channel(); + pending.push(::std::mem::replace(val, BlockDataRequest { + attempted_peers: Default::default(), + consensus_parent: Default::default(), + candidate_hash: Default::default(), + block_data_hash: Default::default(), + sender, + })); + } + + retain + }); + } + self.consensus_gossip.peer_disconnected(ctx, who); + self.dispatch_pending_requests(ctx); + } + } + + fn on_message(&mut self, ctx: &mut Context, who: NodeIndex, message: message::Message) { + match message { + generic_message::Message::BftMessage(msg) => { + trace!(target: "p_net", "Polkadot BFT message from {}: {:?}", who, msg); + // TODO: check signature here? what if relevant block is unknown? + self.consensus_gossip.on_bft_message(ctx, who, msg) + } + generic_message::Message::ChainSpecific(raw) => { + match Message::decode(&mut raw.as_slice()) { + Some(msg) => self.on_polkadot_message(ctx, who, raw, msg), + None => { + trace!(target: "p_net", "Bad message from {}", who); + ctx.report_peer(who, Severity::Bad("Invalid polkadot protocol message format")); + } + } + } + _ => {} + } + } + + fn on_abort(&mut self) { + self.consensus_gossip.abort(); + } + + fn maintain_peers(&mut self, ctx: &mut Context) { + self.consensus_gossip.collect_garbage(None); + self.collators.collect_garbage(None); + self.local_collations.collect_garbage(None); + self.dispatch_pending_requests(ctx); + + for collator_action in self.collators.maintain_peers() { + match collator_action { + Action::Disconnect(collator) => self.disconnect_bad_collator(ctx, collator), + Action::NewRole(account_id, role) => if let Some(collator) = self.collator_peer_id(account_id) { + send_polkadot_message( + ctx, + collator, + Message::CollatorRole(role), + ) + }, + } + } + } + + fn on_block_imported(&mut self, _ctx: &mut Context, hash: Hash, header: &Header) { + self.collators.collect_garbage(Some(&hash)); + self.local_collations.collect_garbage(Some(&header.parent_hash)); + } +} + +impl PolkadotProtocol { + // we received a collation from a peer + fn on_collation(&mut self, ctx: &mut Context, from: NodeIndex, relay_parent: Hash, collation: Collation) { + let collation_para = collation.receipt.parachain_index; + let collated_acc = collation.receipt.collator; + + match self.peers.get(&from) { + None => ctx.report_peer(from, Severity::Useless("Unknown Polkadot specific reason")), + Some(peer_info) => match peer_info.collating_for { + None => ctx.report_peer(from, Severity::Bad("Sent collation without registering collator intent")), + Some((ref acc_id, ref para_id)) => { + let structurally_valid = para_id == &collation_para && acc_id == &collated_acc; + if structurally_valid && collation.receipt.check_signature().is_ok() { + self.collators.on_collation(acc_id.clone(), relay_parent, collation) + } else { + ctx.report_peer(from, Severity::Bad("Sent malformed collation")) + }; + } + }, + } + } + + fn await_collation(&mut self, relay_parent: Hash, para_id: ParaId) -> oneshot::Receiver { + let (tx, rx) = oneshot::channel(); + self.collators.await_collation(relay_parent, para_id, tx); + rx + } + + // get connected peer with given account ID for collation. + fn collator_peer_id(&self, account_id: AccountId) -> Option { + let check_info = |info: &PeerInfo| info + .collating_for + .as_ref() + .map_or(false, |&(ref acc_id, _)| acc_id == &account_id); + + self.peers + .iter() + .filter(|&(_, info)| check_info(info)) + .map(|(who, _)| *who) + .next() + } + + // disconnect a collator by account-id. + fn disconnect_bad_collator(&self, ctx: &mut Context, account_id: AccountId) { + if let Some(who) = self.collator_peer_id(account_id) { + ctx.report_peer(who, Severity::Bad("Consensus layer determined the given collator misbehaved")) + } + } +} + +impl PolkadotProtocol { + /// Add a local collation and broadcast it to the necessary peers. + pub fn add_local_collation( + &mut self, + ctx: &mut Context, + relay_parent: Hash, + targets: HashSet, + collation: Collation, + ) { + for (primary, cloned_collation) in self.local_collations.add_collation(relay_parent, targets, collation.clone()) { + match self.validators.get(&primary) { + Some(who) => send_polkadot_message( + ctx, + *who, + Message::Collation(relay_parent, cloned_collation), + ), + None => + warn!(target: "polkadot_network", "Encountered tracked but disconnected validator {:?}", primary), + } + } + } +} diff --git a/polkadot/network/src/local_collations.rs b/polkadot/network/src/local_collations.rs new file mode 100644 index 0000000000000..2902ed5f0e710 --- /dev/null +++ b/polkadot/network/src/local_collations.rs @@ -0,0 +1,199 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Local collations to be circulated to validators. +//! +//! Collations are attempted to be repropagated when a new validator connects, +//! a validator changes his session key, or when they are generated. + +use polkadot_primitives::{Hash, SessionKey}; + +use collator_pool::Role; + +use std::collections::{HashMap, HashSet}; +use std::time::{Duration, Instant}; + +const LIVE_FOR: Duration = Duration::from_secs(60 * 5); + +struct LocalCollation { + targets: HashSet, + collation: C, + live_since: Instant, +} + +/// Tracker for locally collated values and which validators to send them to. +pub struct LocalCollations { + primary_for: HashSet, + local_collations: HashMap>, +} + +impl LocalCollations { + /// Create a new `LocalCollations` tracker. + pub fn new() -> Self { + LocalCollations { + primary_for: HashSet::new(), + local_collations: HashMap::new(), + } + } + + /// Validator gave us a new role. If the new role is "primary", this function might return + /// a set of collations to send to that validator. + pub fn note_validator_role(&mut self, key: SessionKey, role: Role) -> Vec<(Hash, C)> { + match role { + Role::Backup => { + self.primary_for.remove(&key); + Vec::new() + } + Role::Primary => { + let new_primary = self.primary_for.insert(key); + if new_primary { + self.collations_targeting(&key) + } else { + Vec::new() + } + } + } + } + + /// Fresh session key from a validator. Returns a vector of collations to send + /// to the validator. + pub fn fresh_key(&mut self, old_key: &SessionKey, new_key: &SessionKey) -> Vec<(Hash, C)> { + if self.primary_for.remove(old_key) { + self.primary_for.insert(*new_key); + + self.collations_targeting(new_key) + } else { + Vec::new() + } + } + + /// Validator disconnected. + pub fn on_disconnect(&mut self, key: &SessionKey) { + self.primary_for.remove(key); + } + + /// Mark collations relevant to the given parent hash as obsolete. + pub fn collect_garbage(&mut self, relay_parent: Option<&Hash>) { + if let Some(relay_parent) = relay_parent { + self.local_collations.remove(relay_parent); + } + + let now = Instant::now(); + self.local_collations.retain(|_, v| v.live_since + LIVE_FOR > now); + } + + /// Add a collation. Returns an iterator of session keys to send to and lazy copies of the collation. + pub fn add_collation<'a>( + &'a mut self, + relay_parent: Hash, + targets: HashSet, + collation: C + ) + -> impl Iterator + 'a + { + self.local_collations.insert(relay_parent, LocalCollation { + targets, + collation, + live_since: Instant::now(), + }); + + let local = self.local_collations.get(&relay_parent) + .expect("just inserted to this key; qed"); + + let borrowed_collation = &local.collation; + local.targets + .intersection(&self.primary_for) + .map(move |k| (*k, borrowed_collation.clone())) + } + + fn collations_targeting(&self, key: &SessionKey) -> Vec<(Hash, C)> { + self.local_collations.iter() + .filter(|&(_, ref v)| v.targets.contains(key)) + .map(|(h, v)| (*h, v.collation.clone())) + .collect() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn add_validator_with_ready_collation() { + let key = [1; 32].into(); + let relay_parent = [2; 32].into(); + let targets = { + let mut set = HashSet::new(); + set.insert(key); + set + }; + + let mut tracker = LocalCollations::new(); + assert!(tracker.add_collation(relay_parent, targets, 5).next().is_none()); + assert_eq!(tracker.note_validator_role(key, Role::Primary), vec![(relay_parent, 5)]); + } + + #[test] + fn rename_with_ready() { + let orig_key = [1; 32].into(); + let new_key = [2; 32].into(); + let relay_parent = [255; 32].into(); + let targets = { + let mut set = HashSet::new(); + set.insert(new_key); + set + }; + + let mut tracker: LocalCollations = LocalCollations::new(); + assert!(tracker.add_collation(relay_parent, targets, 5).next().is_none()); + assert!(tracker.note_validator_role(orig_key, Role::Primary).is_empty()); + assert_eq!(tracker.fresh_key(&orig_key, &new_key), vec![(relay_parent, 5u8)]); + } + + #[test] + fn collecting_garbage() { + let relay_parent_a = [255; 32].into(); + let relay_parent_b = [222; 32].into(); + + let mut tracker: LocalCollations = LocalCollations::new(); + assert!(tracker.add_collation(relay_parent_a, HashSet::new(), 5).next().is_none()); + assert!(tracker.add_collation(relay_parent_b, HashSet::new(), 69).next().is_none()); + + let live_since = Instant::now() - LIVE_FOR - Duration::from_secs(10); + tracker.local_collations.get_mut(&relay_parent_b).unwrap().live_since = live_since; + + tracker.collect_garbage(Some(&relay_parent_a)); + + // first one pruned because of relay parent, other because of time. + assert!(tracker.local_collations.is_empty()); + } + + #[test] + fn add_collation_with_connected_target() { + let key = [1; 32].into(); + let relay_parent = [2; 32].into(); + let targets = { + let mut set = HashSet::new(); + set.insert(key); + set + }; + + let mut tracker = LocalCollations::new(); + assert!(tracker.note_validator_role(key, Role::Primary).is_empty()); + assert_eq!(tracker.add_collation(relay_parent, targets, 5).next(), Some((key, 5))); + + } +} diff --git a/polkadot/network/src/router.rs b/polkadot/network/src/router.rs new file mode 100644 index 0000000000000..ff90502a31a24 --- /dev/null +++ b/polkadot/network/src/router.rs @@ -0,0 +1,349 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Statement routing and consensus table router implementation. +//! +//! During the consensus process, validators exchange statements on validity and availability +//! of parachain candidates. +//! The `Router` in this file hooks into the underlying network to fulfill +//! the `TableRouter` trait from `polkadot-consensus`, which is expected to call into a shared statement table +//! and dispatch evaluation work as necessary when new statements come in. + +use polkadot_api::{PolkadotApi, LocalPolkadotApi}; +use polkadot_consensus::{SharedTable, TableRouter, SignedStatement, GenericStatement, StatementProducer}; +use polkadot_primitives::{Hash, BlockId, SessionKey}; +use polkadot_primitives::parachain::{BlockData, Extrinsic, CandidateReceipt, Id as ParaId}; + +use futures::prelude::*; +use tokio::runtime::TaskExecutor; +use parking_lot::Mutex; + +use std::collections::{HashMap, HashSet}; +use std::sync::Arc; + +use super::{NetworkService, Knowledge}; + +/// Table routing implementation. +pub struct Router { + table: Arc, + network: Arc, + api: Arc

, + task_executor: TaskExecutor, + parent_hash: Hash, + knowledge: Arc>, + deferred_statements: Arc>, +} + +impl Router

{ + pub(crate) fn new( + table: Arc, + network: Arc, + api: Arc

, + task_executor: TaskExecutor, + parent_hash: Hash, + knowledge: Arc>, + ) -> Self { + Router { + table, + network, + api, + task_executor, + parent_hash, + knowledge, + deferred_statements: Arc::new(Mutex::new(DeferredStatements::new())), + } + } + + pub(crate) fn session_key(&self) -> SessionKey { + self.table.session_key() + } +} + +impl Clone for Router

{ + fn clone(&self) -> Self { + Router { + table: self.table.clone(), + network: self.network.clone(), + api: self.api.clone(), + task_executor: self.task_executor.clone(), + parent_hash: self.parent_hash.clone(), + deferred_statements: self.deferred_statements.clone(), + knowledge: self.knowledge.clone(), + } + } +} + +impl Router

{ + /// Import a statement whose signature has been checked already. + pub(crate) fn import_statement(&self, statement: SignedStatement) { + // defer any statements for which we haven't imported the candidate yet + let (c_hash, parachain_index) = { + let candidate_data = match statement.statement { + GenericStatement::Candidate(ref c) => Some((c.hash(), c.parachain_index)), + GenericStatement::Valid(ref hash) + | GenericStatement::Invalid(ref hash) + | GenericStatement::Available(ref hash) + => self.table.with_candidate(hash, |c| c.map(|c| (*hash, c.parachain_index))), + }; + match candidate_data { + Some(x) => x, + None => { + self.deferred_statements.lock().push(statement); + return; + } + } + }; + + // import all statements pending on this candidate + let (mut statements, _traces) = if let GenericStatement::Candidate(_) = statement.statement { + self.deferred_statements.lock().get_deferred(&c_hash) + } else { + (Vec::new(), Vec::new()) + }; + + // prepend the candidate statement. + statements.insert(0, statement); + let producers: Vec<_> = self.table.import_remote_statements( + self, + statements.iter().cloned(), + ); + // dispatch future work as necessary. + for (producer, statement) in producers.into_iter().zip(statements) { + let producer = match producer { + Some(p) => p, + None => continue, // statement redundant + }; + + self.knowledge.lock().note_statement(statement.sender, &statement.statement); + self.dispatch_work(c_hash, producer, parachain_index); + } + } + + fn dispatch_work(&self, candidate_hash: Hash, producer: StatementProducer, parachain: ParaId) where + D: Future + Send + 'static, + E: Future + Send + 'static, + { + let parent_hash = self.parent_hash.clone(); + + let api = self.api.clone(); + let validate = move |collation| -> Option { + let id = BlockId::hash(parent_hash); + match ::polkadot_consensus::validate_collation(&*api, &id, &collation) { + Ok(()) => Some(true), + Err(e) => { + debug!(target: "p_net", "Encountered bad collation: {}", e); + Some(false) + } + } + }; + + let table = self.table.clone(); + let network = self.network.clone(); + let knowledge = self.knowledge.clone(); + + let work = producer.prime(validate).map(move |produced| { + // store the data before broadcasting statements, so other peers can fetch. + knowledge.lock().note_candidate(candidate_hash, produced.block_data, produced.extrinsic); + + // propagate the statements + if let Some(validity) = produced.validity { + let signed = table.sign_and_import(validity.clone()); + route_statement(&*network, &*table, parachain, parent_hash, signed); + } + + if let Some(availability) = produced.availability { + let signed = table.sign_and_import(availability); + route_statement(&*network, &*table, parachain, parent_hash, signed); + } + }); + + self.task_executor.spawn(work); + } +} + +impl TableRouter for Router

{ + type Error = (); + type FetchCandidate = BlockDataReceiver; + type FetchExtrinsic = Result; + + fn local_candidate(&self, receipt: CandidateReceipt, block_data: BlockData, extrinsic: Extrinsic) { + // give to network to make available. + let hash = receipt.hash(); + let para_id = receipt.parachain_index; + let signed = self.table.sign_and_import(GenericStatement::Candidate(receipt)); + + self.knowledge.lock().note_candidate(hash, Some(block_data), Some(extrinsic)); + route_statement(&*self.network, &*self.table, para_id, self.parent_hash, signed); + } + + fn fetch_block_data(&self, candidate: &CandidateReceipt) -> BlockDataReceiver { + let parent_hash = self.parent_hash; + let rx = self.network.with_spec(|spec, ctx| { spec.fetch_block_data(ctx, candidate, parent_hash) }); + BlockDataReceiver { inner: rx } + } + + fn fetch_extrinsic_data(&self, _candidate: &CandidateReceipt) -> Self::FetchExtrinsic { + Ok(Extrinsic) + } +} + +/// Receiver for block data. +pub struct BlockDataReceiver { + inner: Option<::futures::sync::oneshot::Receiver>, +} + +impl Future for BlockDataReceiver { + type Item = BlockData; + type Error = (); + + fn poll(&mut self) -> Poll { + match self.inner { + Some(ref mut inner) => inner.poll().map_err(|_| ()), + None => return Err(()), + } + } +} + +// get statement to relevant validators. +fn route_statement(network: &NetworkService, table: &SharedTable, para_id: ParaId, parent_hash: Hash, statement: SignedStatement) { + let broadcast = |i: &mut Iterator| { + let local_key = table.session_key(); + network.with_spec(|spec, ctx| { + for val in i.filter(|&x| x != &local_key) { + spec.send_statement(ctx, *val, parent_hash, statement.clone()); + } + }); + }; + + let g_info = table + .group_info() + .get(¶_id) + .expect("statements only produced about groups which exist"); + + match statement.statement { + GenericStatement::Candidate(_) => + broadcast(&mut g_info.validity_guarantors.iter().chain(g_info.availability_guarantors.iter())), + GenericStatement::Valid(_) | GenericStatement::Invalid(_) => + broadcast(&mut g_info.validity_guarantors.iter()), + GenericStatement::Available(_) => + broadcast(&mut g_info.availability_guarantors.iter()), + } +} + +// A unique trace for valid statements issued by a validator. +#[derive(Hash, PartialEq, Eq, Clone, Debug)] +enum StatementTrace { + Valid(SessionKey, Hash), + Invalid(SessionKey, Hash), + Available(SessionKey, Hash), +} + +// helper for deferring statements whose associated candidate is unknown. +struct DeferredStatements { + deferred: HashMap>, + known_traces: HashSet, +} + +impl DeferredStatements { + fn new() -> Self { + DeferredStatements { + deferred: HashMap::new(), + known_traces: HashSet::new(), + } + } + + fn push(&mut self, statement: SignedStatement) { + let (hash, trace) = match statement.statement { + GenericStatement::Candidate(_) => return, + GenericStatement::Valid(hash) => (hash, StatementTrace::Valid(statement.sender, hash)), + GenericStatement::Invalid(hash) => (hash, StatementTrace::Invalid(statement.sender, hash)), + GenericStatement::Available(hash) => (hash, StatementTrace::Available(statement.sender, hash)), + }; + + if self.known_traces.insert(trace) { + self.deferred.entry(hash).or_insert_with(Vec::new).push(statement); + } + } + + fn get_deferred(&mut self, hash: &Hash) -> (Vec, Vec) { + match self.deferred.remove(hash) { + None => (Vec::new(), Vec::new()), + Some(deferred) => { + let mut traces = Vec::new(); + for statement in deferred.iter() { + let trace = match statement.statement { + GenericStatement::Candidate(_) => continue, + GenericStatement::Valid(hash) => StatementTrace::Valid(statement.sender, hash), + GenericStatement::Invalid(hash) => StatementTrace::Invalid(statement.sender, hash), + GenericStatement::Available(hash) => StatementTrace::Available(statement.sender, hash), + }; + + self.known_traces.remove(&trace); + traces.push(trace); + } + + (deferred, traces) + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use substrate_primitives::H512; + + #[test] + fn deferred_statements_works() { + let mut deferred = DeferredStatements::new(); + let hash = [1; 32].into(); + let sig = H512([2; 64]).into(); + let sender = [255; 32].into(); + + let statement = SignedStatement { + statement: GenericStatement::Valid(hash), + sender, + signature: sig, + }; + + // pre-push. + { + let (signed, traces) = deferred.get_deferred(&hash); + assert!(signed.is_empty()); + assert!(traces.is_empty()); + } + + deferred.push(statement.clone()); + deferred.push(statement.clone()); + + // draining: second push should have been ignored. + { + let (signed, traces) = deferred.get_deferred(&hash); + assert_eq!(signed.len(), 1); + + assert_eq!(traces.len(), 1); + assert_eq!(signed[0].clone(), statement); + assert_eq!(traces[0].clone(), StatementTrace::Valid(sender, hash)); + } + + // after draining + { + let (signed, traces) = deferred.get_deferred(&hash); + assert!(signed.is_empty()); + assert!(traces.is_empty()); + } + } +} diff --git a/polkadot/network/src/tests.rs b/polkadot/network/src/tests.rs new file mode 100644 index 0000000000000..356d272e3f610 --- /dev/null +++ b/polkadot/network/src/tests.rs @@ -0,0 +1,227 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Tests for polkadot and consensus network. + +use super::{PolkadotProtocol, Status, CurrentConsensus, Knowledge, Message, FullStatus}; + +use parking_lot::Mutex; +use polkadot_consensus::GenericStatement; +use polkadot_primitives::{Block, Hash, SessionKey}; +use polkadot_primitives::parachain::{CandidateReceipt, HeadData, BlockData}; +use substrate_primitives::H512; +use codec::Encode; +use substrate_network::{Severity, NodeIndex, PeerInfo, ClientHandle, Context, Roles, message::Message as SubstrateMessage, specialization::Specialization, generic_message::Message as GenericMessage}; + +use std::sync::Arc; +use futures::Future; + +#[derive(Default)] +struct TestContext { + disabled: Vec, + disconnected: Vec, + messages: Vec<(NodeIndex, SubstrateMessage)>, +} + +impl Context for TestContext { + fn client(&self) -> &ClientHandle { + unimplemented!() + } + + fn report_peer(&mut self, peer: NodeIndex, reason: Severity) { + match reason { + Severity::Bad(_) => self.disabled.push(peer), + _ => self.disconnected.push(peer), + } + } + + fn peer_info(&self, _peer: NodeIndex) -> Option> { + unimplemented!() + } + + fn send_message(&mut self, who: NodeIndex, data: SubstrateMessage) { + self.messages.push((who, data)) + } +} + +impl TestContext { + fn has_message(&self, to: NodeIndex, message: Message) -> bool { + use substrate_network::generic_message::Message as GenericMessage; + + let encoded = message.encode(); + self.messages.iter().any(|&(ref peer, ref msg)| match msg { + GenericMessage::ChainSpecific(ref data) => peer == &to && data == &encoded, + _ => false, + }) + } +} + +fn make_status(status: &Status, roles: Roles) -> FullStatus { + FullStatus { + version: 1, + roles, + best_number: 0, + best_hash: Default::default(), + genesis_hash: Default::default(), + chain_status: status.encode(), + } +} + +fn make_consensus(parent_hash: Hash, local_key: SessionKey) -> (CurrentConsensus, Arc>) { + let knowledge = Arc::new(Mutex::new(Knowledge::new())); + let c = CurrentConsensus { + knowledge: knowledge.clone(), + parent_hash, + local_session_key: local_key, + }; + + (c, knowledge) +} + +fn on_message(protocol: &mut PolkadotProtocol, ctx: &mut TestContext, from: NodeIndex, message: Message) { + let encoded = message.encode(); + protocol.on_message(ctx, from, GenericMessage::ChainSpecific(encoded)); +} + +#[test] +fn sends_session_key() { + let mut protocol = PolkadotProtocol::new(None); + + let peer_a = 1; + let peer_b = 2; + let parent_hash = [0; 32].into(); + let local_key = [1; 32].into(); + + let validator_status = Status { collating_for: None }; + let collator_status = Status { collating_for: Some(([2; 32].into(), 5.into())) }; + + { + let mut ctx = TestContext::default(); + protocol.on_connect(&mut ctx, peer_a, make_status(&validator_status, Roles::AUTHORITY)); + assert!(ctx.messages.is_empty()); + } + + { + let mut ctx = TestContext::default(); + let (consensus, _knowledge) = make_consensus(parent_hash, local_key); + protocol.new_consensus(&mut ctx, consensus); + assert!(ctx.has_message(peer_a, Message::SessionKey(local_key))); + } + + { + let mut ctx = TestContext::default(); + protocol.on_connect(&mut ctx, peer_b, make_status(&collator_status, Roles::NONE)); + assert!(ctx.has_message(peer_b, Message::SessionKey(local_key))); + } +} + +#[test] +fn fetches_from_those_with_knowledge() { + let mut protocol = PolkadotProtocol::new(None); + + let peer_a = 1; + let peer_b = 2; + let parent_hash = [0; 32].into(); + let local_key = [1; 32].into(); + + let block_data = BlockData(vec![1, 2, 3, 4]); + let block_data_hash = block_data.hash(); + let candidate_receipt = CandidateReceipt { + parachain_index: 5.into(), + collator: [255; 32].into(), + head_data: HeadData(vec![9, 9, 9]), + signature: H512::from([1; 64]).into(), + balance_uploads: Vec::new(), + egress_queue_roots: Vec::new(), + fees: 1_000_000, + block_data_hash, + }; + + let candidate_hash = candidate_receipt.hash(); + let a_key = [3; 32].into(); + let b_key = [4; 32].into(); + + let status = Status { collating_for: None }; + + let (consensus, knowledge) = make_consensus(parent_hash, local_key); + protocol.new_consensus(&mut TestContext::default(), consensus); + + knowledge.lock().note_statement(a_key, &GenericStatement::Valid(candidate_hash)); + let recv = protocol.fetch_block_data(&mut TestContext::default(), &candidate_receipt, parent_hash); + + // connect peer A + { + let mut ctx = TestContext::default(); + protocol.on_connect(&mut ctx, peer_a, make_status(&status, Roles::AUTHORITY)); + assert!(ctx.has_message(peer_a, Message::SessionKey(local_key))); + } + + // peer A gives session key and gets asked for data. + { + let mut ctx = TestContext::default(); + on_message(&mut protocol, &mut ctx, peer_a, Message::SessionKey(a_key)); + assert!(protocol.validators.contains_key(&a_key)); + assert!(ctx.has_message(peer_a, Message::RequestBlockData(1, candidate_hash))); + } + + knowledge.lock().note_statement(b_key, &GenericStatement::Valid(candidate_hash)); + + // peer B connects and sends session key. request already assigned to A + { + let mut ctx = TestContext::default(); + protocol.on_connect(&mut ctx, peer_b, make_status(&status, Roles::AUTHORITY)); + on_message(&mut protocol, &mut ctx, peer_b, Message::SessionKey(b_key)); + assert!(!ctx.has_message(peer_b, Message::RequestBlockData(2, candidate_hash))); + + } + + // peer A disconnects, triggering reassignment + { + let mut ctx = TestContext::default(); + protocol.on_disconnect(&mut ctx, peer_a); + assert!(!protocol.validators.contains_key(&a_key)); + assert!(ctx.has_message(peer_b, Message::RequestBlockData(2, candidate_hash))); + } + + // peer B comes back with block data. + { + let mut ctx = TestContext::default(); + on_message(&mut protocol, &mut ctx, peer_b, Message::BlockData(2, Some(block_data.clone()))); + drop(protocol); + assert_eq!(recv.wait().unwrap(), block_data); + } +} + +#[test] +fn remove_bad_collator() { + let mut protocol = PolkadotProtocol::new(None); + + let who = 1; + let account_id = [2; 32].into(); + + let status = Status { collating_for: Some((account_id, 5.into())) }; + + { + let mut ctx = TestContext::default(); + protocol.on_connect(&mut ctx, who, make_status(&status, Roles::NONE)); + } + + { + let mut ctx = TestContext::default(); + protocol.disconnect_bad_collator(&mut ctx, account_id); + assert!(ctx.disabled.contains(&who)); + } +} diff --git a/polkadot/parachain/Cargo.toml b/polkadot/parachain/Cargo.toml index 47cde571e1567..2b1eeca7e5611 100644 --- a/polkadot/parachain/Cargo.toml +++ b/polkadot/parachain/Cargo.toml @@ -6,8 +6,8 @@ description = "Types and utilities for creating and working with parachains" [dependencies] substrate-codec = { path = "../../substrate/codec", default-features = false } -wasmi = { version = "0.1", optional = true } -error-chain = { version = "0.11", optional = true } +wasmi = { version = "0.3", optional = true } +error-chain = { version = "0.12", optional = true } [dev-dependencies] tiny-keccak = "1.4" diff --git a/polkadot/parachain/README.adoc b/polkadot/parachain/README.adoc new file mode 100644 index 0000000000000..fbce59a188f42 --- /dev/null +++ b/polkadot/parachain/README.adoc @@ -0,0 +1,5 @@ + += Polkadot Parachain + +placeholder +//TODO Write content :) diff --git a/polkadot/parachain/src/lib.rs b/polkadot/parachain/src/lib.rs index 2f3c064f33f36..7af248fdbeaa4 100644 --- a/polkadot/parachain/src/lib.rs +++ b/polkadot/parachain/src/lib.rs @@ -61,7 +61,7 @@ extern crate error_chain; #[cfg(not(feature = "std"))] use alloc::vec::Vec; -use codec::Slicable; +use codec::{Encode, Decode, Input, Output}; #[cfg(feature = "std")] pub mod wasm; @@ -77,20 +77,18 @@ pub struct ValidationParams { pub parent_head: Vec, } -impl Slicable for ValidationParams { - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - self.block_data.using_encoded(|s| v.extend(s)); - self.parent_head.using_encoded(|s| v.extend(s)); - - v +impl Encode for ValidationParams { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.block_data); + dest.push(&self.parent_head); } +} - fn decode(input: &mut I) -> Option { +impl Decode for ValidationParams { + fn decode(input: &mut I) -> Option { Some(ValidationParams { - block_data: Slicable::decode(input)?, - parent_head: Slicable::decode(input)?, + block_data: Decode::decode(input)?, + parent_head: Decode::decode(input)?, }) } } @@ -104,14 +102,16 @@ pub struct ValidationResult { pub head_data: Vec } -impl Slicable for ValidationResult { - fn encode(&self) -> Vec { - self.head_data.encode() +impl Encode for ValidationResult { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.head_data); } +} - fn decode(input: &mut I) -> Option { +impl Decode for ValidationResult { + fn decode(input: &mut I) -> Option { Some(ValidationResult { - head_data: Slicable::decode(input)?, + head_data: Decode::decode(input)?, }) } } diff --git a/polkadot/parachain/src/wasm.rs b/polkadot/parachain/src/wasm.rs index a16383acb908b..494f176a3de56 100644 --- a/polkadot/parachain/src/wasm.rs +++ b/polkadot/parachain/src/wasm.rs @@ -20,7 +20,7 @@ //! Assuming the parameters are correct, this module provides a wrapper around //! a WASM VM for re-execution of a parachain candidate. -use codec::Slicable; +use codec::{Decode, Encode}; use wasmi::{self, Module, ModuleInstance, MemoryInstance, MemoryDescriptor, MemoryRef, ModuleImportResolver}; use wasmi::{memory_units, RuntimeValue}; diff --git a/polkadot/parachain/test-chains/basic_add/build.sh b/polkadot/parachain/test-chains/basic_add/build.sh index 965913f4957ee..f25f775d43503 100755 --- a/polkadot/parachain/test-chains/basic_add/build.sh +++ b/polkadot/parachain/test-chains/basic_add/build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e # Make LLD produce a binary that imports memory from the outside environment. diff --git a/polkadot/parachain/test-chains/basic_add/src/lib.rs b/polkadot/parachain/test-chains/basic_add/src/lib.rs index 723efb307f330..ff9006c8c2173 100644 --- a/polkadot/parachain/test-chains/basic_add/src/lib.rs +++ b/polkadot/parachain/test-chains/basic_add/src/lib.rs @@ -17,7 +17,13 @@ //! Basic parachain that adds a number as part of its state. #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(alloc, core_intrinsics, lang_items, panic_implementation, core_panic_info))] +#![cfg_attr( + not(feature = "std"), + feature( + alloc, core_intrinsics, lang_items, panic_implementation, core_panic_info, + alloc_error_handler + ) +)] #[cfg(not(feature = "std"))] extern crate alloc; @@ -27,7 +33,7 @@ extern crate wee_alloc; extern crate tiny_keccak; extern crate pwasm_libc; -use parachain::codec::{Slicable, Input}; +use parachain::codec::{Decode, Encode, Input, Output}; #[cfg(not(feature = "std"))] mod wasm; @@ -35,9 +41,6 @@ mod wasm; #[cfg(not(feature = "std"))] pub use wasm::*; -#[cfg(not(feature = "std"))] -use alloc::vec::Vec; - // Define global allocator. #[cfg(not(feature = "std"))] #[global_allocator] @@ -54,22 +57,20 @@ struct HeadData { post_state: [u8; 32], } -impl Slicable for HeadData { - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - self.number.using_encoded(|s| v.extend(s)); - self.parent_hash.using_encoded(|s| v.extend(s)); - self.post_state.using_encoded(|s| v.extend(s)); - - v +impl Encode for HeadData { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.number); + dest.push(&self.parent_hash); + dest.push(&self.post_state); } +} +impl Decode for HeadData { fn decode(input: &mut I) -> Option { Some(HeadData { - number: Slicable::decode(input)?, - parent_hash: Slicable::decode(input)?, - post_state: Slicable::decode(input)?, + number: Decode::decode(input)?, + parent_hash: Decode::decode(input)?, + post_state: Decode::decode(input)?, }) } } @@ -83,20 +84,18 @@ struct BlockData { add: u64, } -impl Slicable for BlockData { - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - self.state.using_encoded(|s| v.extend(s)); - self.add.using_encoded(|s| v.extend(s)); - - v +impl Encode for BlockData { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.state); + dest.push(&self.add); } +} +impl Decode for BlockData { fn decode(input: &mut I) -> Option { Some(BlockData { - state: Slicable::decode(input)?, - add: Slicable::decode(input)?, + state: Decode::decode(input)?, + add: Decode::decode(input)?, }) } } diff --git a/polkadot/parachain/test-chains/basic_add/src/wasm.rs b/polkadot/parachain/test-chains/basic_add/src/wasm.rs index edf53dc46f68a..10071131886fb 100644 --- a/polkadot/parachain/test-chains/basic_add/src/wasm.rs +++ b/polkadot/parachain/test-chains/basic_add/src/wasm.rs @@ -16,9 +16,9 @@ //! Defines WASM module logic. -use core::{intrinsics, panic}; +use core::{intrinsics, panic, alloc}; use parachain::{self, ValidationResult}; -use parachain::codec::Slicable; +use parachain::codec::{Encode, Decode}; use super::{HeadData, BlockData}; #[panic_implementation] @@ -29,9 +29,9 @@ pub fn panic(_info: &panic::PanicInfo) -> ! { } } -#[lang = "oom"] +#[alloc_error_handler] #[no_mangle] -pub fn oom() -> ! { +pub fn oom(_: alloc::Layout) -> ! { unsafe { intrinsics::abort(); } diff --git a/polkadot/parachain/test-chains/build.sh b/polkadot/parachain/test-chains/build.sh deleted file mode 100755 index d46a63561363d..0000000000000 --- a/polkadot/parachain/test-chains/build.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -set -e - -rm -rf ./target -for i in */ -do - i=${i%/} - cd $i - - RUSTFLAGS="-C link-arg=--import-memory" cargo +nightly build --target=wasm32-unknown-unknown --release --no-default-features - wasm-gc target/wasm32-unknown-unknown/release/$i.wasm ../../tests/res/$i.wasm - cd .. -done diff --git a/polkadot/parachain/tests/basic_add.rs b/polkadot/parachain/tests/basic_add.rs index c5fbe467a433d..566a6efc3f2ad 100644 --- a/polkadot/parachain/tests/basic_add.rs +++ b/polkadot/parachain/tests/basic_add.rs @@ -20,7 +20,7 @@ extern crate polkadot_parachain as parachain; extern crate tiny_keccak; use parachain::ValidationParams; -use parachain::codec::{Slicable, Input}; +use parachain::codec::{Decode, Encode, Input, Output}; // Head data for this parachain. #[derive(Default, Clone)] @@ -33,22 +33,20 @@ struct HeadData { post_state: [u8; 32], } -impl Slicable for HeadData { - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - self.number.using_encoded(|s| v.extend(s)); - self.parent_hash.using_encoded(|s| v.extend(s)); - self.post_state.using_encoded(|s| v.extend(s)); - - v +impl Encode for HeadData { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.number); + dest.push(&self.parent_hash); + dest.push(&self.post_state); } +} +impl Decode for HeadData { fn decode(input: &mut I) -> Option { Some(HeadData { - number: Slicable::decode(input)?, - parent_hash: Slicable::decode(input)?, - post_state: Slicable::decode(input)?, + number: Decode::decode(input)?, + parent_hash: Decode::decode(input)?, + post_state: Decode::decode(input)?, }) } } @@ -62,20 +60,18 @@ struct BlockData { add: u64, } -impl Slicable for BlockData { - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - self.state.using_encoded(|s| v.extend(s)); - self.add.using_encoded(|s| v.extend(s)); - - v +impl Encode for BlockData { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.state); + dest.push(&self.add); } +} +impl Decode for BlockData { fn decode(input: &mut I) -> Option { Some(BlockData { - state: Slicable::decode(input)?, - add: Slicable::decode(input)?, + state: Decode::decode(input)?, + add: Decode::decode(input)?, }) } } diff --git a/polkadot/primitives/README.adoc b/polkadot/primitives/README.adoc new file mode 100644 index 0000000000000..a8468a0cd9612 --- /dev/null +++ b/polkadot/primitives/README.adoc @@ -0,0 +1,5 @@ + += Polkadot primitives + +placeholder +//TODO Write content :) diff --git a/polkadot/primitives/src/lib.rs b/polkadot/primitives/src/lib.rs index f7861a8337fbe..83118799bb355 100644 --- a/polkadot/primitives/src/lib.rs +++ b/polkadot/primitives/src/lib.rs @@ -42,7 +42,7 @@ use primitives::bytes; use rstd::prelude::*; use runtime_primitives::traits::BlakeTwo256; use runtime_primitives::generic; -use codec::{Input, Slicable}; +use codec::{Encode, Decode, Input, Output}; pub mod parachain; @@ -109,12 +109,14 @@ pub type BlockId = generic::BlockId; #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] pub struct Log(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); -impl Slicable for Log { +impl Decode for Log { fn decode(input: &mut I) -> Option { Vec::::decode(input).map(Log) } +} - fn using_encoded R>(&self, f: F) -> R { - self.0.using_encoded(f) +impl Encode for Log { + fn encode_to(&self, dest: &mut T) { + self.0.encode_to(dest) } } diff --git a/polkadot/primitives/src/parachain.rs b/polkadot/primitives/src/parachain.rs index 9f803810e4538..ff7580067e101 100644 --- a/polkadot/primitives/src/parachain.rs +++ b/polkadot/primitives/src/parachain.rs @@ -16,7 +16,7 @@ //! Polkadot parachain types. -use codec::{Slicable, Input}; +use codec::{Encode, Decode, Input, Output}; use rstd::prelude::*; use rstd::cmp::Ordering; use super::Hash; @@ -47,11 +47,13 @@ impl Id { } } -impl Slicable for Id { +impl Decode for Id { fn decode(input: &mut I) -> Option { u32::decode(input).map(Id) } +} +impl Encode for Id { fn using_encoded R>(&self, f: F) -> R { self.0.using_encoded(f) } @@ -67,30 +69,26 @@ pub enum Chain { Parachain(Id), } -impl Slicable for Chain { +impl Decode for Chain { fn decode(input: &mut I) -> Option { let disc = input.read_byte()?; match disc { 0 => Some(Chain::Relay), - 1 => Some(Chain::Parachain(Slicable::decode(input)?)), + 1 => Some(Chain::Parachain(Decode::decode(input)?)), _ => None, } } +} - fn encode(&self) -> Vec { - let mut v = Vec::new(); +impl Encode for Chain { + fn encode_to(&self, dest: &mut T) { match *self { - Chain::Relay => { v.push(0); } + Chain::Relay => { dest.push_byte(0); } Chain::Parachain(id) => { - v.push(1u8); - id.using_encoded(|s| v.extend(s)); + dest.push_byte(1u8); + dest.push(&id); } } - v - } - - fn using_encoded R>(&self, f: F) -> R { - f(&self.encode().as_slice()) } } @@ -105,25 +103,19 @@ pub struct DutyRoster { pub guarantor_duty: Vec, } -impl Slicable for DutyRoster { +impl Decode for DutyRoster { fn decode(input: &mut I) -> Option { Some(DutyRoster { - validator_duty: Slicable::decode(input)?, - guarantor_duty: Slicable::decode(input)?, + validator_duty: Decode::decode(input)?, + guarantor_duty: Decode::decode(input)?, }) } +} - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - v.extend(self.validator_duty.encode()); - v.extend(self.guarantor_duty.encode()); - - v - } - - fn using_encoded R>(&self, f: F) -> R { - f(&self.encode().as_slice()) +impl Encode for DutyRoster { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.validator_duty); + dest.push(&self.guarantor_duty); } } @@ -134,26 +126,6 @@ impl Slicable for DutyRoster { #[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct Extrinsic; -/// Candidate parachain block. -/// -/// https://github.com/w3f/polkadot-spec/blob/master/spec.md#candidate-para-chain-block -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] -#[cfg_attr(feature = "std", serde(deny_unknown_fields))] -pub struct Candidate { - /// The ID of the parachain this is a proposal for. - pub parachain_index: Id, - /// Collator's signature - pub collator_signature: CandidateSignature, - /// Unprocessed ingress queue. - /// - /// Ordered by parachain ID and block number. - pub unprocessed_ingress: ConsolidatedIngress, - /// Block data - pub block: BlockData, -} - /// Candidate receipt type. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] @@ -164,6 +136,8 @@ pub struct CandidateReceipt { pub parachain_index: Id, /// The collator's relay-chain account ID pub collator: super::AccountId, + /// Signature on blake2-256 of the block data by collator. + pub signature: CandidateSignature, /// The head-data pub head_data: HeadData, /// Balance uploads to the relay chain. @@ -172,30 +146,34 @@ pub struct CandidateReceipt { pub egress_queue_roots: Vec<(Id, Hash)>, /// Fees paid from the chain to the relay chain validators pub fees: u64, + /// blake2-256 Hash of block data. + pub block_data_hash: Hash, } -impl Slicable for CandidateReceipt { - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - self.parachain_index.using_encoded(|s| v.extend(s)); - self.collator.using_encoded(|s| v.extend(s)); - self.head_data.0.using_encoded(|s| v.extend(s)); - self.balance_uploads.using_encoded(|s| v.extend(s)); - self.egress_queue_roots.using_encoded(|s| v.extend(s)); - self.fees.using_encoded(|s| v.extend(s)); - - v +impl Encode for CandidateReceipt { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.parachain_index); + dest.push(&self.collator); + dest.push(&self.signature); + dest.push(&self.head_data.0); + dest.push(&self.balance_uploads); + dest.push(&self.egress_queue_roots); + dest.push(&self.fees); + dest.push(&self.block_data_hash); } +} +impl Decode for CandidateReceipt { fn decode(input: &mut I) -> Option { Some(CandidateReceipt { - parachain_index: Slicable::decode(input)?, - collator: Slicable::decode(input)?, - head_data: Slicable::decode(input).map(HeadData)?, - balance_uploads: Slicable::decode(input)?, - egress_queue_roots: Slicable::decode(input)?, - fees: Slicable::decode(input)?, + parachain_index: Decode::decode(input)?, + collator: Decode::decode(input)?, + signature: Decode::decode(input)?, + head_data: Decode::decode(input).map(HeadData)?, + balance_uploads: Decode::decode(input)?, + egress_queue_roots: Decode::decode(input)?, + fees: Decode::decode(input)?, + block_data_hash: Decode::decode(input)?, }) } } @@ -204,9 +182,20 @@ impl CandidateReceipt { /// Get the blake2_256 hash #[cfg(feature = "std")] pub fn hash(&self) -> Hash { - use runtime_primitives::traits::{BlakeTwo256, Hashing}; + use runtime_primitives::traits::{BlakeTwo256, Hash}; BlakeTwo256::hash_of(self) } + + /// Check integrity vs. provided block data. + pub fn check_signature(&self) -> Result<(), ()> { + use runtime_primitives::traits::Verify; + + if self.signature.verify(&self.block_data_hash.0[..], &self.collator) { + Ok(()) + } else { + Err(()) + } + } } impl PartialOrd for CandidateReceipt { @@ -223,6 +212,34 @@ impl Ord for CandidateReceipt { } } +/// A full collation. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "std", serde(deny_unknown_fields))] +pub struct Collation { + /// Block data. + pub block_data: BlockData, + /// Candidate receipt itself. + pub receipt: CandidateReceipt, +} + +impl Decode for Collation { + fn decode(input: &mut I) -> Option { + Some(Collation { + block_data: Decode::decode(input)?, + receipt: Decode::decode(input)?, + }) + } +} + +impl Encode for Collation { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.block_data); + dest.push(&self.receipt); + } +} + /// Parachain ingress queue message. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] @@ -243,6 +260,27 @@ pub struct ConsolidatedIngress(pub Vec<(Id, Vec)>); #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] pub struct BlockData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); +impl BlockData { + /// Compute hash of block data. + #[cfg(feature = "std")] + pub fn hash(&self) -> Hash { + use runtime_primitives::traits::{BlakeTwo256, Hash}; + BlakeTwo256::hash(&self.0[..]) + } +} + +impl Decode for BlockData { + fn decode(input: &mut I) -> Option { + Some(BlockData(Decode::decode(input)?)) + } +} + +impl Encode for BlockData { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.0); + } +} + /// Parachain header raw bytes wrapper type. #[derive(PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] @@ -263,29 +301,21 @@ pub struct ValidationCode(#[cfg_attr(feature = "std", serde(with="bytes"))] pub #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] pub struct Activity(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); -impl Slicable for Activity { +impl Decode for Activity { fn decode(input: &mut I) -> Option { Vec::::decode(input).map(Activity) } - - fn using_encoded R>(&self, f: F) -> R { - self.0.using_encoded(f) - } } -#[derive(Clone, Copy, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] -#[repr(u8)] -enum StatementKind { - Candidate = 1, - Valid = 2, - Invalid = 3, - Available = 4, +impl Encode for Activity { + fn encode_to(&self, dest: &mut T) { + self.0.encode_to(dest) + } } /// Statements which can be made about parachain candidates. #[derive(Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] pub enum Statement { /// Proposal of a parachain candidate. Candidate(CandidateReceipt), @@ -296,47 +326,3 @@ pub enum Statement { /// Vote to advance round after inactive primary. Available(Hash), } - -impl Slicable for Statement { - fn encode(&self) -> Vec { - let mut v = Vec::new(); - match *self { - Statement::Candidate(ref candidate) => { - v.push(StatementKind::Candidate as u8); - candidate.using_encoded(|s| v.extend(s)); - } - Statement::Valid(ref hash) => { - v.push(StatementKind::Valid as u8); - hash.using_encoded(|s| v.extend(s)); - } - Statement::Invalid(ref hash) => { - v.push(StatementKind::Invalid as u8); - hash.using_encoded(|s| v.extend(s)); - } - Statement::Available(ref hash) => { - v.push(StatementKind::Available as u8); - hash.using_encoded(|s| v.extend(s)); - } - } - - v - } - - fn decode(value: &mut I) -> Option { - match value.read_byte() { - Some(x) if x == StatementKind::Candidate as u8 => { - Slicable::decode(value).map(Statement::Candidate) - } - Some(x) if x == StatementKind::Valid as u8 => { - Slicable::decode(value).map(Statement::Valid) - } - Some(x) if x == StatementKind::Invalid as u8 => { - Slicable::decode(value).map(Statement::Invalid) - } - Some(x) if x == StatementKind::Available as u8 => { - Slicable::decode(value).map(Statement::Available) - } - _ => None, - } - } -} diff --git a/polkadot/runtime/Cargo.toml b/polkadot/runtime/Cargo.toml index 9ac1f50175300..40685956016c9 100644 --- a/polkadot/runtime/Cargo.toml +++ b/polkadot/runtime/Cargo.toml @@ -26,6 +26,7 @@ substrate-runtime-session = { path = "../../substrate/runtime/session" } substrate-runtime-staking = { path = "../../substrate/runtime/staking" } substrate-runtime-system = { path = "../../substrate/runtime/system" } substrate-runtime-timestamp = { path = "../../substrate/runtime/timestamp" } +substrate-runtime-version = { path = "../../substrate/runtime/version" } [dev-dependencies] hex-literal = "0.1.0" @@ -48,6 +49,7 @@ std = [ "substrate-runtime-staking/std", "substrate-runtime-system/std", "substrate-runtime-timestamp/std", + "substrate-runtime-version/std", "serde_derive", "serde/std", "log", diff --git a/polkadot/runtime/README.adoc b/polkadot/runtime/README.adoc new file mode 100644 index 0000000000000..86dc313134a08 --- /dev/null +++ b/polkadot/runtime/README.adoc @@ -0,0 +1,5 @@ + += Polkadot Runtime + +placeholder +//TODO Write content :) diff --git a/polkadot/runtime/src/lib.rs b/polkadot/runtime/src/lib.rs index e0a678993ed08..7c366e30e7a8a 100644 --- a/polkadot/runtime/src/lib.rs +++ b/polkadot/runtime/src/lib.rs @@ -56,6 +56,8 @@ extern crate substrate_runtime_session as session; extern crate substrate_runtime_staking as staking; extern crate substrate_runtime_system as system; extern crate substrate_runtime_timestamp as timestamp; +#[macro_use] +extern crate substrate_runtime_version as version; #[cfg(feature = "std")] mod checked_block; @@ -69,6 +71,7 @@ pub use staking::address::Address as RawAddress; use primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, Log, SessionKey, Signature}; use runtime_primitives::{generic, traits::{HasPublicAux, BlakeTwo256, Convert}}; +use version::RuntimeVersion; #[cfg(feature = "std")] pub use runtime_primitives::BuildStorage; @@ -102,6 +105,22 @@ pub type Block = generic::Block; #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] pub struct Concrete; +/// Polkadot runtime version. +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: ver_str!("polkadot"), + impl_name: ver_str!("parity-polkadot"), + authoring_version: 1, + spec_version: 2, + impl_version: 0, +}; + +impl version::Trait for Concrete { + const VERSION: RuntimeVersion = VERSION; +} + +/// Version module for this concrete runtime. +pub type Version = version::Module; + impl HasPublicAux for Concrete { type PublicAux = AccountId; // TODO: Option } @@ -126,8 +145,8 @@ impl consensus::Trait for Concrete { pub type Consensus = consensus::Module; impl timestamp::Trait for Concrete { - const SET_POSITION: u32 = TIMESTAMP_SET_POSITION; - type Value = u64; + const TIMESTAMP_SET_POSITION: u32 = TIMESTAMP_SET_POSITION; + type Moment = u64; } /// Timestamp module for this concrete runtime. pub type Timestamp = timestamp::Module; @@ -136,20 +155,21 @@ pub type Timestamp = timestamp::Module; pub struct SessionKeyConversion; impl Convert for SessionKeyConversion { fn convert(a: AccountId) -> SessionKey { - a.0 + a.0.into() } } impl session::Trait for Concrete { type ConvertAccountIdToSessionKey = SessionKeyConversion; + type OnSessionChange = Staking; } /// Session module for this concrete runtime. pub type Session = session::Module; impl staking::Trait for Concrete { type Balance = Balance; - type DetermineContractAddress = BlakeTwo256; type AccountIndex = AccountIndex; + type OnAccountKill = (); } /// Staking module for this concrete runtime. pub type Staking = staking::Module; @@ -198,6 +218,7 @@ impl_outer_dispatch! { Democracy = 5, Council = 6, CouncilVoting = 7, + Parachains = 8, } } @@ -213,12 +234,14 @@ impl_outer_config! { StakingConfig => staking, DemocracyConfig => democracy, CouncilConfig => council, + TimestampConfig => timestamp, ParachainsConfig => parachains, } } pub mod api { impl_stubs!( + version => |()| super::Version::version(), authorities => |()| super::Consensus::authorities(), initialise_block => |header| super::Executive::initialise_block(&header), apply_extrinsic => |extrinsic| super::Executive::apply_extrinsic(extrinsic), @@ -234,7 +257,7 @@ pub mod api { mod tests { use super::*; use substrate_primitives as primitives; - use ::codec::Slicable; + use codec::{Encode, Decode}; use substrate_primitives::hexdisplay::HexDisplay; use substrate_serializer as ser; use runtime_primitives::traits::{Digest as DigestT, Header as HeaderT}; @@ -353,7 +376,7 @@ mod tests { // df0f0200 // 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - let v = Slicable::encode(&tx); + let v = Encode::encode(&tx); assert_eq!(&v[..], &hex!["6f000000ff0101010101010101010101010101010101010101010101010101010101010101e70300000300df0f02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"][..]); println!("{}", HexDisplay::from(&v)); assert_eq!(UncheckedExtrinsic::decode(&mut &v[..]).unwrap(), tx); @@ -370,7 +393,13 @@ mod tests { )) ))), }; - let v = Slicable::encode(&xt); + let v = Encode::encode(&xt); assert_eq!(Extrinsic::decode(&mut &v[..]).unwrap(), xt); } + + #[test] + fn parachain_calls_are_privcall() { + let _register = PrivCall::Parachains(parachains::PrivCall::register_parachain(0.into(), vec![1, 2, 3], vec![])); + let _deregister = PrivCall::Parachains(parachains::PrivCall::deregister_parachain(0.into())); + } } diff --git a/polkadot/runtime/src/parachains.rs b/polkadot/runtime/src/parachains.rs index c200648112b8b..4ac5f3f2a1089 100644 --- a/polkadot/runtime/src/parachains.rs +++ b/polkadot/runtime/src/parachains.rs @@ -16,15 +16,14 @@ //! Main parachains logic. For now this is just the determination of which validators do what. -use primitives; use rstd::prelude::*; -use codec::{Slicable, Joiner}; +use codec::Decode; -use runtime_primitives::traits::{Executable, RefInto, MaybeEmpty}; +use runtime_primitives::traits::{Hash, BlakeTwo256, Executable, RefInto, MaybeEmpty}; use primitives::parachain::{Id, Chain, DutyRoster, CandidateReceipt}; use {system, session}; -use substrate_runtime_support::{Hashable, StorageValue, StorageMap}; +use substrate_runtime_support::{StorageValue, StorageMap}; use substrate_runtime_support::dispatch::Result; #[cfg(any(feature = "std", test))] @@ -33,7 +32,7 @@ use rstd::marker::PhantomData; #[cfg(any(feature = "std", test))] use {runtime_io, runtime_primitives}; -pub trait Trait: system::Trait + session::Trait { +pub trait Trait: system::Trait + session::Trait { /// The position of the set_heads call in the block. const SET_POSITION: u32; @@ -43,13 +42,19 @@ pub trait Trait: system::Trait + session::Trait { decl_module! { /// Parachains module. pub struct Module; - /// Call type for parachains. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum Call where aux: ::PublicAux { // provide candidate receipts for parachains, in ascending order by id. fn set_heads(aux, heads: Vec) -> Result = 0; } + + /// Private calls for parachains. + #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] + pub enum PrivCall { + fn register_parachain(id: Id, code: Vec, initial_head_data: Vec) -> Result = 0; + fn deregister_parachain(id: Id) -> Result = 1; + } } decl_storage! { @@ -83,8 +88,9 @@ impl Module { let mut roles_gua = roles_val.clone(); - let random_seed = system::Module::::random_seed(); - let mut seed = random_seed.to_vec().and(b"validator_role_pairs").blake2_256(); + let mut random_seed = system::Module::::random_seed().to_vec(); + random_seed.extend(b"validator_role_pairs"); + let mut seed = BlakeTwo256::hash(&random_seed); // shuffle for i in 0..(validator_count - 1) { @@ -100,7 +106,7 @@ impl Module { if offset == 24 { // into the last 8 bytes - rehash to gather new entropy - seed = seed.blake2_256(); + seed = BlakeTwo256::hash(&seed); } // exchange last item with randomly chosen first. @@ -116,20 +122,22 @@ impl Module { /// Register a parachain with given code. /// Fails if given ID is already used. - pub fn register_parachain(id: Id, code: Vec, initial_head_data: Vec) { + pub fn register_parachain(id: Id, code: Vec, initial_head_data: Vec) -> Result { let mut parachains = Self::active_parachains(); match parachains.binary_search(&id) { - Ok(_) => panic!("Parachain with id {} already exists", id.into_inner()), + Ok(_) => fail!("Parachain already exists"), Err(idx) => parachains.insert(idx, id), } >::insert(id, code); >::put(parachains); >::insert(id, initial_head_data); + + Ok(()) } /// Deregister a parachain with given id - pub fn deregister_parachain(id: Id) { + pub fn deregister_parachain(id: Id) -> Result { let mut parachains = Self::active_parachains(); match parachains.binary_search(&id) { Ok(idx) => { parachains.remove(idx); } @@ -139,6 +147,7 @@ impl Module { >::remove(id); >::remove(id); >::put(parachains); + Ok(()) } fn set_heads(aux: &::PublicAux, heads: Vec) -> Result { @@ -181,10 +190,14 @@ impl Executable for Module { /// Parachains module genesis configuration. #[cfg(any(feature = "std", test))] +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] pub struct GenesisConfig { /// The initial parachains, mapped to code. pub parachains: Vec<(Id, Vec)>, /// Phantom data. + #[serde(skip)] pub phantom: PhantomData, } @@ -201,10 +214,9 @@ impl Default for GenesisConfig { #[cfg(any(feature = "std", test))] impl runtime_primitives::BuildStorage for GenesisConfig { - fn build_storage(mut self) -> runtime_io::TestExternalities { + fn build_storage(mut self) -> ::std::result::Result { use std::collections::HashMap; - use runtime_io::twox_128; - use codec::Slicable; + use codec::Encode; self.parachains.sort_unstable_by_key(|&(ref id, _)| id.clone()); self.parachains.dedup_by_key(|&mut (ref id, _)| id.clone()); @@ -212,15 +224,15 @@ impl runtime_primitives::BuildStorage for GenesisConfig let only_ids: Vec<_> = self.parachains.iter().map(|&(ref id, _)| id).cloned().collect(); let mut map: HashMap<_, _> = map![ - twox_128(>::key()).to_vec() => only_ids.encode() + Self::hash(>::key()).to_vec() => only_ids.encode() ]; for (id, code) in self.parachains { - let key = twox_128(&>::key_for(&id)).to_vec(); + let key = Self::hash(&>::key_for(&id)).to_vec(); map.insert(key, code.encode()); } - map.into() + Ok(map.into()) } } @@ -232,7 +244,7 @@ mod tests { use runtime_primitives::BuildStorage; use runtime_primitives::traits::{HasPublicAux, Identity, BlakeTwo256}; use runtime_primitives::testing::{Digest, Header}; - use consensus; + use {consensus, timestamp}; #[derive(Clone, Eq, PartialEq)] pub struct Test; @@ -254,6 +266,11 @@ mod tests { } impl session::Trait for Test { type ConvertAccountIdToSessionKey = Identity; + type OnSessionChange = (); + } + impl timestamp::Trait for Test { + const TIMESTAMP_SET_POSITION: u32 = 0; + type Moment = u64; } impl Trait for Test { const SET_POSITION: u32 = 0; @@ -264,19 +281,20 @@ mod tests { type Parachains = Module; fn new_test_ext(parachains: Vec<(Id, Vec)>) -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::::default().build_storage(); + let mut t = system::GenesisConfig::::default().build_storage().unwrap(); t.extend(consensus::GenesisConfig::{ code: vec![], authorities: vec![1, 2, 3], - }.build_storage()); + }.build_storage().unwrap()); t.extend(session::GenesisConfig::{ session_length: 1000, validators: vec![1, 2, 3, 4, 5, 6, 7, 8], - }.build_storage()); + broken_percent_late: 100, + }.build_storage().unwrap()); t.extend(GenesisConfig::{ parachains: parachains, phantom: PhantomData, - }.build_storage()); + }.build_storage().unwrap()); t } @@ -307,12 +325,12 @@ mod tests { assert_eq!(Parachains::parachain_code(&5u32.into()), Some(vec![1,2,3])); assert_eq!(Parachains::parachain_code(&100u32.into()), Some(vec![4,5,6])); - Parachains::register_parachain(99u32.into(), vec![7,8,9], vec![1, 1, 1]); + Parachains::register_parachain(99u32.into(), vec![7,8,9], vec![1, 1, 1]).unwrap(); assert_eq!(Parachains::active_parachains(), vec![5u32.into(), 99u32.into(), 100u32.into()]); assert_eq!(Parachains::parachain_code(&99u32.into()), Some(vec![7,8,9])); - Parachains::deregister_parachain(5u32.into()); + Parachains::deregister_parachain(5u32.into()).unwrap(); assert_eq!(Parachains::active_parachains(), vec![99u32.into(), 100u32.into()]); assert_eq!(Parachains::parachain_code(&5u32.into()), None); diff --git a/polkadot/runtime/src/utils.rs b/polkadot/runtime/src/utils.rs index 4c16e215bab7e..1531590ff5fca 100644 --- a/polkadot/runtime/src/utils.rs +++ b/polkadot/runtime/src/utils.rs @@ -47,5 +47,5 @@ pub fn inherent_extrinsics(timestamp: ::primitives::Timestamp, parachain_heads: /// Checks an unchecked extrinsic for validity. pub fn check_extrinsic(xt: UncheckedExtrinsic) -> bool { - xt.check(Staking::lookup).is_ok() + xt.check_with(Staking::lookup).is_ok() } diff --git a/polkadot/runtime/wasm/Cargo.lock b/polkadot/runtime/wasm/Cargo.lock index 73fab465f692c..b90d8e14e89d8 100644 --- a/polkadot/runtime/wasm/Cargo.lock +++ b/polkadot/runtime/wasm/Cargo.lock @@ -137,11 +137,6 @@ dependencies = [ name = "environmental" version = "0.1.0" -[[package]] -name = "error-chain" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "ethbloom" version = "0.5.0" @@ -294,16 +289,6 @@ dependencies = [ "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "kvdb" -version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#dec390a89fe038337399315daf15e628ffbb4d8e" -dependencies = [ - "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)", -] - [[package]] name = "lazy_static" version = "0.2.11" @@ -367,6 +352,11 @@ dependencies = [ "rlp 0.2.1 (git+https://github.com/paritytech/parity.git)", ] +[[package]] +name = "nan-preserving-float" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "nodrop" version = "0.1.12" @@ -395,17 +385,7 @@ dependencies = [ [[package]] name = "parity-wasm" -version = "0.27.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-wasm" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -500,6 +480,7 @@ dependencies = [ "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", "substrate-runtime-timestamp 0.1.0", + "substrate-runtime-version 0.1.0", ] [[package]] @@ -535,16 +516,6 @@ dependencies = [ name = "pwasm-libc" version = "0.1.0" -[[package]] -name = "pwasm-utils" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "quote" version = "0.6.3" @@ -759,7 +730,7 @@ dependencies = [ "substrate-runtime-std 0.1.0", "twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)", - "wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -778,17 +749,6 @@ dependencies = [ "substrate-runtime-system 0.1.0", ] -[[package]] -name = "substrate-runtime-contract" -version = "0.1.0" -dependencies = [ - "parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pwasm-utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-codec 0.1.0", - "substrate-runtime-sandbox 0.1.0", - "substrate-runtime-std 0.1.0", -] - [[package]] name = "substrate-runtime-council" version = "0.1.0" @@ -866,6 +826,7 @@ name = "substrate-runtime-primitives" version = "0.1.0" dependencies = [ "integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", @@ -885,7 +846,7 @@ dependencies = [ "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-std 0.1.0", - "wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -905,6 +866,7 @@ dependencies = [ "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", + "substrate-runtime-timestamp 0.1.0", ] [[package]] @@ -919,7 +881,6 @@ dependencies = [ "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-consensus 0.1.0", - "substrate-runtime-contract 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-sandbox 0.1.0", @@ -927,6 +888,7 @@ dependencies = [ "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", + "substrate-runtime-timestamp 0.1.0", ] [[package]] @@ -977,6 +939,7 @@ dependencies = [ "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-std 0.1.0", @@ -984,6 +947,17 @@ dependencies = [ "substrate-runtime-system 0.1.0", ] +[[package]] +name = "substrate-runtime-version" +version = "0.1.0" +dependencies = [ + "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", +] + [[package]] name = "substrate-state-machine" version = "0.1.0" @@ -992,7 +966,6 @@ dependencies = [ "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.1 (git+https://github.com/paritytech/parity.git)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity.git)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "memorydb 0.1.1 (git+https://github.com/paritytech/parity.git)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1134,12 +1107,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasmi" -version = "0.1.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.27.6 (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.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1179,7 +1153,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" -"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386" "checksum ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum ethcore-logger 1.12.0 (git+https://github.com/paritytech/parity.git)" = "" @@ -1197,7 +1170,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)" = "" "checksum keccak-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b7f51f30d7986536accaec4a6a288008dfb3dbffe8a2863a65292bc395a3ae7" "checksum keccak-hash 0.1.2 (git+https://github.com/paritytech/parity.git)" = "" -"checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739" "checksum libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)" = "ac8ebf8343a981e2fa97042b14768f02ed3e1d602eac06cae6166df3c8ced206" @@ -1207,12 +1179,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" "checksum memorydb 0.1.1 (git+https://github.com/paritytech/parity.git)" = "" +"checksum nan-preserving-float 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34d4f00fcc2f4c9efa8cc971db0da9e28290e28e97af47585e48691ef10ff31f" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum parity-wasm 0.27.6 (registry+https://github.com/rust-lang/crates.io-index)" = "bd4dc02a80a0315b109e48992c46942c79bcdb8fac416dd575d330ed9ced6cbd" -"checksum parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41083957b80abb8a01fac4d2773d5f92653aed8f0b740c8d3da1da62c7857abe" +"checksum parity-wasm 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1c91199d14bd5b78ecade323d4a891d094799749c1b9e82d9c590c2e2849a40" "checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" "checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" @@ -1221,7 +1193,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0" "checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892" "checksum proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1fa93823f53cfd0f5ac117b189aed6cfdfb2cfc0a9d82e956dd7927595ed7d46" -"checksum pwasm-utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3a822d2a1624b10c46572c231c149575bcc261c37d84fd3f1a2f5ae1f65515" "checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" @@ -1260,7 +1231,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d19da510b59247935ad5f598357b3cc739912666d75d3d28318026478d95bbdb" +"checksum wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b4a6d379e9332b1b1f52c5a87f2481c85c7c931d8ec411963dfb8f26b1ec1e3" "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/polkadot/runtime/wasm/Cargo.toml b/polkadot/runtime/wasm/Cargo.toml index f5dc280e6f6b2..3a73d894001e0 100644 --- a/polkadot/runtime/wasm/Cargo.toml +++ b/polkadot/runtime/wasm/Cargo.toml @@ -24,6 +24,7 @@ substrate-runtime-session = { path = "../../../substrate/runtime/session", defau substrate-runtime-staking = { path = "../../../substrate/runtime/staking", default-features = false } substrate-runtime-system = { path = "../../../substrate/runtime/system", default-features = false } substrate-runtime-timestamp = { path = "../../../substrate/runtime/timestamp", default-features = false } +substrate-runtime-version = { path = "../../../substrate/runtime/version", default-features = false } [features] default = [] @@ -44,6 +45,7 @@ std = [ "substrate-runtime-staking/std", "substrate-runtime-system/std", "substrate-runtime-timestamp/std", + "substrate-runtime-version/std", ] [profile.release] diff --git a/polkadot/runtime/wasm/build.sh b/polkadot/runtime/wasm/build.sh index 8920ca8bbb35c..88010211f95d6 100755 --- a/polkadot/runtime/wasm/build.sh +++ b/polkadot/runtime/wasm/build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e cargo +nightly build --target=wasm32-unknown-unknown --release diff --git a/polkadot/runtime/wasm/genesis.wasm b/polkadot/runtime/wasm/genesis.wasm deleted file mode 100644 index 07c28e8cff597..0000000000000 Binary files a/polkadot/runtime/wasm/genesis.wasm and /dev/null differ diff --git a/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm b/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm index 9fa902edcbcc7..72aa4463a3ed7 100644 Binary files a/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm and b/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm differ diff --git a/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm b/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm index a98f50b4ca5d1..c50030ecaadf3 100755 Binary files a/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm and b/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm differ diff --git a/polkadot/service/Cargo.toml b/polkadot/service/Cargo.toml index 86b4deea507fd..77c7589c91df9 100644 --- a/polkadot/service/Cargo.toml +++ b/polkadot/service/Cargo.toml @@ -1,19 +1,16 @@ [package] name = "polkadot-service" -version = "0.2.0" +version = "0.3.0" authors = ["Parity Technologies "] [dependencies] -futures = "0.1.17" parking_lot = "0.4" -tokio-timer = "0.1.2" -error-chain = "0.11" +error-chain = "0.12" lazy_static = "1.0" log = "0.3" slog = "^2" -clap = "2.27" -tokio-core = "0.1.12" -exit-future = "0.1" +tokio = "0.1.7" +hex-literal = "0.1" ed25519 = { path = "../../substrate/ed25519" } polkadot-primitives = { path = "../primitives" } polkadot-runtime = { path = "../runtime" } @@ -21,14 +18,11 @@ polkadot-consensus = { path = "../consensus" } polkadot-executor = { path = "../executor" } polkadot-api = { path = "../api" } polkadot-transaction-pool = { path = "../transaction-pool" } -substrate-keystore = { path = "../../substrate/keystore" } +polkadot-network = { path = "../network" } substrate-runtime-io = { path = "../../substrate/runtime-io" } -substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" } substrate-primitives = { path = "../../substrate/primitives" } substrate-network = { path = "../../substrate/network" } substrate-client = { path = "../../substrate/client" } -substrate-client-db = { path = "../../substrate/client/db" } substrate-codec = { path = "../../substrate/codec" } -substrate-executor = { path = "../../substrate/executor" } -substrate-state-machine = { path = "../../substrate/state-machine" } +substrate-service = { path = "../../substrate/service" } substrate-telemetry = { path = "../../substrate/telemetry" } diff --git a/polkadot/service/README.adoc b/polkadot/service/README.adoc new file mode 100644 index 0000000000000..3de386712855d --- /dev/null +++ b/polkadot/service/README.adoc @@ -0,0 +1,5 @@ + += Polkadot Service + +placeholder +//TODO Write content :) diff --git a/polkadot/service/res/krummelanke.json b/polkadot/service/res/krummelanke.json new file mode 100644 index 0000000000000..0e76ea124b98f --- /dev/null +++ b/polkadot/service/res/krummelanke.json @@ -0,0 +1,51 @@ +{ +"name": "Krumme Lanke", +"id": "krummelanke", +"genesis": {"raw": { + "0x9768f3cbdd14c1a63474dfbdbe052f42": "0x80f4030000000000", + "0x3b700687fecdff5ec1c4a5b714521eb6": "0x0000000000000000", + "0xa059ae3b3ef725721e97452642803b61": "0x0c00000000000000", + "0x81c1e7165a6371a30eda241a30ea26dd": "0x6400000000000000", + "0x45e71d57a2e3a4eace16dbc9286652e3": "0x00000000", + "0x1d72be21946c0b245c026b7be8256cc5": "0x00000000", + "0xd68ee884e4baac617d9823d543ab9295": "0x0000000000000010", + "0x1d007e138cb61e2524a67b15ec01d8cb": "0x0000000000000010", + "0xbfde7c86a8efd60ee5db2de6446703d5": "0xc04e000000000000", + "0x3a617574683a6c656e": "0x04000000", + "0xb54b186fe8782c2a03f2fd15f95c26bf": "0x00000000", + "0x9dd24013e492bdbb3544fba06734baf7": "0xd002000000000000", + "0xd52c584b1e542130e5b277f1af7b7714": "0x00000000", + "0x3a617574683a03000000": "0x8101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c", + "0x916dbd78366f27a9597bd4c831e7914d": "0x00e9070000000000", + "0xf37d2c26c6953b18878dbc1dc65edbc0": "0x1800000000000000", + "0x8d62e0fbc08e8694f8991f88d763c5fb": "0x5a00000000000000", + "0xa659ecb253960cfd890e08809104b815": "0x809d000000000000", + "0x3a617574683a00000000": "0x82c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf5", + "0x3a617574683a02000000": "0x063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca5", + "0xe885ffcc2245c8b7d128685cac6b1a0b": "0x0100000000000000", + "0x94b01408fc662bcf2e97df23ce6d67e2": "0x0100000000000000", + "0x6cac40e934558080fbf29c55c113b461": "0x0000000000000000", + "0x8379e35e0cd953085e0404b9223c0cb0": "0xc04e000000000000", + "0x5a3dcf1edb28ea65a038d1eef6767380": "0x003b010000000000", + "0x7a5bafa684003bc748abe89bfbd20f76": "0xe803000000000000", + "0x3d5680071e92ff27a2914bba661e5d83": "0x400b000000000000", + "0x274351e20682cb2ed212b6eab04ef89f": "0x00000000", + "0x3a617574683a01000000": "0x4de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7", + "0x482b5d7b62ccccac45d55bd43c767266": "0x6400000000000000", + "0x35b8ced31f34a951bc3b56db2f425c51": "0x00000000", + "0x98b9e95963cac608a3d0d537fbeaf5c2": "0x0400000082c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf54de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca58101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c", + "0xce83497694648564e47482d0dc444564": "0x18000000", + "0xa0c2154e69bce912f28e890561fcb95c": "0x0400000082c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf54de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca58101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c", + "0x9b7ecc8eb0fade7c91d94b8715fc9ee1": "0xe803000000000000", + "0x3a636f6465": "0x0061736d010000000197011760027f7f0060057f7f7f7f7f017f60017f017f60037f7f7f017f60017f0060000060037f7f7f0060047f7f7f7f006000017e60027f7f017f60027f7e0060037e7f7f0060017f017e600a7f7f7f7f7f7f7f7f7f7f0060017e0060067f7f7f7f7f7f0060047f7f7f7f017f60047f7f7f7f017e60067f7f7f7f7f7f017f60057f7f7f7f7f0060027f7f017e60027f7e017f60037f7f7e0002f1031603656e76146578745f6765745f73746f726167655f696e746f000103656e760a6578745f6d616c6c6f63000203656e76086578745f66726565000403656e760c6578745f74776f785f313238000603656e760f6578745f7365745f73746f72616765000703656e76116578745f636c6561725f73746f72616765000003656e760a6578745f6d656d636d70000303656e76186578745f656e756d6572617465645f747269655f726f6f74000703656e760e6578745f7072696e745f75746638000003656e760d6578745f7072696e745f6e756d000e03656e760a6578745f6d656d637079000303656e760b6578745f6d656d6d6f7665000303656e760a6578745f6d656d736574000303656e76166578745f73616e64626f785f6d656d6f72795f6e6577000903656e76176578745f73616e64626f785f696e7374616e7469617465001203656e76126578745f73616e64626f785f696e766f6b65001003656e76166578745f73616e64626f785f6d656d6f72795f676574001003656e76166578745f73616e64626f785f6d656d6f72795f736574001003656e760e6578745f626c616b65325f323536000603656e760d6578745f7072696e745f686578000003656e76106578745f73746f726167655f726f6f74000403656e76126578745f656432353531395f766572696679001003d001ce010003040505050500030000020404050400060000060505000804040900000505040004030004060a040b0005000c0c00040405060404060d0504050002040400050505050505050505050505050505050505040504050405050405040505040504050405040504050405040506060000060007070f070f0710070707071107130906000409060000040500140014061404140a06041414140002060a15000000000400000004040000040c000405070a1400000000000413060706160704140616060000060000000000000000090405017001161605030100110609017f0141d0c3c0000b07a8010b066d656d6f7279020011727573745f626567696e5f756e77696e64004d066d616c6c6f630052046672656500530b617574686f72697469657300a10110696e697469616c6973655f626c6f636b00a3010f6170706c795f65787472696e73696300a5010d657865637574655f626c6f636b00a7010e66696e616c6973655f626c6f636b00ab010f76616c696461746f725f636f756e7400ac010a76616c696461746f727300ad010930010041010b158f019001910192019301cc01cd01ce01c601cf01d001d101c701d30195019b01d4019401d501d6019c010abbe40cce01ea0403067f017e057f230041106b220224002002410036020020012001280208220341002001280200220420012802042205200241042003100022032003417f461b2203410420034104491b6a22063602080240024002400240200341034d0d0020022802002207ad420c7e2208422088a70d022008a72203417f4c0d01024002402003450d002003100122090d010c050b410421090b20022007360204200220093602002002410036020802402007450d00200141086a210a4100210b4100210c03402002410036020c200a4100200420052002410c6a41042006100022012001417f461b2201410420014104491b20066a2206360200024002400240200141034d0d00200228020c2201417f4c0d01024002402001450d00200110012203450d0a20034100200110171a0c010b410121030b200a20014100200420052003200120061000220d200d417f461b220d200d20014b1b20066a220636020002402001200d4b0d002003450d01200c41016a210c2001ad22084220862008842108200b2002280204470d0320021018200241086a280200210b200228020021090c030b200310020b200228020021060240200b450d00200b410c6c21032006210103400240200141046a280200450d00200128020010020b2001410c6a2101200341746a22030d000b0b2002280204450d04200610020c040b1019000b2009200b410c6c6a2201200837020420012003360200200241086a200b41016a220b360200200c2007490d000b200228020021090b2009450d002000200229020437020420002009360200200241106a24000f0b20004100360200200241106a24000f0b101a000b101b000b101c000b0a00200020012002100c0b810101057f410421010240024002400240200041046a2802002202450d00200241186c2201417f4c0d0320002802002103200110012204450d022004200320012002410c6c2205200520014b1b101e1a20031002200241017421010c010b413010012204450d010b20002004360200200041046a20013602000f0b101c000b1073000b05001041000b05001041000b05001041000b0500104e000bc11105097f037e017f017e027f230041a0026b220224002001280200210320024180026a20012802042204412020044120491b22056a41004100412020056b2005411f4b1b10171a20024180026a20032005101e1a2001200420056b22063602042001200320056a22053602000240024002400240024002400240024002402004411f4d0d00200241e0016a41186a220420024180026a41186a2203290300370300200241e0016a41106a220720024180026a41106a2208290300370300200241e0016a41086a220920024180026a41086a220a29030037030020022002290380023703e00120032004290300220b37030020082007290300220c370300200a2009290300220d370300200241c0006a41086a2204200d370300200241c0006a41106a2203200c370300200241c0006a41186a2207200b370300200220022903e001220b3703402002200b37038002200241206a41186a2007290300370300200241206a41106a2003290300370300200241206a41086a200429030037030020022002290340370320200242003703800220024180026a20052006410820064108491b2204101e1a200141046a2207200620046b22033602002001200520046a2204360200200641074d0d01200229038002210c20024180026a2003412020034120491b22056a41004100412020056b2005411f4b1b10171a20024180026a20042005101e1a2007200320056b22063602002001200420056a22043602002003411f4d0d02200241e0016a41186a220320024180026a41186a2207290300370300200241e0016a41106a220820024180026a41106a2209290300370300200241e0016a41086a220a20024180026a41086a220e29030037030020022002290380023703e00120072003290300220b37030020092008290300220d370300200e200a290300220f37030020024180016a41086a2205200f37030020024180016a41106a2210200d37030020024180016a41186a2211200b370300200220022903e001220b370380012002200b37038002200241e0006a41186a2011290300370300200241e0006a41106a2010290300370300200241e0006a41086a2005290300370300200220022903800137036020024180026a2006412020064120491b22056a41004100412020056b2005411f4b1b10171a20024180026a20042005101e1a200141046a2211200620056b22103602002001200420056a22053602002006411f4d0d032003200729030037030020082009290300370300200a200e29030037030020022002290380023703e00120072003290300220b37030020092008290300220d370300200e200a290300220f370300200241c0016a41086a2204200f370300200241c0016a41106a2203200d370300200241c0016a41186a2206200b370300200220022903e001220b3703c0012002200b37038002200241a0016a41186a2006290300370300200241a0016a41106a2003290300370300200241a0016a41086a2004290300370300200220022903c0013703a001200241003602800220024180026a20052010410420104104491b2204101e1a2011201020046b3602002001200520046a360200201041034d0d062002280280022208ad420c7e220b422088a70d08200ba72205417f4c0d072005450d042005100122070d05101c000b20024180026a41186a200241e0016a41186a29000037030020024180026a41106a200241e0016a41106a29000037030020024180026a41086a200241e0016a41086a290000370300200220022900e0013703800220004100360208200241a0026a24000f0b20004100360208200241a0026a24000f0b20024180026a41186a200241e0016a41186a29000037030020024180026a41106a200241e0016a41106a29000037030020024180026a41086a200241e0016a41086a290000370300200220022900e0013703800220004100360208200241a0026a24000f0b2007200329000037030020092008290000370300200e200a290000370300200220022900e0013703800220004100360208200241a0026a24000f0b410421070b200220083602e401200220073602e00141002105200241003602e80102402008450d00200241e8016a210941002104034020024180026a2001101f024002402002280280022203450d00200441016a2104200229028402210b200520022802e401470d01200241e0016a10182009280200210520022802e00121070c010b20022802e001210402402005450d002005410c6c21052004210103400240200141046a280200450d00200128020010020b2001410c6a2101200541746a22050d000b0b20022802e401450d03200410020c030b20072005410c6c6a2206200b370204200620033602002009200541016a220536020020042008490d000b20022802e00121070b2007450d0020022902e401210b20024180026a41186a2201200241206a41186a29030037030020024180026a41106a2205200241206a41106a29030037030020024180026a41086a2204200241206a41086a290300370300200241e0016a41086a2203200241e0006a41086a290300370300200241e0016a41106a2206200241e0006a41106a290300370300200241e0016a41186a2208200241e0006a41186a290300370300200241086a2209200241a0016a41086a290300370300200241106a220a200241a0016a41106a290300370300200241186a220e200241a0016a41186a2903003703002002200229032037038002200220022903603703e001200220022903a001370300200020073602082000200c3703002000200b37020c200041146a2002290380023702002000411c6a2004290300370200200041246a20052903003702002000412c6a2001290300370200200041346a20022903e0013702002000413c6a2003290300370200200041c4006a2006290300370200200041cc006a2008290300370200200041ec006a200e290300370200200041e4006a200a290300370200200041dc006a2009290300370200200041d4006a2002290300370200200241a0026a24000f0b20004100360208200241a0026a24000f0b101a000b101b000b0a00200020012002100a0b880201067f230041106b220224002002410036020c2002410c6a2001280200220320012802042204410420044104491b2205101e1a2001200420056b22063602042001200320056a220536020002400240024002400240200441034d0d00200228020c2204417f4c0d032004450d01200410012207450d0420074100200410171a0c020b20004100360200200241106a24000f0b410121070b200720052006200420062004491b2203101e2107200141046a200620036b3602002001200520036a3602000240200620044f0d002000410036020020071002200241106a24000f0b2000200436020420002007360200200041086a2004360200200241106a24000f0b1019000b101c000ba6c80107097f047e047f027e257f057e077f230041f0126b2202240020012001280200200128020422034104200341044922041b22056a22063602002001200320056b2203360204024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020040d00200241d8096a2003412020034120491b22046a41004100412020046b2004411f4b1b10171a200241d8096a20062004101e1a200141046a200320046b22053602002001200620046a22043602002003411f4d0d01200241086a41186a2203200241d8096a41186a2206290300370300200241086a41106a2207200241d8096a41106a2208290300370300200241086a41086a2209200241d8096a41086a220a290300370300200220022903d80937030820062003290300220b37030020082007290300220c370300200a2009290300220d370300200241e0076a41086a2203200d370300200241e0076a41106a2206200c370300200241e0076a41186a2207200b37030020022002290308220b3703e0072002200b3703d809200241c0076a41186a2007290300370300200241c0076a41106a2006290300370300200241c0076a41086a2003290300370300200220022903e0073703c00720024200370308200241086a200420054108200541084922061b2203101e1a200141046a2207200520036b22053602002001200420036a220336020020060d022002290308210e200241003a0008200241086a200320054100472204101e1a2007200520046b220f3602002001200320046a22043602002005450d184107210320022d0008221041074b0d37024020100e08000507083b090406000b200241003a0008200241086a2004200f4100472205101e1a200141046a2208200f20056b22063602002001200420056a2207360200410321094200210d20022d00084108744100200f1b2005724181fe03714101470d35200241f8096a2006412020064120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20072004101e1a2008200620046b22053602002001200720046a22043602002006411f4d0d0c200241086a41186a2206200241f8096a41186a2207290300370300200241086a41106a2208200241f8096a41106a220a290300370300200241086a41086a2211200241f8096a41086a2212290300370300200220022903f80937030820072006290300220b370300200a2008290300220c370300201220112903002213370300200241d8116a41086a22062013370300200241d8116a41106a2207200c370300200241d8116a41186a2208200b37030020022002290308220b3703d8112002200b3703f80920024198106a41186a200829030037030020024198106a41106a200729030037030020024198106a41086a2006290300370300200220022903d8113703981020024200370308200241086a200420054108200541084922071b2206101e1a200141046a2208200520066b22053602002001200420066a220636020020070d332002290308210b200241f8096a2005412020054120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20062004101e1a2008200520046b22073602002001200620046a22043602002005411f4d0d20200241086a41186a2205200241f8096a41186a2206290300370300200241086a41106a2208200241f8096a41106a220a290300370300200241086a41086a2211200241f8096a41086a2212290300370300200220022903f80937030820062005290300220c370300200a20082903002213370300201220112903002214370300200241d8116a41086a22052014370300200241d8116a41106a22062013370300200241d8116a41186a2208200c37030020022002290308220c3703d8112002200c3703f809200241b8106a41186a2008290300370300200241b8106a41106a2006290300370300200241b8106a41086a2005290300370300200220022903d8113703b810200241003a0008200241086a200420074100472205101e1a200141046a200720056b22063602002001200420056a22043602002007450d3341014102410320022d000822054112461b20054111461b22054101460d2b20054103460d3320024100360208200241086a20042006410420064104491b2205101e1a200141046a2208200620056b22073602002001200420056a2205360200200641034d0d3320022802082115200241f8096a2007412020074120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20052004101e1a2008200720046b22063602002001200520046a22083602002007411f4d0d2a200241086a41186a2216200241f8096a41186a2207290300370300200241086a41106a2217200241f8096a41106a2218290300370300200241086a41086a2219200241f8096a41086a221a290300370300200220022903f80937030820182017290300370300201a20192903003703002007201629030037030020024198126a41086a2204200241870a6a221b280000360200200220022903083703f809200220022900ff093703981220072d0000210520022800fb09211c20022d008b0a211d20022d008c0a211e20022f008d0a210a20022d008f0a211120022f00910a210f20022d00930a211220022d00940a211f20022f00950a212020022d00970a211020022f01f809212120022d00fa092122200241d8096a41086a200428020036020020022002290398123703d809200241f8096a200641c000200641c000491b22046a4100410041c00020046b2004413f4b1b10171a200241f8096a20082004101e1a200141046a2223200620046b22243602002001200820046a22253602002006413f4d0d29200241086a41386a2204200241f8096a41386a2206290300370300200241086a41306a2208200241f8096a41306a2226290300370300200241086a41286a2227200241f8096a41286a2228290300370300200241086a41206a2229200241f8096a41206a222a29030037030020162007290300370300201720182903003703002019201a290300370300200220022903f80937030820182017290300370300201a201929030037030020072016290300370300202a202929030037030020282027290300370300202620082903003703002006200429030037030020024198116a41086a2204201b29000037030020024198116a41106a22062002418f0a6a29000037030020024198116a41186a2207200241f8096a411f6a29000037030020024198116a41206a22082002419f0a6a29000037030020024198116a41286a2216200241a70a6a29000037030020024198116a41306a2217200241af0a6a29000037030020024198116a41386a2218200241f8096a413f6a2d00003a0000200220022903083703f809200220022900ff093703981120023502f809210c20023201fc09211320023100fe092114200241d8106a41086a2004290300370300200241d8106a41106a2006290300370300200241d8106a41186a2007290300370300200241d8106a41206a2008290300370300200241d8106a41286a2016290300370300200241d8106a41306a2017290300370300200241d8106a41386a20182d00003a000020022002290398113703d81020022f01e209211620022d00e109210820022d00e009211920022f01de09211720022d00dd09210720022d00dc09211820022802d809212b200241f8096a2024412020244120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20252004101e1a2023202420046b22063602002001202520046a222c3602002024411f4d0d28200241086a41186a222d200241f8096a41186a222e290300370300200241086a41106a222f200241f8096a41106a2230290300370300200241086a41086a2231200241f8096a41086a2232290300370300200220022903f8093703082030202f29030037030020322031290300370300202e202d290300370300200241b8126a41086a2204200241870a6a280000360200200220022903083703f809200220022900ff093703b812202e2d0000212620022800fb09211a20022d008b0a212420022d008c0a212520022f008d0a211b20022d008f0a212320022f00910a212720022d00930a212820022d00940a212920022f00950a212a20022d00970a213320022f01f809213420022d00fa092135200241d8096a41086a22362004280200360200200220022903b8123703d809200241f8096a200641c000200641c000491b22046a4100410041c00020046b2004413f4b1b10171a200241f8096a202c2004101e1a200141046a200620046b3602002001202c20046a3602002006413f4d0d2720212022411074722137200c201320144210868442208684210c20342035411074722106200241086a41386a2204200241f8096a41386a2221290300370300200241086a41306a2222200241f8096a41306a222c290300370300200241086a41286a2234200241f8096a41286a2235290300370300200241086a41206a2238200241f8096a41206a2239290300370300202d202e290300370300202f203029030037030020312032290300370300200220022903f809370308202120042903002213370300202c2022290300221437030020352034290300223a37030020392038290300223b370300202e202d290300223c3703002030202f290300223d37030020322031290300223e370300200241d8116a41086a223f203e370300200241d8116a41106a2240203d370300200241d8116a41186a2241203c370300200241d8116a41206a2242203b370300200241d8116a41286a2243203a370300200241d8116a41306a22442014370300200241d8116a41386a224520133703002002200229030822133703d811200220133703f809200241e0126a41086a20362802003602002031203f290300370300202f2040290300370300202d204129030037030020382042290300370300203420432903003703002022204429030037030020042045290300370300200220022903d8093703e012200220022903d8113703082021200241d8106a41386a2d00003a0000202c200241d8106a41306a2903003703002035200241d8106a41286a2903003703002039200241d8106a41206a290300370300202e200241d8106a41186a2903003703002030200241d8106a41106a2903003703002032200241d8106a41086a290300370300200220022903d8103703f809410121040c2c0b200041073a0008200241f0126a24000f0b200241d8096a41186a200241086a41186a290000370300200241d8096a41106a200241086a41106a290000370300200241d8096a41086a200241086a41086a290000370300200220022900083703d8090b410721040c380b200241003a0008200241086a2004200f4100472206101e1a200141046a200f20066b22053602002001200420066a2206360200200f450d3320022d0008220441044b0d33024020040e050019161714000b20024100360208200241086a20062005410420054104491b2207101e1a200141046a200520076b22043602002001200620076a2206360200200541034d0d332002280208220a417f4c0d22200a450d20200a100122110d21101c000b200241003a0008200241086a2004200f4100472205101e1a200141046a2208200f20056b22063602002001200420056a220736020020022d00084108744100200f1b2005724181fe03714101470d05200241f8096a20064120200641204922051b22046a41004100412020046b2004411f4b1b10171a200241f8096a20072004101e1a2008200620046b3602002001200720046a36020020050d04200241086a41186a2205200241f8096a41186a2204290300370300200241086a41106a2206200241f8096a41106a2207290300370300200241086a41086a2208200241f8096a41086a2209290300370300200220022903f809370308200720062903003703002009200829030037030020042005290300370300200241d8116a41086a2209200241870a6a280000360200200220022903083703f809200220022900ff093703d81120042d0000211120022800fb09210520022d008b0a211220022d008c0a211d20022f008d0a211620022d008f0a211720022f00910a210620022d00930a210720022d00940a211820022f00950a210a20022d00970a210820022f01f809210420022d00fa092119200241d8096a41086a22152009280200360200200220022903d8113703d809200241b00e6a41086a2015280200360200200220022903d8093703b00e20042019411074722104410121090c060b200241003a0008200241086a2004200f4100472205101e1a200141046a200f20056b22063602002001200420056a2204360200200f450d3120022d00082205450d0a20054101460d0720054102470d31200241f8096a2006412020064120491b22056a41004100412020056b2005411f4b1b10171a200241f8096a20042005101e1a200141046a200620056b3602002001200420056a3602002006411f4d0d18200241086a41186a2204200241f8096a41186a2203290300370300200241086a41106a2205200241f8096a41106a2206290300370300200241086a41086a2207200241f8096a41086a2208290300370300200220022903f809370308200620052903003703002008200729030037030020032004290300370300200241d8116a41086a2205200241870a6a280000360200200220022903083703f809200220022900ff093703d81120032d0000210720022800fb09210420022d008b0a212b20022d008c0a212020022f008d0a211f20022d008f0a211820022f00910a211720022d00930a211920022d00940a210820022f00950a211620022d00970a211d20022f01f809210320022d00fa092106200241d8096a41086a2005280200360200200220022903d8113703d8092003200641107472210520022902dc09210d20022802d809210f4103211c0c0b0b200241003a0008200241086a2004200f4100472205101e1a200141046a200f20056b22063602002001200420056a2205360200200f450d3020022d00082204450d0b20044101460d0720044102470d33410321060c080b200241003a0008200241086a2004200f4100472205101e1a200141046a2207200f20056b22063602002001200420056a220436020020022d00084108744100200f1b2005724181fe03714101470d2f20024200370308200241086a20042006410820064108491b2203101e1a2007200620036b3602002001200420036a36020041072103200641074d0d2f2002290308210d20024198096a41086a200241d8116a41086a29030037030020024198096a41106a200241d8116a41106a29030037030020024198096a41186a200241d8116a41186a29030037030020024198096a41206a200241d8116a41206a29030037030020024198096a41286a200241d8116a41286a29030037030020024198096a41306a200241d8116a41306a29030037030020024198096a41386a200241d8116a41386a2d00003a0000200220022f0198113b01d609200220022903d8113703980920024188096a41086a200241800b6a41086a280200360200200241c8086a41086a200241086a41086a290000370300200241c8086a41106a200241086a41106a290000370300200241c8086a41186a200241086a41186a290000370300200241c8086a41206a200241086a41206a290000370300200241c8086a41286a200241086a41286a290000370300200241c8086a41306a200241086a41306a290000370300200241c8086a41386a200241086a41386a290000370300200220022903800b37038809200220022900083703c808200241c4086a41026a200241f8096a41026a2d00003a0000200241a0086a41186a200241b00e6a41186a290300370300200241a0086a41106a200241b00e6a41106a290300370300200241a0086a41086a200241b00e6a41086a29030037030020024180086a41186a200241d80c6a41186a29030037030020024180086a41106a200241d80c6a41106a29030037030020024180086a41086a200241d80c6a41086a290300370300200220022f00f8093b01c408200220022903b00e3703a008200220022903d80c37038008410321034201210b0c0e0b200241003a0008200241086a2004200f4100472205101e1a200141046a200f20056b22063602002001200420056a2204360200200f450d2e20022d00082205450d0b20054101460d0a20054102470d2e20024100360208200241086a20042006410420064104491b2205101e1a200141046a2208200620056b22073602002001200420056a2205360200200641034d0d2e20022802082104200241003a0008200241086a200520074100472206101e1a2008200720066b3602002001200520066a3602002007450d2e2002310008420183210b410321030c0c0b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090b410221090b200241870a6a200241b00e6a41086a280200360000200220053600fb09200220123a008b0a2002201d3a008c0a200220163b008d0a200220173a008f0a200220113a00900a200220063b00910a200220073a00930a200220183a00940a2002200a3b00950a200220083a00970a200220022903b00e3700ff09200220043b01f809200220044110763a00fa0920094102460d2b200220022f01f8093b01d609200241940a6a2f0100211720022901fe09210b20022901860a210d200228018e0a212b20024198096a41386a200241d8116a41386a2d00003a000020024198096a41306a200241d8116a41306a29010037030020024198096a41286a200241d8116a41286a29010037030020024198096a41206a200241d8116a41206a29010037030020024198096a41186a200241d8116a41186a29010037030020024198096a41106a200241d8116a41106a29010037030020024198096a41086a200241d8116a41086a29010037030020024188096a41086a200241800b6a41086a280100360200200220022901d81137039809200220022901800b37038809200241c8086a41386a200241086a41386a290000370300200241c8086a41306a200241086a41306a290000370300200241c8086a41286a200241086a41286a290000370300200241c8086a41206a200241086a41206a290000370300200241c8086a41186a200241086a41186a290000370300200241c8086a41106a200241086a41106a290000370300200241c8086a41086a200241086a41086a290000370300200241c4086a41026a200241f8096a41026a2d00003a0000200220022900083703c808200220022f00f8093b01c408200241a0086a41186a200241b00e6a41186a290100370300200241a0086a41106a200241b00e6a41106a290100370300200241a0086a41086a200241b00e6a41086a29010037030020024180086a41186a200241d80c6a41186a29010037030020024180086a41106a200241d80c6a41106a29010037030020024180086a41086a200241d80c6a41086a290100370300200220022901b00e3703a008200220022901d80c37038008202b411076211f202b41087621202004418080fc0771411076211c20064180fe03714108762118200a4180fe03714108762119410121030c2e0b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c260b200241f8096a2006412020064120491b22056a41004100412020056b2005411f4b1b10171a200241f8096a20042005101e1a200141046a220a200620056b22093602002001200420056a22053602002006411f4d0d0f200241086a41186a2206200241f8096a41186a2204290300370300200241086a41106a2207200241f8096a41106a2208290300370300200241086a41086a2211200241f8096a41086a2212290300370300200220022903f809370308200820072903003703002012201129030037030020042006290300370300200241d8116a41086a2206200241870a6a280000360200200220022903083703f809200220022900ff093703d81120042d0000210720022800fb09210420022d008b0a212b20022d008c0a212020022f008d0a211f20022d008f0a211820022f00910a211720022d00930a211920022d00940a210820022f00950a211620022d00970a211d20022f01f809211120022d00fa092112200241d8096a41086a2006280200360200200220022903d8113703d809200241003a0008200241086a200520094100472206101e1a200a200920066b3602002001200520066a3602002009450d292011201241107472210520022d0008410171211e20022902dc09210d20022802d809210f4102211c0c030b410221060b0c220b4101211c200110212204450d290b20024198096a41086a200241d8116a41086a29030037030020024198096a41106a200241d8116a41106a29030037030020024198096a41186a200241d8116a41186a29030037030020024198096a41206a200241d8116a41206a29030037030020024198096a41286a200241d8116a41286a29030037030020024198096a41306a200241d8116a41306a29030037030020024198096a41386a200241d8116a41386a2d00003a0000200220022f0198113b01d609200220022903d8113703980920024188096a41086a200241800b6a41086a280200360200200241c8086a41086a200241086a41086a290000370300200241c8086a41106a200241086a41106a290000370300200241c8086a41186a200241086a41186a290000370300200241c8086a41206a200241086a41206a290000370300200241c8086a41286a200241086a41286a290000370300200241c8086a41306a200241086a41306a290000370300200241c8086a41386a200241086a41386a290000370300200220022903800b37038809200220022900083703c808200241c4086a41026a200241f8096a41026a2d00003a0000200241a0086a41186a200241b00e6a41186a290300370300200241a0086a41106a200241b00e6a41106a290300370300200241a0086a41086a200241b00e6a41086a29030037030020024180086a41186a200241d80c6a41186a29030037030020024180086a41106a200241d80c6a41106a29030037030020024180086a41086a200241d80c6a41086a290300370300200220022f00f8093b01c408200220022903b00e3703a008200220022903d80c37038008200fad4220862004ad84210b410621030c270b200241f8096a2006412020064120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20052004101e1a200141046a2212200620046b22093602002001200520046a22113602002006411f4d0d0c200241086a41186a2204200241f8096a41186a2203290300370300200241086a41106a2205200241f8096a41106a2206290300370300200241086a41086a2207200241f8096a41086a2208290300370300200220022903f809370308200620052903003703002008200729030037030020032004290300370300200241d8116a41086a2206200241870a6a280000360200200220022903083703f809200220022900ff093703d81120032d0000210820022800fb09210520022d008b0a211820022d008c0a210720022f008d0a211720022d008f0a211920022f00910a211620022d00930a211d20022d00940a211e20022f00950a210a20022d00970a210420022f01f809211520022d00fa09211a200241d8096a41086a2006280200360200200220022903d8113703d80920024200370308200241086a20112009410820094108491b2203101e1a2012200920036b3602002001201120036a36020041072103200941074d0d242015201a4110747221092002290308210c20022802e009212b20022903d809210d410121060c1f0b20024100360208200241086a20042006410420064104491b2205101e1a200141046a200620056b3602002001200420056a360200200641034d0d2320022802082104410221034200210b0c010b200110212204450d22200220043602d8104200210b20024200370308200241086a20012802002206200141046a22072802002205410820054108491b2203101e1a2007200520036b3602002001200620036a36020041072103200541074d0d0d2002290308210d410121030b20024198096a41086a200241d8116a41086a29030037030020024198096a41106a200241d8116a41106a29030037030020024198096a41186a200241d8116a41186a29030037030020024198096a41206a200241d8116a41206a29030037030020024198096a41286a200241d8116a41286a29030037030020024198096a41306a200241d8116a41306a29030037030020024198096a41386a200241d8116a41386a2d00003a0000200220022f0198113b01d609200220022903d8113703980920024188096a41086a200241800b6a41086a280200360200200241c8086a41086a200241086a41086a290000370300200241c8086a41106a200241086a41106a290000370300200241c8086a41186a200241086a41186a290000370300200241c8086a41206a200241086a41206a290000370300200241c8086a41286a200241086a41286a290000370300200241c8086a41306a200241086a41306a290000370300200241c8086a41386a200241086a41386a290000370300200220022903800b37038809200220022900083703c808200241c4086a41026a200241f8096a41026a2d00003a0000200241a0086a41186a200241b00e6a41186a290300370300200241a0086a41106a200241b00e6a41106a290300370300200241a0086a41086a200241b00e6a41086a29030037030020024180086a41186a200241d80c6a41186a29030037030020024180086a41106a200241d80c6a41106a29030037030020024180086a41086a200241d80c6a41086a290300370300200220022f00f8093b01c408200220022903b00e3703a008200220022903d80c37038008200b2004ad42188684420886200341ff0171ad84210b410421030b4100211f410021200c210b200241f8096a2005412020054120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20062004101e1a200141046a2212200520046b22093602002001200620046a22043602002005411f4d0d09200241086a41186a2205200241f8096a41186a2203290300370300200241086a41106a2206200241f8096a41106a2207290300370300200241086a41086a2208200241f8096a41086a220a290300370300200220022903f80937030820072006290300370300200a200829030037030020032005290300370300200241d8116a41086a2206200241870a6a280000360200200220022903083703f809200220022900ff093703d81120032d0000210820022800fb09210520022d008b0a211820022d008c0a210720022f008d0a211720022d008f0a211920022f00910a211620022d00930a211d20022d00940a211e20022f00950a210a20022d00970a211120022f01f809211520022d00fa09211a200241d8096a41086a2006280200360200200220022903d8113703d80920024200370308200241086a20042009410820094108491b2203101e1a2012200920036b22063602002001200420036a2203360200200941074d0d002002290308210c20024100360208200241086a20032006410420064104491b2204101e1a200141046a200620046b3602002001200320046a360200200641034d0d002015201a4110747221032002280208211220022802e009212b20022903d809210d410521040c190b410721030c1e0b20024100360208200241086a20062005410420054104491b2204101e1a200141046a200520046b3602002001200620046a36020041032104200541034d0d1d0c010b2002410036020841042104200241086a20062005410420054104491b2207101e1a200141046a200520076b3602002001200620076a360200200541034d0d1c0b200228020821050c150b20024100360208200241086a20062005410420054104491b2204101e1a200141046a2208200520046b22073602002001200620046a2206360200200541034d0d1a20022802082112200241f8096a2007412020074120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20062004101e1a2008200720046b22093602002001200620046a22043602002007411f4d0d06200241086a41186a2206200241f8096a41186a2205290300370300200241086a41106a2207200241f8096a41106a2208290300370300200241086a41086a220a200241f8096a41086a2211290300370300200220022903f809370308200820072903003703002011200a29030037030020052006290300370300200241d8116a41086a2206200241870a6a280000360200200220022903083703f809200220022900ff093703d81120052d0000210820022800fb09210520022d008b0a211820022d008c0a210720022f008d0a211720022d008f0a211920022f00910a211620022d00930a211d20022d00940a211e20022f00950a210a20022d00970a211120022f01f809212420022d00fa092125200241d8096a41086a2006280200360200200220022903d8113703d80920024100360208200241086a20042009410420094104491b2206101e1a200141046a221a200920066b22153602002001200420066a2204360200200941034d0d1a2002350208210b20024100360208200241086a20042015410420154104491b2206101e1a201a201520066b3602002001200420066a360200201541034d0d1a202420254110747221032002350208422086200b84210c20022802e009212b20022903d809210d410221040c140b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c190b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c180b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c170b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c120b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c150b200241d8106a10220c140b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c130b410121110b2002200a36020c20022011360208200241003602100240200a450d00200141046a211d200241106a211241002105410021080340200241003a00d811200241d8116a200620044100472207101e1a201d200420076b22093602002001200620076a2206360200024002402004450d00200841016a210820022d00d81141017121042005200228020c470d01200241086a102320122802002105200228020821110c010b200228020c450d14201110020c140b201120056a20043a00002012200541016a2205360200200921042008200a490d000b200228020821110b2011450d112011410020111b2105200229020c210d20024100360208200241086a20012802002207200141046a22082802002204410420044104491b2206101e1a2008200420066b3602002001200720066a3602000240200441034d0d002002280208212b410121040c0c0b200da7450d11200510020c110b1024000b200241f8096a41386a200241086a41386a290000370300200241f8096a41306a200241086a41306a290000370300200241f8096a41286a200241086a41286a290000370300200241f8096a41206a200241086a41206a290000370300202e202d2900003703002030202f29000037030020322031290000370300200220022900083703f8090c0b0b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c0a0b200241f8096a41386a200241086a41386a290000370300200241f8096a41306a200241086a41306a290000370300200241f8096a41286a200241086a41286a290000370300200241f8096a41206a200241086a41206a2900003703002007201629000037030020182017290000370300201a2019290000370300200220022900083703f8090c090b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c080b20024100360208200241086a20042006410420064104491b2205101e1a200141046a2208200620056b22073602002001200420056a2205360200200641034d0d0720022802082115200241f8096a2007412020074120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20052004101e1a2008200720046b22063602002001200520046a22253602002007411f4d0d01200241086a41186a221b200241f8096a41186a221a290300370300200241086a41106a2223200241f8096a41106a2224290300370300200241086a41086a2226200241f8096a41086a2227290300370300200220022903f80937030820242023290300370300201a201b29030037030020272026290300370300200220022903083703f80920242d00002108201a2d0000210520022800fb09211c20022800ff09212b20022d00830a211820022d00840a210720022f00850a211720022d00870a211920022f00890a211620022d008b0a211d20022d008c0a211e20022f008d0a210a20022d008f0a211120022f00910a210f20022d00930a211220022d00940a211f20022f00950a212020022d00970a211020022f01f809212a20022d00fa092133200241f8096a200641c000200641c0004922281b22046a4100410041c00020046b2004413f4b1b10171a200241f8096a20252004101e1a200141046a2229200620046b22063602002001202520046a222536020020280d02200241086a41386a2204200241f8096a41386a2228290300370300200241086a41306a222e200241f8096a41306a2221290300370300200241086a41286a2222200241f8096a41286a222c290300370300200241086a41206a222d200241f8096a41206a222f290300370300201b201a2903003703002023202429030037030020262027290300370300200220022903f8093703082024202329030037030020272026290300370300201a201b290300370300202f202d290300370300202c20222903003703002021202e2903003703002028200429030037030020024198116a41086a2204200241870a6a29000037030020024198116a41106a221a2002418f0a6a29000037030020024198116a41186a2224200241f8096a411f6a29000037030020024198116a41206a221b2002419f0a6a29000037030020024198116a41286a2223200241a70a6a29000037030020024198116a41306a2226200241af0a6a29000037030020024198116a41386a2227200241f8096a413f6a2d00003a0000200220022903083703f809200220022900ff093703981120023502f809210c20023201fc09211320023100fe092114200241d8106a41386a20272d00003a0000200241d8106a41306a2026290300370300200241d8106a41286a2023290300370300200241d8106a41206a201b290300370300200241d8106a41186a2024290300370300200241d8106a41106a201a290300370300200241d8106a41086a200429030037030020022002290398113703d810200241f8096a2006412020064120491b22046a41004100412020046b2004411f4b1b10171a200241f8096a20252004101e1a2029200620046b221a3602002001202520046a22243602002006411f4d0d03200241086a41186a2225200241f8096a41186a222e290300370300200241086a41106a221b200241f8096a41106a2221290300370300200241086a41086a2223200241f8096a41086a2222290300370300200220022903f809370308202e2025290300223a3703002021201b290300223b37030020222023290300223c370300200241b8126a41086a2204203c370300200241b8126a41106a2206203b370300200241b8126a41186a2226203a37030020022002290308223a3703b8122002203a3703f809200241d8096a41186a2026290300370300200241d8096a41106a2006290300370300200241d8096a41086a2004290300370300200220022903b8123703d80941002104200241f8096a201a41c000201a41c000491b22066a4100410041c00020066b2006413f4b1b10171a200241f8096a20242006101e1a200141046a201a20066b3602002001202420066a360200201a413f4d0d04202a2033411074722137200c201320144210868442208684210c200241086a41386a2206200241f8096a41386a222c290300370300200241086a41306a221a200241f8096a41306a222d290300370300200241086a41286a2224200241f8096a41286a222f290300370300200241086a41206a2226200241f8096a41206a22302903003703002025202e290300370300201b202129030037030020232022290300370300200220022903f809370308202c20062903002213370300202d201a2903002214370300202f2024290300223a37030020302026290300223b370300202e2025290300223c3703002021201b290300223d37030020222023290300223e370300200241d8116a41086a2227203e370300200241d8116a41106a2228203d370300200241d8116a41186a2229203c370300200241d8116a41206a222a203b370300200241d8116a41286a2233203a370300200241d8116a41306a22312014370300200241d8116a41386a223220133703002002200229030822133703d811200220133703f809200241e0126a41086a200241e7096a28000036020020232027290300370300201b2028290300370300202520292903003703002026202a29030037030020242033290300370300201a203129030037030020062032290300370300200220022900df093703e012200220022903d81137030820022800db09211a20022d00eb09212420022d00ec09212520022f00ed09211b20022d00ef09212320022d00f009212620022f00f109212720022d00f309212820022d00f409212920022f00f509212a20022d00f709213320022f01d809210620022d00da092131202c200241d8106a41386a2d00003a0000202d200241d8106a41306a290300370300202f200241d8106a41286a2903003703002030200241d8106a41206a290300370300202e200241d8106a41186a2903003703002021200241d8106a41106a2903003703002022200241d8106a41086a290300370300200220022903d8103703f809200620314110747221060b20024198116a41386a200241f8096a41386a2d00003a000020024198116a41306a200241f8096a41306a29030037030020024198116a41286a200241f8096a41286a29030037030020024198116a41206a200241f8096a41206a29030037030020024198116a41186a200241f8096a41186a29030037030020024198116a41106a200241f8096a41106a29030037030020024198116a41086a200241f8096a41086a29030037030020024188106a41086a200241e0126a41086a280200360200200220022903f80937039811200220022903e01237038810200241d8116a41386a200241086a41386a290300370300200241d8116a41306a200241086a41306a290300370300200241d8116a41286a200241086a41286a290300370300200241d8116a41206a200241086a41206a290300370300200241d8116a41186a200241086a41186a290300370300200241d8116a41106a200241086a41106a290300370300200241d8116a41086a200241086a41086a29030037030020024184106a41026a200241d8106a41026a2d00003a0000200220022903083703d811200220022f00d8103b018410200241e00f6a41186a20024198106a41186a290300370300200241e00f6a41106a20024198106a41106a290300370300200241e00f6a41086a20024198106a41086a29030037030020022002290398103703e00f200241c00f6a41186a200241b8106a41186a290300370300200241c00f6a41106a200241b8106a41106a290300370300200241c00f6a41086a200241b8106a41086a290300370300200220022903b8103703c00f0c070b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c050b200241f8096a41386a200241086a41386a290000370300200241f8096a41306a200241086a41306a290000370300200241f8096a41286a200241086a41286a290000370300200241f8096a41206a200241086a41206a290000370300201a201b2900003703002024202329000037030020272026290000370300200220022900083703f8090c040b200241f8096a41186a200241086a41186a290000370300200241f8096a41106a200241086a41106a290000370300200241f8096a41086a200241086a41086a290000370300200220022900083703f8090c030b200241f8096a41386a200241086a41386a290000370300200241f8096a41306a200241086a41306a290000370300200241f8096a41286a200241086a41286a290000370300200241f8096a41206a200241086a41206a290000370300202e20252900003703002021201b29000037030020222023290000370300200220022900083703f8090c020b20024198096a41086a200241d8116a41086a29030037030020024198096a41106a200241d8116a41106a29030037030020024198096a41186a200241d8116a41186a29030037030020024198096a41206a200241d8116a41206a29030037030020024198096a41286a200241d8116a41286a29030037030020024198096a41306a200241d8116a41306a29030037030020024198096a41386a200241d8116a41386a2d00003a0000200220022f0198113b01d609200220022903d8113703980920024188096a41086a200241800b6a41086a280200360200200241c8086a41086a200241086a41086a290000370300200241c8086a41106a200241086a41106a290000370300200241c8086a41186a200241086a41186a290000370300200241c8086a41206a200241086a41206a290000370300200241c8086a41286a200241086a41286a290000370300200241c8086a41306a200241086a41306a290000370300200241c8086a41386a200241086a41386a290000370300200220022903800b37038809200220022900083703c808200241c4086a41026a200241f8096a41026a2d00003a0000200241a0086a41186a200241b00e6a41186a290300370300200241a0086a41106a200241b00e6a41106a290300370300200241a0086a41086a200241b00e6a41086a29030037030020024180086a41186a200241d80c6a41186a29030037030020024180086a41106a200241d80c6a41106a29030037030020024180086a41086a200241d80c6a41086a290300370300200220022f00f8093b01c408200220022903b00e3703a008200220022903d80c370380082005ad421886200341ffffff0771ad84420886200441ff0171ad84210b202b411076211f202b4108762120410521030c060b20024198096a41086a200241d8116a41086a29030037030020024198096a41106a200241d8116a41106a29030037030020024198096a41186a200241d8116a41186a29030037030020024198096a41206a200241d8116a41206a29030037030020024198096a41286a200241d8116a41286a29030037030020024198096a41306a200241d8116a41306a29030037030020024198096a41386a200241d8116a41386a2d00003a0000200220022f0198113b01d609200220022903d8113703980920024188096a41086a200241800b6a41086a280200360200200241c8086a41086a200241086a41086a290000370300200241c8086a41106a200241086a41106a290000370300200241c8086a41186a200241086a41186a290000370300200241c8086a41206a200241086a41206a290000370300200241c8086a41286a200241086a41286a290000370300200241c8086a41306a200241086a41306a290000370300200241c8086a41386a200241086a41386a290000370300200220022903800b37038809200220022900083703c80841022103200241c4086a41026a200241f8096a41026a2d00003a0000200241a0086a41186a200241b00e6a41186a290300370300200241a0086a41106a200241b00e6a41106a290300370300200241a0086a41086a200241b00e6a41086a29030037030020024180086a41186a200241d80c6a41186a29030037030020024180086a41106a200241d80c6a41106a29030037030020024180086a41086a200241d80c6a41086a290300370300200220022f00f8093b01c408200220022903b00e3703a008200220022903d80c370380082005ad421886200941ffffff0771ad84420886200641ff0171ad84210b202b411076211f202b4108762120200441ff017121110c050b410221040b200241f8096a41386a222e20024198116a41386a2d00003a0000200241f8096a41306a222120024198116a41306a290300370300200241f8096a41286a222220024198116a41286a290300370300200241f8096a41206a222c20024198116a41206a290300370300200241f8096a41186a222d20024198116a41186a290300370300200241f8096a41106a222f20024198116a41106a290300370300200241f8096a41086a223020024198116a41086a290300370300200241e0126a41086a223120024188106a41086a28020036020020022002290398113703f80920022002290388103703e012200241086a41386a2232200241d8116a41386a290300370300200241086a41306a2234200241d8116a41306a290300370300200241086a41286a2235200241d8116a41286a290300370300200241086a41206a2236200241d8116a41206a290300370300200241086a41186a2238200241d8116a41186a290300370300200241086a41106a2239200241d8116a41106a290300370300200241086a41086a223f200241d8116a41086a290300370300200241dc126a41026a20024184106a41026a2d00003a0000200220022903d811370308200220022f0184103b01dc12200241b8126a41186a2240200241e00f6a41186a290300370300200241b8126a41106a2241200241e00f6a41106a290300370300200241b8126a41086a2242200241e00f6a41086a29030037030020024198126a41186a2243200241c00f6a41186a29030037030020024198126a41106a2244200241c00f6a41106a29030037030020024198126a41086a2245200241c00f6a41086a290300370300200220022903e00f3703b812200220022903c00f370398120240024020044102470d004102210441024102470d010c020b200241800f6a41386a202e2d00003a0000200241800f6a41306a2021290300370300200241800f6a41286a2022290300370300200241800f6a41206a202c290300370300200241800f6a41186a202d290300370300200241800f6a41106a202f290300370300200241800f6a41086a2030290300370300200241f00e6a41086a2031280200360200200220022903f8093703800f200220022903e0123703f00e200241b00e6a41386a2032290300370300200241b00e6a41306a2034290300370300200241b00e6a41286a2035290300370300200241b00e6a41206a2036290300370300200241b00e6a41186a2038290300370300200241b00e6a41106a2039290300370300200241b00e6a41086a203f290300370300200241ac0e6a41026a200241dc126a41026a2d00003a0000200220022903083703b00e200220022f01dc123b01ac0e200241880e6a41186a2040290300370300200241880e6a41106a2041290300370300200241880e6a41086a2042290300370300200220022903b8123703880e200241e80d6a41186a2043290300370300200241e80d6a41106a2044290300370300200241e80d6a41086a204529030037030020022002290398123703e80d200c420886201041ff0171ad84210c2020411074201f41ff017141087472201241ff0171722112200f411074200541ff017141087472201141ff017172211120044102460d010b20024198116a41386a200241800f6a41386a2d00003a000020024198116a41306a200241800f6a41306a29030037030020024198116a41286a200241800f6a41286a29030037030020024198116a41206a200241800f6a41206a29030037030020024198116a41186a200241800f6a41186a29030037030020024198116a41106a200241800f6a41106a29030037030020024198116a41086a200241800f6a41086a29030037030020024188106a41086a200241f00e6a41086a280200360200200220022903800f37039811200220022903f00e37038810200241d8116a41386a200241b00e6a41386a290300370300200241d8116a41306a200241b00e6a41306a290300370300200241d8116a41286a200241b00e6a41286a290300370300200241d8116a41206a200241b00e6a41206a290300370300200241d8116a41186a200241b00e6a41186a290300370300200241d8116a41106a200241b00e6a41106a290300370300200241d8116a41086a200241b00e6a41086a29030037030020024184106a41026a200241ac0e6a41026a2d00003a0000200220022903b00e3703d811200220022f01ac0e3b018410200241e00f6a41186a200241880e6a41186a290300370300200241e00f6a41106a200241880e6a41106a290300370300200241e00f6a41086a200241880e6a41086a290300370300200220022903880e3703e00f200241c00f6a41186a200241e80d6a41186a290300370300200241c00f6a41106a200241e80d6a41106a290300370300200241c00f6a41086a200241e80d6a41086a290300370300200220022903e80d3703c00f201cad421886203741ffffff0771ad84420886210d0c010b410321040b200241f8096a41386a220520024198116a41386a2d00003a0000200241f8096a41306a221c20024198116a41306a290300370300200241f8096a41286a220f20024198116a41286a290300370300200241f8096a41206a221f20024198116a41206a290300370300200241f8096a41186a222020024198116a41186a290300370300200241f8096a41106a221020024198116a41106a290300370300200241f8096a41086a20024198116a41086a290300370300200241e0126a41086a20024188106a41086a28020036020020022002290398113703f80920022002290388103703e012200241086a41386a222e200241d8116a41386a290300370300200241086a41306a2221200241d8116a41306a290300370300200241086a41286a2222200241d8116a41286a290300370300200241086a41206a222c200241d8116a41206a290300370300200241086a41186a222d200241d8116a41186a290300370300200241086a41106a222f200241d8116a41106a290300370300200241086a41086a200241d8116a41086a290300370300200241dc126a41026a223020024184106a41026a2d00003a0000200220022903d811370308200220022f0184103b01dc12200241b8126a41186a2231200241e00f6a41186a290300370300200241b8126a41106a2232200241e00f6a41106a290300370300200241b8126a41086a200241e00f6a41086a29030037030020024198126a41186a2234200241c00f6a41186a29030037030020024198126a41106a2235200241c00f6a41106a29030037030020024198126a41086a200241c00f6a41086a290300370300200220022903e00f3703b812200220022903c00f37039812024020044103460d00200241a80d6a41386a20052d00003a0000200241a80d6a41306a201c290300370300200241a80d6a41286a200f290300370300200241a80d6a41206a201f290300370300200241a80d6a41186a2020290300370300200241a80d6a41106a2010290300370300200241a80d6a41086a200241f8096a41086a290300370300200241980d6a41086a200241e0126a41086a280200360200200220022903f8093703a80d200220022903e0123703980d200241d80c6a41386a202e290300370300200241d80c6a41306a2021290300370300200241d80c6a41286a2022290300370300200241d80c6a41206a202c290300370300200241d80c6a41186a202d290300370300200241d80c6a41106a202f290300370300200241d80c6a41086a200241086a41086a290300370300200241d40c6a41026a20302d00003a0000200220022903083703d80c200220022f01dc123b01d40c200241b00c6a41186a2031290300370300200241b00c6a41106a2032290300370300200241b00c6a41086a200241b8126a41086a290300370300200220022903b8123703b00c200241900c6a41186a2034290300370300200241900c6a41106a2035290300370300200241900c6a41086a20024198126a41086a29030037030020022002290398123703900c200421090b20094103460d0020024198096a41086a200241a80d6a41086a29030037030020024198096a41106a200241a80d6a41106a29030037030020024198096a41186a200241a80d6a41186a29030037030020024198096a41206a200241a80d6a41206a29030037030020024198096a41286a200241a80d6a41286a29030037030020024198096a41306a200241a80d6a41306a29030037030020024198096a41386a200241a80d6a41386a2d00003a0000200220022f018e0c3b01d609200220022903a80d3703980920024188096a41086a200241980d6a41086a280200360200200241c8086a41086a200241d80c6a41086a290300370300200241c8086a41106a200241d80c6a41106a290300370300200241c8086a41186a200241d80c6a41186a290300370300200241c8086a41206a200241d80c6a41206a290300370300200241c8086a41286a200241d80c6a41286a290300370300200241c8086a41306a200241d80c6a41306a290300370300200241c8086a41386a200241d80c6a41386a290300370300200220022903980d37038809200220022903d80c3703c808200241c4086a41026a200241d40c6a41026a2d00003a0000200241a0086a41186a200241b00c6a41186a290300370300200241a0086a41106a200241b00c6a41106a290300370300200241a0086a41086a200241b00c6a41086a29030037030020024180086a41186a200241900c6a41186a29030037030020024180086a41106a200241900c6a41106a29030037030020024180086a41086a200241900c6a41086a290300370300200220022f01d40c3b01c408200220022903b00c3703a008200220022903900c37038008202b411076211f202b4108762120200d200941ff0171ad84210d410021030c010b0c020b0b0b200241d00b6a41086a220f20024198096a41086a290300370300200241d00b6a41106a221020024198096a41106a290300370300200241d00b6a41186a222e20024198096a41186a290300370300200241d00b6a41206a222120024198096a41206a290300370300200241d00b6a41286a222220024198096a41286a290300370300200241d00b6a41306a222c20024198096a41306a290300370300200241d00b6a41386a222d20024198096a41386a2d00003a0000200220022f01d6093b018e0c20022002290398093703d00b200241c00b6a41086a222f20024188096a41086a280200360200200241800b6a41086a2230200241c8086a41086a290300370300200241800b6a41106a2231200241c8086a41106a290300370300200241800b6a41186a2232200241c8086a41186a290300370300200241800b6a41206a2234200241c8086a41206a290300370300200241800b6a41286a2235200241c8086a41286a290300370300200241800b6a41306a2236200241c8086a41306a290300370300200241800b6a41386a2238200241c8086a41386a29030037030020022002290388093703c00b200220022903c8083703800b200241fc0a6a41026a2239200241c4086a41026a2d00003a0000200241d80a6a41186a223f200241a0086a41186a290300370300200241d80a6a41106a2240200241a0086a41106a290300370300200241d80a6a41086a2241200241a0086a41086a290300370300200241b80a6a41186a224220024180086a41186a290300370300200241b80a6a41106a224320024180086a41106a290300370300200241b80a6a41086a224420024180086a41086a290300370300200220022f01c4083b01fc0a200220022903a0083703d80a20022002290380083703b80a4107210420034107460d00200241d80c6a41086a200f290300370300200241d80c6a41106a2010290300370300200241d80c6a41186a202e290300370300200241d80c6a41206a2021290300370300200241d80c6a41286a2022290300370300200241d80c6a41306a202c290300370300200241d80c6a41386a202d2d00003a0000200220022f018e0c3b01c00f200220022903d00b3703d80c200241b8126a41086a202f280200360200200241d8116a41086a2030290300370300200241d8116a41106a2031290300370300200241d8116a41186a2032290300370300200241d8116a41206a2034290300370300200241d8116a41286a2035290300370300200241d8116a41306a2036290300370300200241d8116a41386a2038290300370300200220022903c00b3703b812200220022903800b3703d81120024198126a41026a20392d00003a000020024198116a41186a203f29030037030020024198116a41106a204029030037030020024198116a41086a2041290300370300200241800f6a41186a2042290300370300200241800f6a41106a2043290300370300200241800f6a41086a2044290300370300200220022f01fc0a3b019812200220022903d80a37039811200220022903b80a3703800f200241a80d6a41186a200241c0076a41186a290300370300200241a80d6a41106a200241c0076a41106a290300370300200241a80d6a41086a200241c0076a41086a290300370300200220022903c0073703a80d201f411074202041ff017141087472202b41ff017172210f200321040c010b0b200241b00e6a41086a222b200241d80c6a41086a290300370300200241b00e6a41106a221f200241d80c6a41106a290300370300200241b00e6a41186a2220200241d80c6a41186a290300370300200241b00e6a41206a2210200241d80c6a41206a290300370300200241b00e6a41286a222e200241d80c6a41286a290300370300200241b00e6a41306a2221200241d80c6a41306a290300370300200241b00e6a41386a2222200241d80c6a41386a2d00003a0000200220022f01c00f3b01e00f200220022903d80c3703b00e200241d00b6a41086a222c200241b8126a41086a280200360200200241086a41086a222d200241d8116a41086a290300370300200241086a41106a222f200241d8116a41106a290300370300200241086a41186a2230200241d8116a41186a290300370300200241086a41206a2231200241d8116a41206a290300370300200241086a41286a2232200241d8116a41286a290300370300200241086a41306a2234200241d8116a41306a290300370300200241086a41386a2235200241d8116a41386a290300370300200220022903b8123703d00b200220022903d81137030820024198096a41026a223620024198126a41026a2d00003a0000200241800b6a41186a223820024198116a41186a290300370300200241800b6a41106a223920024198116a41106a290300370300200241800b6a41086a223f20024198116a41086a290300370300200241f8096a41186a2240200241800f6a41186a290300370300200241f8096a41106a2241200241800f6a41106a290300370300200241f8096a41086a2242200241800f6a41086a290300370300200220022f0198123b01980920022002290398113703800b200220022903800f3703f809200241c8086a41186a2243200241a80d6a41186a290300370300200241c8086a41106a2244200241a80d6a41106a290300370300200241c8086a41086a2245200241a80d6a41086a290300370300200220022903a80d3703c80841072103024020044107460d0020024180076a41086a202b29030037030020024180076a41106a201f29030037030020024180076a41186a202029030037030020024180076a41206a201029030037030020024180076a41286a202e29030037030020024180076a41306a202129030037030020024180076a41386a20222d00003a0000200220022f01e00f3b01be07200220022903b00e37038007200241f0066a41086a202c280200360200200241b0066a41086a202d290300370300200241b0066a41106a202f290300370300200241b0066a41186a2030290300370300200241b0066a41206a2031290300370300200241b0066a41286a2032290300370300200241b0066a41306a2034290300370300200241b0066a41386a2035290300370300200220022903d00b3703f006200220022903083703b006200241ac066a41026a20362d00003a000020024188066a41186a203829030037030020024188066a41106a203929030037030020024188066a41086a203f290300370300200241e8056a41186a2040290300370300200241e8056a41106a2041290300370300200241e8056a41086a2042290300370300200220022f0198093b01ac06200220022903800b37038806200220022903f8093703e805200241c8056a41186a2043290300370300200241c8056a41106a2044290300370300200241c8056a41086a2045290300370300200220022903c8083703c805200421030b024020034107470d00200041073a0008200241f0126a24000f0b20024197036a20054110763a000020024195036a20053b000020024191036a20093a000020024192036a20022f01be073b010020024194036a201c3a000020024188036a41106a2209200b37030020024188036a41186a200d37030020024188036a41206a200f360200200241ac036a20183a0000200241ad036a20073a0000200241ae036a20173b010020024188036a41286a20193a0000200241b1036a20083a0000200241b2036a20163b0100200241b4036a201d3a0000200241b5036a201e3a0000200241b6036a200a3b0100200220033a0090032002200e37038803200241bc036a201236020020024188036a41306a201136020020024188036a41386a200c37030020024188036a41c0006a200229038007370300200241d0036a20024180076a41086a290300370300200241d8036a20024180076a41106a290300370300200241e0036a20024180076a41186a290300370300200241e8036a20024180076a41206a290300370300200241f0036a20024180076a41286a290300370300200241f8036a20024180076a41306a29030037030020024180046a20024180076a41386a2d00003a000020024183046a20064110763a000020024181046a20063b000020024184046a201a36020020024194046a20243a000020024195046a20253a000020024196046a201b3b010020024198046a20233a000020024199046a20263a00002002419a046a20273b01002002419c046a20283a00002002419d046a20293a00002002419e046a202a3b0100200241a0046a20333a000020024190046a200241f0066a41086a28020036020020024188046a20022903f006370300200241d9046a200241b0066a41386a290300370000200241d1046a200241b0066a41306a290300370000200241c9046a200241b0066a41286a290300370000200241c1046a200241b0066a41206a290300370000200241b9046a200241b0066a41186a290300370000200241b1046a200241b0066a41106a290300370000200241a9046a200241b0066a41086a290300370000200241a1046a20022903b006370000200241e3046a200241ae066a2d00003a0000200241e1046a20022f01ac063b0000200241e4046a201536020020024180056a20024188066a41186a290300370300200241f8046a20024188066a41106a290300370300200241f0046a20024188066a41086a290300370300200241e8046a200229038806370300200241a0056a200241e8056a41186a29030037030020024198056a200241e8056a41106a29030037030020024190056a200241e8056a41086a29030037030020024188056a20022903e805370300200241c0056a200241c8056a41186a290300370300200241b8056a200241c8056a41106a290300370300200241b0056a200241c8056a41086a290300370300200220022903c8053703a80520012802002105200241f8096a200141046a2206280200220441c000200441c000491b22036a4100410041c00020036b2003413f4b1b10171a200241f8096a20052003101e1a2006200420036b3602002001200520036a36020002402004413f4d0d00200241086a41386a2209200241f8096a41386a2201290300370300200241086a41306a220a200241f8096a41306a2203290300370300200241086a41286a2211200241f8096a41286a2204290300370300200241086a41206a2212200241f8096a41206a2205290300370300200241086a41186a221d200241f8096a41186a2206290300370300200241086a41106a2216200241f8096a41106a2207290300370300200241086a41086a2217200241f8096a41086a2208290300370300200220022903f80937030820012009290300220b3703002003200a290300220c37030020042011290300220d37030020052012290300220e3703002006201d290300221337030020072016290300221437030020082017290300223a370300200241d8116a41086a2209203a370300200241d8116a41106a220a2014370300200241d8116a41186a22112013370300200241d8116a41206a2212200e370300200241d8116a41286a221d200d370300200241d8116a41306a2216200c370300200241d8116a41386a2217200b37030020022002290308220b3703d8112002200b3703f809200241b00e6a41386a22182017290300370300200241b00e6a41306a22172016290300370300200241b00e6a41286a2216201d290300370300200241b00e6a41206a221d2012290300370300200241b00e6a41186a22122011290300370300200241b00e6a41106a2211200a290300370300200241b00e6a41086a220a2009290300370300200220022903d8113703b00e20012018290300220b37030020032017290300220c37030020042016290300220d3703002005201d290300220e3703002006201229030022133703002007201129030022143703002008200a290300223a370300200241d80c6a41086a2201203a370300200241d80c6a41106a22032014370300200241d80c6a41186a22042013370300200241d80c6a41206a2205200e370300200241d80c6a41286a2206200d370300200241d80c6a41306a2207200c370300200241d80c6a41386a2208200b370300200220022903b00e220b3703d80c2002200b3703f809200241086a20024188036a41c002101e1a20024180036a2008290300370300200241f8026a2007290300370300200241f0026a2006290300370300200241e8026a2005290300370300200241e0026a2004290300370300200241d8026a2003290300370300200241d0026a2001290300370300200220022903d80c3703c8022000200241086a418003101e1a200241f0126a24000f0b200241f8096a41386a2201200241086a41386a290000370300200241f8096a41306a2203200241086a41306a290000370300200241f8096a41286a2204200241086a41286a290000370300200241f8096a41206a2205200241086a41206a290000370300200241f8096a41186a2206200241086a41186a290000370300200241f8096a41106a2207200241086a41106a290000370300200241f8096a41086a2208200241086a41086a290000370300200220022900083703f8092001200241b00e6a41386a2900003703002003200241b00e6a41306a2900003703002004200241b00e6a41286a2900003703002005200241b00e6a41206a2900003703002006200241b00e6a41186a2900003703002007200241b00e6a41106a2900003703002008200241b00e6a41086a290000370300200220022900b00e3703f809200041073a0008024020024188036a41086a2d00002201411d74411d75417f4a0d000240024020014104460d0020014105470d0120024198036a2d00004101470d02200241a0036a280200450d022002419c036a2802001002200241f0126a24000f0b20024198036a2d00004101470d012002419c036a1025200241f0126a24000f0b20024194036a2d00004101470d0020091025200241f0126a24000f0b200241f0126a24000bd81a05077f017e027f017e017f230041c0016b22012400200141003a00a001200141a0016a20002802002202200028020422034100472204101e1a2000200320046b22053602042000200220046a220236020002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402003450d004106210420012d00a001220341074b0d19024020030e080004021b1b050603000b200141003a00a001200141a0016a200220054100472203101e1a200041046a200520036b22063602002000200220036a22033602002005450d1920012d00a0012205450d0820054101470d19200141003602a001200141a0016a20032006410420064104491b2205101e1a200041046a200620056b3602002000200320056a360200200641034d0d1920012802a0012207ad42187e2208422088a70d152008a72203417f4c0d142003450d112003100122090d120c1b0b410621040c180b200141003a00a001200141a0016a200220054100472203101e1a41042109200041046a200520036b22063602002000200220036a22033602002005450d1720012d00a001220541034b0d17024020050e04000a0b0c000b200142003703a001200141a0016a20032006410820064108491b2205101e1a200041046a200620056b3602002000200320056a360200200641074d0d1720012903a0012108410121090c0b0b200141003a00a001200141a0016a200220054100472203101e1a200041046a200520036b22063602002000200220036a22033602002005450d1620012d00a0012205450d0320054101470d16200142003703a001200141a0016a20032006410820064108491b2205101e1a200041046a200620056b3602002000200320056a360200200641074d0d1620012903a00121084202210b0c040b200141003a00a001200141a0016a200220054100472203101e1a200041046a200520036b22063602002000200220036a22033602002005450d1520012d00a0012205450d054202210b20054101460d060c160b200141a0016a200010a00120012903a001220ba741ff01714103460d1520014180016a41086a200141a0016a41086a29020037030020014180016a41106a200141a0016a41106a290200370300200120012902a001370380012001200b370348410321040c150b200141003a00a001200141a0016a200220054100472206101e1a200041046a200520066b22033602002000200220066a220236020002402005450d004105210520012d00a001220641034b0d11024020060e04000c0a0b000b200141003602a001200141a0016a20022003410420034104491b2206101e1a200041046a200320066b3602002000200220066a360200200341034d0d1120012802a0012100410121050c130b410521050c100b200142003703a001200141a0016a20032006410820064108491b2205101e1a200041046a200620056b3602002000200320056a360200200641074d0d1220012903a00121084201210b0b20014180016a41086a200141a0016a41086a29030037030020014180016a41106a200141a0016a41106a290300370300200120012903a001370380012001200b37024c410521040c120b200141a0016a2000101f20012802a0012209450d1020012902a4012108410121000c0a0b200142003703a001200141a0016a200320064108200641084922021b2205101e1a200041046a200620056b3602002000200320056a36020020020d0f20012903a00121084201210b0b20014180016a41086a200141a0016a41086a29030037030020014180016a41106a200141a0016a41106a290300370300200120012903a001370380012001200b37024c410121040c0f0b200142003703a001200141a0016a20032006410820064108491b2205101e1a200041046a200620056b3602002000200320056a360200200641074d0d0d20012903a0012108410221090c010b200141003602a001200141a0016a20032006410420064104491b2205101e1a200041046a200620056b3602002000200320056a36020041032109200641034d0d0c20012802a00121020b20014180016a41086a200141a0016a41086a29030037030020014180016a41106a200141a0016a41106a290300370300200120023602502001200936024c200120012903a00137038001410221040c0c0b200142003703a001200141a0016a20022003410820034108491b2206101e1a200041046a200320066b3602002000200220066a360200200341074d0d0720012903a0012108410321050c080b200142003703a001200141a0016a20022003410820034108491b2206101e1a200041046a200320066b3602002000200220066a360200200341074d0d0620012903a0012108410421050c080b200141a0016a2003412020034120491b22066a41004100412020066b2006411f4b1b10171a200141a0016a20022006101e1a200041046a200320066b3602002000200220066a36020002402003411f4d0d0020014180016a41186a2200200141a0016a41186a220329030037030020014180016a41106a2205200141a0016a41106a220229030037030020014180016a41086a2206200141a0016a41086a2209290300370300200120012903a0013703800120032000290300370300200220052903003703002009200629030037030020012001290380013703a00141022105200141fc006a41026a220320012d00a2013a0000200141e8006a41086a2202200141b7016a290000370300200141e8006a41106a2206200141a0016a411f6a2d00003a0000200120012f01a0013b017c200120012900af0137036820012800a301210020012900a7012108200141e4006a41026a20032d00003a0000200141c8006a41086a2002290300370300200141c8006a41106a20062d00003a0000200120012f017c3b0164200120012903683703480c080b200141a0016a41186a20014180016a41186a290000370300200141a0016a41106a20014180016a41106a290000370300200141a0016a41086a20014180016a41086a29000037030020012001290080013703a0010c050b410421090b2001200736024c20012009360248410021032001410036025002402007450d00200141d0006a210c41002102034020014180016a2000101f024002402001280280012206450d002001290284012108200141a0016a2000101f024020012802a001220a450d00200241016a210220012902a401210b2003200128024c470d02200141c8006a1076200c2802002103200128024821090c020b2008a7450d00200610020b2001280248210502402003450d00200341186c21032005210003400240200041046a280200450d00200028020010020b0240200041106a280200450d002000410c6a28020010020b200041186a2100200341686a22030d000b0b200128024c450d09200510020c090b2009200341186c6a22052008370204200520063602002005410c6a200a360200200541106a200b370200200c200341016a220336020020022007490d000b200128024821090b2009450d06200129024c2108410221000b20014180016a41086a200141a0016a41086a29020037030020014180016a41106a200141a0016a41106a29020037030020012000360248200120012902a00137038001200120084220862009ad8437024c20084220882108410021040c060b1061000b1060000b0b0b20014180016a41026a2203200141e4006a41026a2d00003a0000200141a0016a41086a2202200141c8006a41086a290300370300200141a0016a41106a2206200141c8006a41106a290300370300200120012f01643b018001200120012903483703a00120054105460d00200141c4006a41026a220420032d00003a0000200141286a41086a22032002290300370300200141286a41106a22022006290300370300200120012f0180013b0144200120012903a00137032820014180016a41086a200329030037030020014180016a41106a2002290300370300200120053a004c20012000360250200120012f01443b004d200120042d00003a004f2001200129032837038001410421040c010b0b200141c4006a41026a220020012d004f3a0000200141286a41086a220520014180016a41086a290300370300200141286a41106a220220014180016a41106a290300370300200120012f004d3b014420012001290380013703282001280250210620012d004c21092001280248210a41062103024020044106460d00200141246a41026a20002d00003a0000200141086a41086a2005290300370300200141086a41106a2002290300370300200120012f01443b012420012001290328370308200421030b024020034106470d00200141c0016a240041000f0b20014180016a41026a2204200141246a41026a2d00003a0000200141a0016a41086a2205200141086a41086a290300370300200141a0016a41106a2202200141086a41106a290300370300200120012f01243b018001200120012903083703a001413010012200450d002000200a36020420002003360200200020093a0008200020012f0180013b00092000200636000c20002008370210200020012903a0013702182000410b6a20042d00003a0000200041206a2005290300370200200041286a2002290300370200200141c0016a240020000f0b101c000be60101037f0240024002402000280200220128020022024103460d0020020d0220012802042202450d0220024101470d012001410c6a280200450d02200141086a2802001002200028020010020f0b20012d00044101470d01200141086a1022200028020010020f0b0240200141106a2802002203450d00200141086a2802002102200341186c210303400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200341686a22030d000b0b2001410c6a280200450d00200141086a28020010020b200028020010020b7901047f0240024002400240200041046a2802002201450d002001418080808004710d03200028020021022001410174220310012204450d022004200220032001200120034b1b101e1a200210020c010b410410012204450d01410421030b20002004360200200041046a20033602000f0b101c000b106e000b05001041000be60101037f0240024002402000280200220128020022024103460d0020020d0220012802042202450d0220024101470d012001410c6a280200450d02200141086a2802001002200028020010020f0b20012d00044101470d01200141086a1025200028020010020f0b0240200141106a2802002203450d00200141086a2802002102200341186c210303400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200341686a22030d000b0b2001410c6a280200450d00200141086a28020010020b200028020010020b890403037f017e027f230041206b22022400200241003602082002420137030020024100410410272002280200200228020822036a41003600002002200341046a220336020820022003412010272002280200200228020822046a220320012900a002370000200341186a200141b8026a290000370000200341106a200141b0026a290000370000200341086a200141a8026a2900003700002002200441206a22033602082001290300210520022003410810272002280200200228020822036a20053700002002200341086a2206360208200241106a200141086a1028200228021021042002200620022802182203102720022003200228020822066a2207360208200620022802006a20042003101e1a02402002280214450d00200410020b2002200741c0001027200241086a22032003280200220441c0006a22063602002004200228020022076a220320012900c002370000200341086a200141c8026a290000370000200341106a200141d0026a290000370000200341186a200141d8026a290000370000200341206a200141e0026a290000370000200341286a200141e8026a290000370000200341306a200141f0026a290000370000200341386a200141f8026a2900003700000240200641034d0d002000200229030037020020072004413c6a360000200041086a200241086a280200360200200241206a24000f0b410420061029000ba10101027f024002400240200041046a280200220320016b20024f0d00200120026a220220014922010d0141000d01200341017422044100200220011b2201200420014b1b22014100480d01024002402003450d0020002802002104200110012202450d042002200420012003200320014b1b101e1a200410020c010b200110012202450d030b20002002360200200041046a20013602000b0f0b1041000b101c000bfb2602077f017e230041306b22022400200241003602082002420137030002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a220341054b0d0002400240024002400240024020030e06000402030105000b2002107e2002280200200241086a22032802006a41013a00002003200328020041016a2204360200200241003602282002420137032020012d0001450d16200241206a107e2002280220200241206a41086a220528020022066a41003a00002005200641016a2206360200200241206a20064120102720052005280200220741206a22063602002007200228022022086a2205200141026a290000370000200541086a2001410a6a290000370000200541106a200141126a290000370000200541186a2001411a6a29000037000020022802242101200220042006102720032003280200220520066a360200200520022802006a20082006101e1a2001450d14200810020c140b2002107e2002280200200241086a22032802006a41063a00002003200328020041016a3602002002410036021820024201370310200141086a2d0000417f6a220341044b0d16024020030e05001210110f000b200241106a107e2002280210200241186a22032802006a41003a00002003200328020041016a2208360200200241206a2001410c6a10b80120022802202106200241106a200820022802282205102720032005200328020022086a360200200820022802106a20062005101e1a02402002280224450d00200610020b200141186a2802002101200241106a20032802004104102720032003280200220541046a360200200520022802106a20013600000c120b2002107e2002280200200241086a22032802006a41033a00002003200328020041016a3602002002410036022820024201370320200141086a2903004200510d16200241206a107e2002280220200241206a41086a220528020022066a41003a00002005200641016a2206360200200141106a2903002109200241206a20064108102720052005280200220641086a22013602002006200228022022056a200937000020022802242106200220032802002001102720032003280200220820016a360200200820022802006a20052001101e1a2006450d12200510020c120b2002107e2002280200200241086a22032802006a41053a00002003200328020041016a3602002002410036021820024201370310200141086a2d000022034103714101460d0520034102460d0320034103470d16200241106a107e2002280210200241186a220528020022036a41023a00002005200341016a22033602002001410c6a2802002106200241106a20034104102720052005280200220341046a2208360200200320022802106a2006360000200241106a20084101102720052005280200220641016a22033602002006200228021022056a200141096a2d00003a00000c060b2002107e2002280200200241086a22032802006a41023a00002003200328020041016a22063602002002410036022820024201370320200141086a2d000022054103714101460d0620054103460d0320054102470d16200241206a107e20022802202205200241286a220328020022016a41013a00002003200141016a22013602000c070b2002107e2002280200200241086a22032802006a41073a00002003200328020041016a22063602002002410036021820024201370310200141046a2d000022034103714101460d0820034102460d0720034103470d16200241106a107e2002280210200241106a41086a220528020022036a41023a00002005200341016a2203360200200241106a20034120102720052005280200220841206a22033602002008200228021022056a2208200141056a290000370000200841086a2001410d6a290000370000200841106a200141156a290000370000200841186a2001411d6a2900003700000c090b2002107e2002280200200241086a22032802006a41003a00002003200328020041016a3602002002410036022820024201370320200141106a2d00004102460d16200241206a107e2002280220200241206a41086a220328020022056a41003a00002003200541016a2207360200412010012203450d0f200341186a2206200141f0016a290000370000200341106a2208200141e8016a290000370000200341086a2204200141e0016a2900003700002003200141d8016a290000370000200141086a290300210941c00010012205450d0f20052003290000370000200541186a2006290000370000200541106a2008290000370000200541086a2004290000370000200310022005200937002041800110012203450d0f20032005290000370000200341386a2206200541386a290000370000200341306a2208200541306a290000370000200341286a2204200541286a290000370000200341206a200541206a290000370000200341186a200541186a290000370000200341106a200541106a290000370000200341086a200541086a29000037000020051002200341c0006a20014190026a290000370000200620014188026a290000370000200820014180026a2900003700002004200141f8016a29000037000020014191016a2105200141f1006a2108200141316a2106200141116a210402400240200141106a2d0000450d00200341c8006a41123a00002003200141d4016a2802003600492003200429000037004d200341d5006a200441086a290000370000200341dd006a200441106a290000370000200341e5006a200441186a29000037000041800210012201450d1120012003418001101e210120031002200141a5016a200641386a2900003700002001419d016a200641306a29000037000020014195016a200641286a2900003700002001418d016a200641206a29000037000020014185016a200641186a290000370000200141fd006a200641106a290000370000200141f5006a200641086a2900003700002001200629000037006d200120082900003700ad01200141b5016a200841086a290000370000200141bd016a200841106a290000370000200141c5016a200841186a29000037000041800410012206450d1120062001418002101e21032001100220034185026a200541386a290000370000200341fd016a200541306a290000370000200341f5016a200541286a290000370000200341ed016a200541206a290000370000200341e5016a200541186a290000370000200341dd016a200541106a290000370000200341d5016a200541086a290000370000200320052900003700cd010c010b200341c8006a41113a00002003200141d4016a2802003600492003200429000037004d200341d5006a200441086a290000370000200341dd006a200441106a290000370000200341e5006a200441186a29000037000041800210012201450d1020012003418001101e210120031002200141a5016a200641386a2900003700002001419d016a200641306a29000037000020014195016a200641286a2900003700002001418d016a200641206a29000037000020014185016a200641186a290000370000200141fd006a200641106a290000370000200141f5006a200641086a2900003700002001200629000037006d200120082900003700ad01200141b5016a200841086a290000370000200141bd016a200841106a290000370000200141c5016a200841186a29000037000041800410012206450d1020062001418002101e21032001100220034185026a200541386a290000370000200341fd016a200541306a290000370000200341f5016a200541286a290000370000200341ed016a200541206a290000370000200341e5016a200541186a290000370000200341dd016a200541106a290000370000200341d5016a200541086a290000370000200320052900003700cd010b200241206a2007418d021027200241206a41086a220120012802002203418d026a22013602002003200228022022056a2006418d02101e1a20061002200228022421062002200241086a22032802002001102720032003280200220820016a360200200820022802006a20052001101e1a2006450d0e200510020c0e0b200241106a107e2002280210200241186a220528020022036a41013a00002005200341016a22033602002001410c6a2802002101200241106a20034104102720052005280200220641046a22033602002006200228021022056a20013600000c020b200241206a107e20022802202205200241286a220328020022016a41023a00002003200141016a22013602000c030b200241106a107e2002280210200241106a41086a220328020022056a41003a00002003200541016a2208360200200241206a2001410c6a28020010d80120022802202106200241106a200820022802282205102720032005200328020022086a2204360200200820022802106a20062005101e1a02402002280224450d00200610020b200141106a2903002109200241106a200441081027200241106a41086a22012001280200220141086a22033602002001200228021022056a20093700000b200228021421062002200241086a22012802002003102720012001280200220820036a360200200820022802006a20052003101e1a2006450d0a200510020c0a0b200241206a107e2002280220200241206a41086a220628020022056a41003a00002006200541016a2205360200200241206a2005412010272002280220200628020022086a2205200141096a290000370000200541186a200141216a290000370000200541106a200141196a290000370000200541086a200141116a2900003700002006200841206a2205360200200141306a2903002109200241206a20054108102720022802202205200628020022016a20093700002006200141086a2201360200200328020021060b200228022421032002200620011027200241086a22062006280200220620016a360200200620022802006a20052001101e1a2003450d08200510020c080b200241106a107e2002280210200241106a41086a220628020022036a41013a00002006200341016a2203360200200241106a20034120102720062006280200220341206a2205360200200320022802106a2203200141056a290000370000200341086a2001410d6a290000370000200341106a200141156a290000370000200341186a2001411d6a290000370000200241106a20054101102720022802102205200628020022036a200141256a2d00003a00002006200341016a2203360200200241086a28020021060c010b200241106a107e2002280210200241106a41086a220528020022036a41003a00002005200341016a2203360200200241206a200141086a28020010d80120022802202108200241106a200320022802282201102720052001200528020022046a22033602002004200228021022056a20082001101e1a2002280224450d00200810020b200228021421012002200620031027200241086a22062006280200220620036a360200200620022802006a20052003101e1a2001450d05200510020c050b200241106a107e2002280210200241106a41086a22032802006a41043a00002003200328020041016a2205360200200241106a20054120102720032003280200220541206a2206360200200520022802106a220541186a200141216a290000370000200541106a200141196a290000370000200541086a200141116a2900003700002005200141096a290000370000200141306a2903002109200241106a20064108102720032003280200220541086a360200200520022802106a20093700002001412c6a2802002101200241106a20032802004104102720032003280200220541046a360200200520022802106a20013600000c030b200241106a107e2002280210200241186a22032802006a41023a00002003200328020041016a22053602002001410c6a2802002101200241106a20054104102720032003280200220541046a360200200520022802106a20013600000c020b200241106a107e2002280210200241186a22032802006a41033a00002003200328020041016a22053602002001410c6a2802002101200241106a20054104102720032003280200220541046a360200200520022802106a20013600000c010b200241106a107e2002280210200241106a41086a22032802006a41013a00002003200328020041016a22053602002001412c6a2802002106200241106a20054104102720032003280200220541046a360200200520022802106a2006360000200241106a20032802004120102720032003280200220541206a2206360200200520022802106a220541186a200141216a290000370000200541106a200141196a290000370000200541086a200141116a2900003700002005200141096a290000370000200141306a2802002105200241106a20064104102720032003280200220641046a360200200620022802106a2005360000200141346a2802002101200241106a20032802004104102720032003280200220541046a360200200520022802106a20013600000b20022802142106200228021021052002200241086a2201280200200241106a41086a2802002203102720012003200128020022086a360200200820022802006a20052003101e1a2006450d00200510020b20002002290300370200200041086a200241086a280200360200200241306a24000f0b101c000b41ec30103b000b419435103b000b41ec34103b000b41ac3f103b000b41943b103b000b41843e103b000b41ecc100103b000b08004194321054000b4b01017f02402002417f4c0d00024002402002450d002002100122030d01101c000b410121030b200320012002101e21012000200236020420002001360200200020023602080f0b102b000b05001041000ba10c03037f027e0c7f23004180016b22002400200041e0006a41086a220142003703002000420037036041c8084107200041e0006a1003200041306a41086a200129030037030020002000290360370330024002400240200041306a411041d02d410041001000417f460d002000420037036002400240200041306a4110200041e0006a41084100100041016a41084d0d002000200029036042017c370340200041e0006a41086a220242003703002000420037036041c8084107200041e0006a1003200041306a41086a2201200229030037030020002000290360370330200041306a4110200041c0006a41081004200142003703002000420037033041dd084107200041306a1003200041106a41086a2001290300370300200020002903303703100240200041106a411041d02d410041001000417f460d0020004200370360200041106a4110200041e0006a41084100100041016a41084d0d0220002903602103200041306a41086a220142003703002000420037033041dd084107200041306a1003200041e0006a41086a200129030037030020002000290330370360200041e0006a411010054201a74101470d050c040b4200a74101460d030c040b41c1214133102d000b41c1214133102d000b41f4214122102d000b102e210420002003370340200041e0006a41086a220142003703002000420037036041cf084107200041e0006a1003200041306a41086a2202200129030037030020002000290360370330200041306a4110200041c0006a4108100420002004370340200142003703002000420037036041d6084107200041e0006a10032002200129030037030020002000290360370330200041306a4110200041c0006a410810040b2000102f2000280200210502400240024020002802082201450d002001410574210620052107410021080340410810012201450d022000200136026020004208370264200041e0006a410041081027200041e0006a41086a22012001280200220241086a360200200220002802606a42f3cacdd3e38d9eba3a370000200041c0006a41086a2202200128020036020020002000290360370340412010012209450d022000200936026020004220370264200041e0006a41004120102720012001280200220a41206a2209360200200a2000280260220b6a220a2007290000370000200a41086a200741086a290000370000200a41106a200741106a290000370000200a41186a200741186a2900003700002000280264210c200041c0006a2002280200200910272000280240220a2002280200220d6a200b2009101e1a2002200d20096a220d3602000240200c450d00200b10020b2000280244210c200041306a41086a2209420037030020004200370330200a200d200041306a1003200041106a41086a220b20092903003703002000200029033037031002400240200041106a411041d02d410041001000417f460d00200041e0006a41186a220e4200370300200041e0006a41106a220f42003703002001420037030020004200370360200041106a4110200041e0006a4120410010002210417f460d052010411f4d0d05200041c0006a41186a200e290300370300200041c0006a41106a200f29030037030020022001290300370300200020002903603703402009420037030020004200370330200a200d200041306a10032001200929030037030020002000290330370360200041e0006a41101005410121090c010b410021090b200041106a41186a220d200041c0006a41186a290300370300200041106a41106a220e200041c0006a41106a290300370300200b2002290300370300200020002903403703100240200c450d00200a10020b02402009450d00200041e0006a41186a200d290300370300200041e0006a41106a200e2903003703002001200b29030037030020002000290310370360200041c0006a10302000280240220920022802001031210102402000280244450d00200910020b200120084d0d00200041c0006a20081032200028024022012002280200200041e0006a412010042000280244450d00200110020b200741206a2107200841016a2108200641606a22060d000b0b02402000280204450d00200510020b20004180016a24000f0b101c000b41c1214133102d000b080041b4321054000b9f0102027f017e230041206b22002400200041106a41086a220142003703002000420037031041d12d4107200041106a1003200041086a20012903003703002000200029031037030002402000411041d02d410041001000417f460d0020004200370310024020004110200041106a41084100100041016a41084d0d0020002903102102200041206a240020020f0b41c1214133102d000b41f4214122102d000bab0101027f230041306b22012400200141206a41086a220242003703002001420037032041e4084107200141206a1003200141086a200229030037030020012001290320370300024002402001411041d02d410041001000417f460d002001421037021420012001360210200141206a200141106a103a20012802202202450d012000200129022437020420002002360200200141306a24000f0b41f4214122102d000b41c1214133102d000bd60101047f230041206b220124000240410610012202450d002001200236021020014206370214200141106a4100410610272001280210200128021822036a220441002800c12d360000200141086a2202200341066a2203360200200441046a41002f00c52d3b0000200120012903103703002001200336021820012002280200410310272000200129030037020020022002280200220341036a2204360200200320012802006a220241002f00ee2e3b0000200041086a2004360200200241026a41002d00f02e3a0000200141206a24000f0b101c000b6001027f230041106b2202240041002103024002402000200141d02d410041001000417f460d002002410036020c200020012002410c6a41044100100041016a41044d0d01200228020c21030b200241106a240020030f0b41eb1a4133102d000bc30101047f230041206b220224000240410610012203450d002002200336021020024206370214200241106a4100410610272002280210200228021822046a220541002800c12d360000200241086a2203200441066a2204360200200541046a41002f00c52d3b00002002200229031037030020022004360218200220032802004104102720032003280200220441046a36020020002002290300370200200420022802006a2001360000200041086a2003280200360200200241206a24000f0b101c000b810301047f230041306b220224000240024002400240024002400240200128020022032001280204460d002001200341186a36020020032802082201417f4c0d06200328020021042001450d012001100122050d020c030b20004100360200200241306a24000f0b410121050b200220013602242002200536022020024100360228200241206a41002001102720022002280228220520016a360228200520022802206a20042001101e1a200241106a20022802283602002002200229032037030820032802142201417f4c0d03200328020c21032001450d012001100122040d020b101c000b410121040b200220013602242002200436022020024100360228200241206a41002001102720022002280228220420016a360228200420022802206a20032001101e1a200241146a220141086a200228022836020020012002290320370200200041106a200241086a41106a290300370200200041086a200241086a41086a29030037020020002002290308370200200241306a24000f0b1019000bd55a09017f017e017f017e067f017e177f047e027f230041f0026b220024001035102e2101200041c8026a41086a22024200370300200042003703c802418a264107200041c8026a100320004198026a41086a2002290300370300200020002903c802370398020240024002400240024002400240024002400240024002400240024020004198026a411041d02d410041001000417f460d00200042003703680240024020004198026a4110200041e8006a41084100100041016a41084d0d00200029036822034200510d0320012003824200520d0a200041f8016a103620002802f80121080240024002402000280280022209450d00200041e8006a2008280230103720002802702207450d072008200941d8006c6a2104200841d8006a2102200041f8006a35020021032000290368210a02402000280274450d00200710020b20022004460d01200a20037e2103200941d8006c41a87f6a210b41002105200041f0006a210c200041f8006a210d200041f4006a210e41012104200821060340200041e8006a200241306a2802001037200c2802002207450d052000290368200d3502007e210a0240200e280200450d00200710020b2003200a2003200a5622071b21032005200420071b21052006200220071b2106200441016a2104200241d8006a2102200b41a87f6a220b0d000b20060d022009450d00200941d8006c210420082102034020021038200241d8006a2102200441a87f6a22040d000b0b20002802fc01450d0c200810020c0c0b410021050b200920054d0d06200041e8006a2008200541d8006c6a220241d800101e1a200220082009417f6a220441d8006c6a220741d80010391a2007200041e8006a41d800101e2102200041f8016a41086a2004360200200041e8006a41086a22042002410c6a290200370300200041e8006a41106a2207200241146a290200370300200041e8006a41186a22052002411c6a290200370300200041e8006a41206a2206200241246a290200370300200041e8006a41286a220b2002412c6a280200360200200020022902043703682002280200220c4106460d07200041c0016a41086a220d2004290300370300200041c0016a41106a22042007290300370300200041c0016a41186a22072005290300370300200041c0016a41206a22052006290300370300200041c0016a41286a2206200b280200360200200020002903683703c001200241046a28022c2102200041386a41286a2006280200360200200041386a41206a2005290300370300200041386a41186a2007290300370300200041386a41106a2004290300370300200041386a41086a200d290300370300200020002903c001370338410810012204450d0b200020043602682000420837026c200041e8006a4100410810272000280268200028027022046a42e4cab5d3c3ac99b83a3700002000200441086a360270200041c0016a41086a2000280270360200200020002903683703c001410410012204450d0b200020043602682000420437026c200041e8006a41004104102720002802682207200028027022046a20023600002000200441046a2202360270200028026c2105200041c0016a20002802c8012002102720002802c001220420002802c80122066a20072002101e1a2000200620026a22023602c80102402005450d00200710020b20002802c401210620004198026a41086a2207420037030020004200370398022004200220004198026a1003200041e8006a41086a20072903003703002000200029039802370368410021070240200041e8006a411041d02d410041001000417f460d002000200041e8006a3602082000411036020c200042003703c00120004100200041e8006a4110200041c0016a41084100100022072007417f461b2207410820074108491b360210200741074d0d0620002903c0012103200041c0016a200041086a103a20002802c0012207450d06200041c0016a41086a280200210520002802c401210b20004198026a41086a220d420037030020004200370398022004200220004198026a1003200041c8026a41086a200d29030037030020002000290398023703c802200041c8026a411010052006450d0a0c090b20060d080c090b41c1214133102d000b4198264132102d000b41f4214122102d000b41c43f103b000b4198264132102d000b41c1214133102d000b41dc3f20052009103c000b41ec3f103b000b200410020b024002402007450d0002402005450d002005410574210420072102034020022003103d200241206a2102200441606a22040d000b0b200041e8006a41086a2202200041f8016a41086a280200360200200020002903f801370368200041e8006a103e20002802682105024020022802002202450d00200241d8006c210420052102034020021038200241d8006a2102200441a87f6a22040d000b0b0240200028026c450d00200510020b200041c8026a41086a22024200370300200042003703c80241f7264107200041c8026a100320004198026a41086a2002290300370300200020002903c8023703980220004198026a411041d02d410041001000417f460d0120004200370368024020004198026a4110200041e8006a41084100100041016a41084d0d0020002903682103200041f4006a200041c0006a290300370200200041fc006a200041c8006a29030037020020004184016a200041d0006a2903003702002000418c016a200041d8006a29030037020020004194016a200041e0006a2802003602002000200c3602682000200029033837026c200320017c200041e8006a4100103f200b450d03200710020c030b41c1214133102d000b41ca26412d102d000b41f4214122102d000b200020013703f801200041c8026a41086a22024200370300200042003703c80241fe264107200041c8026a100320004198026a41086a2002290300370300200020002903c80237039802024002400240024020004198026a411041d02d410041001000417f460d00200041003602680240024020004198026a4110200041e8006a41044100100041016a41044d0d0020002802682104200041c8026a41086a22024200370300200042003703c8024185274107200041c8026a100320004198026a41086a2002290300370300200020002903c8023703980220004198026a411041d02d410041001000417f460d032000410036026820004198026a4110200041e8006a41044100100041016a41044d0d012000200028026822053602cc02200041003a00d402200020043602c8022000200041f8016a3602d0020240200420054f0d002000200441016a22023602c802200041f0006a210602400340200041e8006a20041040200628020022074106470d01200220054f0d022000200241016a22073602c80220022104200721020c000b0b200041386a41086a2205200041fc006a2206290200370300200041386a41106a220b20004184016a220c290200370300200041386a41186a220d2000418c016a220e290200370300200041386a41206a220820004194016a2209290200370300200041386a41286a220f2000419c016a221028020036020020002000290274370338200041a0016a2d0000211120002903682103200041b8026a41026a221220004198026a41026a2d00003a0000200020002f0098023b01b802200041e8006a410c6a2202200029033837020020062005290300370200200c200b290300370200200e200d290300370200200920082903003702002010200f280200360200200041a7016a20122d00003a00002000200736027020002003370368200020043602a001200020113a00a401200020002f01b8023b00a5010240200320002903f801520d00200041c0016a41306a200241306a280200360200200041c0016a41286a200241286a290200370300200041c0016a41206a200241206a290200370300200041c0016a41186a200241186a290200370300200041c0016a41106a200241106a290200370300200041c0016a41086a200241086a290200370300200020022902003703c00120074106460d010c060b200041c8026a410c6a41013a0000200041e8006a41086a10384106210741064106470d050b4108211341002102410021140c050b41c1214133102d000b41c1214133102d000b41f4214122102d000b41f4214122102d000b200041e8006a41306a2202200041c0016a41306a280200360200200041e8006a41286a2204200041c0016a41286a290300370300200041e8006a41206a2205200041c0016a41206a290300370300200041e8006a41186a2206200041c0016a41186a290300370300200041e8006a41106a220b200041c0016a41106a290300370300200041e8006a41086a220c200041c0016a41086a290300370300200020002903c00137036841c00010012213450d0120132007360208201320033703002013200029036837020c201341146a200c2903003702002013411c6a200b290300370200201341246a20062903003702002013412c6a2005290300370200201341346a20042903003702002013413c6a2002280200360200200041086a41086a200041c8026a41086a290300370300200020002903c802370308024020002d00140d0020002802082202200028020c4f0d002000200241016a360208200041f0006a210402400340200041e8006a20021040200428020022074106470d0120002802082202200028020c4f0d022000200241016a3602080c000b0b200041386a41086a2205200041fc006a2206290200370300200041386a41106a220b20004184016a220c290200370300200041386a41186a220d2000418c016a220e290200370300200041386a41206a220820004194016a2209290200370300200041386a41286a220f2000419c016a221028020036020020002000290274370338200041a0016a2d0000211120002903682103200041b8026a41026a221220004198026a41026a2d00003a0000200020002f0098023b01b802200041e8006a410c6a2204200029033837020020062005290300370200200c200b290300370200200e200d290300370200200920082903003702002010200f280200360200200041a7016a20122d00003a00002000200736027020002003370368200020023602a001200020113a00a401200020002f01b8023b00a5010240024020032000280210290300520d00200041c0016a41306a200441306a280200360200200041c0016a41286a200441286a290200370300200041c0016a41206a200441206a290200370300200041c0016a41186a200441186a290200370300200041c0016a41106a200441106a290200370300200041c0016a41086a200441086a290200370300200020042902003703c0014106210b20074106470d010c020b200041086a410c6a41013a0000200041e8006a41086a1038410621074106210b41064106460d010b200041e8006a41086a2106200041a5016a2111200041e8006a410c6a210d410121144101210202400340200041e8006a41306a2205200041c0016a41306a2212280200360200200041e8006a41286a220c200041c0016a41286a221c290300370300200041e8006a41206a2209200041c0016a41206a221e290300370300200041e8006a41186a220f200041c0016a41186a221d290300370300200041e8006a41106a2210200041c0016a41106a22202903003703002006200041c0016a41086a2215290300370300200020002903c001370368024020022014470d00201441016a2204201449221b0d02200e2014410174221f20082004201b1b22082008201f491b2204ad420686220aa7200a422088a7221b1b220e4100480d02201b4100470d02024002402014450d00200e1001221b450d07201b2013200e2014200b74221f201f200e4b1b101e211b20131002201b21130c010b200e10012213450d060b200421140b20132002200b746a22042007360208200420033703002004413c6a2005280200360200200441346a200c2903003702002004412c6a2009290300370200200441246a200f2903003702002004411c6a2010290300370200200441146a20062903003702002004410c6a2000290368370200200241016a2102200041086a410c6a22092d00000d0320002802082205200028020c220c4f0d032000200541016a220436020802400340200041e8006a2005104020062802002207200b470d012004200c4f0d052000200441016a220736020820042105200721040c000b0b200041386a41086a221f200d41086a2204290200370300200041386a41106a2221200d41106a220c290200370300200041386a41186a2219200d41186a220f290200370300200041386a41206a2216200d41206a2210290200370300200041386a41286a221a200d41286a221b2802003602002000200d290200370338200041a0016a22172d000021182000290368210a200041b8026a41026a222720004198026a41026a2d00003a0000200020002f0098023b01b8022006200736020020172005360200200041e8006a413c6a20183a0000200d20002903383702002004201f290300370200200c2021290300370200200f201929030037020020102016290300370200201b201a280200360200201120002f01b8023b0000201141026a20272d00003a00002000200a3703680240200a200041086a41086a280200290300520d002012200d41306a280200360200201c201b290200370300201e2010290200370300201d200f2902003703002020200c290200370300201520042902003703002000200d2902003703c001200a21032007200b470d010c040b200941013a000020061038410621074106200b470d000c030b0b1041000b41012114410121020b201320024106746a21152002450d01200041386a41086a2116200041386a4104722110200041a7026a2117200041f8016a4104722118200041c0016a41186a2119200041c9016a211a200041c0016a41086a2107200041e8006a4104722105200041e8006a41286a211b200041e8006a41206a2112200041e8006a41106a211c2013210f0340200f22022802082111201b200241346a28020036020020122002412c6a290200370300200041e8006a41186a221d200241246a290200370300201c2002411c6a290200370300200041e8006a41086a221e200241146a29020037030020002002410c6a290200370368200241c0006a210f20114106460d0320022802382109200041086a41086a2204201e290300370300200041086a41106a2206201c290300370300200041086a41186a220b201d290300370300200041086a41206a220c2012290300370300200041086a41286a220d201b2802003602002000200029036837030820022d003c211f20102000290308370200201041086a2004290300370200201041106a2006290300370200201041186a200b290300370200201041206a200c290300370200201041286a200d28020036020020002011360238200041f8016a2009104220002802f801212002400240024002400240200041f8016a41086a22212802002202450d002002410574210d420021034200210a20202102034020021043210120021044212220052002290000370000200541086a200241086a290000370000200541106a200241106a290000370000200541186a200241186a29000037000020002009360268410810012204450d07200020043602c001200042083702c401200041c0016a41004108102720072007280200220441086a360200200420002802c0016a42e4cab5d3e3ee9bba3a370000200041c8026a41086a22042007280200360200200020002903c0013703c802200041c0016a200041e8006a104520002802c401210e20002802c001210c200041c8026a200428020020072802002206102720002802c802220b200428020022086a200c2006101e1a2004200820066a22083602000240200e450d00200c10020b20002802cc02210620044200370300200042003703c802200b2008200041c8026a100320004198026a41086a2004290300370300200020002903c8023703980202400240024020004198026a411041d02d410041001000417f470d004102210420060d010c020b200041003a00c00120004198026a4110200041c0016a41014100100041016a41014d0d0520002d00c00121042006450d010b200b10020b200441ff01714102460d02200241206a21024200202220017c2201200441017122041b200a7c210a2001420020041b20037c2103200d41606a220d0d000b20002802fc01450d040c030b4200210a4200210320002802fc010d020c030b41f90941e000102d000b41c1214133102d000b202010020b0240200041c8026a41086a22064200370300200042003703c80241f9204107200041c8026a100320004198026a41086a220b2006290300370300200020002903c802370398020240024002400240024020004198026a411041d02d410041001000417f460d0020004200370368024020004198026a4110200041e8006a41084100100041016a41084d0d0020002903682101200910460240200a20037c22224202882223500d0020232022510d004100210402400340200441026a21022022200441046a413e71ad882223500d012002210420232022520d000b0b20222002413e71ad88420052ad212302402002450d0003402023420186222320234201842223202320237e202241002002417e6a2204200420024b1b2202413f71ad88561b212320020d000b0b20014202882222500d040c030b2022420052ad21232001420288222250450d020c030b41c1214133102d000b41f4214122102d000b20222001510d004100210402400340200441026a21022001200441046a413e71ad882222500d012002210420222001520d000b0b20012002413e71ad88420052ad212202402002450d0003402022420186222220224201842222202220227e200141002002417e6a2204200420024b1b2202413f71ad88561b212220020d000b0b2023500d020c010b2001420052ad21222023500d010b02400240024002400240201f41037122024101460d0020024102470d012003200a580d050c040b2022500d01200a202280222420032023802225540d0303402023210120252024540d05200a202282212320032001822224500d052023500d042022202380212520222103202421222001210a2001202480222420255a0d000c040b0b2022500d01200a202380222420032022802225540d0203402023210120252024540d04200a200182212520032022822223500d042025500d03202220238021242022210a20012103202521222024200120258022255a0d000c030b0b419c31103b000b419c31103b000b200041c0016a41286a200041386a41286a290300370300200041c0016a41206a200041386a41206a2903003703002019200041386a41186a290300370300200041c0016a41106a220c200041386a41106a29030037030020072016290300370300200020002903383703c00102400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002802c001220e417f6a220241044b0d000240024002400240024020020e050004020301000b200728020022024101460d0720024102470d13102c0c210b200c2903002103200728020022024101460d0420024102470d132000200337036820064200370300200042003703c80241e122410a200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410810040c200b200020002902c40122033703f8012003422088a721022003a72204410371220c4101460d04200c4102470d1320021046200441ff01714101470d1f201810220c1f0b20004194026a41026a220d201a41026a2d00003a00002021201941086a290300370300200041f8016a41106a2208201941106a2903003703002000201a2f00003b019402200020192903003703f80120072d0000410771417f6a220241034b0d13200c2903002103200041c0016a410c6a2802002104024020020e04000a0709000b2000200436026820064200370300200042003703c802419b164107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410410040c1a0b2007280200410771417f6a220241034b0d13200c2903002103024020020e04000b070a000b2000200337036820064200370300200042003703c80241cf1d4107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410810040c1d0b200c2802002111200041c0016a410c6a280200211e2007280200210820002802c401410371221d4101460d03201d4102470d1302402011450d002008201141186c22046a210d2008210203402002280200200241086a2802002002410c6a280200200241146a2802001004200241186a2202200d470d000b2011450d002008210203400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200441686a22040d000b0b0240201e450d00200810020b41002104201d4101470d194100210441000d19201e450d1920081002200e41077122024103470d1a0c1b0b2000200337036820064200370300200042003703c802418d23410b200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410810040c1b0b102e210a20064200370300200042003703c80241f7264107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a411041d02d410041001000417f460d122000420037036820004198026a4110200041e8006a41084100100041016a41084d0d0b20002903682101201b200241286a2903003703002012200241206a290300370300201d200241186a290300370300201c200241106a290300370300201e200241086a290300370300200020022903003703682001200a7c200041e8006a2003420888a7103f200210020c1a0b2000200c29030037036820064200370300200042003703c80241dd084107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410810040c190b41942f4105200820111004201e450d18200810020c180b2000200337036820064200370300200042003703c80241a2164107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410810040c130b2000200041c0016a410c6a28020036026820064200370300200042003703c80241de1d4107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410410040c160b2000200337036820064200370300200042003703c80241a9164107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410810040c110b20004198026a41036a200436000020004198026a41076a2003370000201720002903f80137000020004198026a41026a200d2d00003a0000201741086a2021290300370000201741106a20082d00003a0000200020002f0194023b019802200041e8006a1047200028026c2126200028026821270240201e2802002202450d00200241286c220241b07f6a2104200241586a210d202721020340200241086a2903002103200241106a290300210a200241186a2903002101200229030021222012200241206a290300370300201d2001370300201c200a370300201e200337030020002022370368200041e8006a20004198026a412010060d04200241286a2102200441586a2104200d41586a220d4158470d000b0b41002102410821112026450d03202710024100210d0c0f0b1048102c0c130b2000200337036820064200370300200042003703c80241d21e4107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a410810040c120b200041c8026a41206a22202012290300370300200041c8026a41186a221f201d290300370300200041c8026a41106a2221201c2903003703002006201e290300370300200020002903683703c802412810012211450d15201120002903c802370300201141206a2020290300370300201141186a201f290300370300201141106a2021290300370300201141086a2006290300370300200020113602b80220004281808080103702bc02200d450d01200241286a21024101210d03402012200241206a290300370300201d200241186a290300370300201c200241106a290300370300201e200241086a290300370300200020022903003703680240200041e8006a20004198026a41201006450d0020202012290300370300201f201d2903003703002021201c2903003703002006201e290300370300200020002903683703c80220122020290300370300201d201f290300370300201c2021290300370300201e2006290300370300200020002903c8023703680240200d20002802bc02470d00200041b8026a200d4101104920002802b80221110b2011200d41286c6a22082000290368370300200841206a2012290300370300200841186a201d290300370300200841106a201c290300370300200841086a201e290300370300200041b8026a41086a200d41016a220d3602000b02402004450d00200241286a2102200441586a21040c010b0b2026450d0b0c0a0b4100210d0c0b0b4101210d20260d080c090b41c1214133102d000b418431103b000b419c3e103b000b419cc000103b000b41ac35103b000b41f43b103b000b419cc200103b000b41f4214122102d000b202710020b20002802bc0221020b201e200d3602002000200236026c20002011360268200041e8006a104a2002450d00201110020b410121040b200e41077122024103460d010b20020d012004450d0120002802c4012202450d01024020024101470d00200041c0016a410c6a280200450d02200728020010020c020b2007280200210d0240200c2802002202450d00200241186c2104200d210203400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200441686a22040d000b0b200041c0016a410c6a280200450d01200d10020c010b41000d0020002d00c40141ff01714101470d002007104b0b2000200941016a36026820064200370300200042003703c80241fe264107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a41041004200f2015470d020c010b2000200941016a36026820064200370300200042003703c80241fe264107200041c8026a1003200b2006290300370300200020002903c8023703980220004198026a4110200041e8006a41041004024002400240201141077122024103460d0020020d02200028023c2202450d0220024101470d01200041386a410c6a280200450d0220162802001002200f2015470d040c030b20002d003c4101470d0120161022200f2015470d030c020b201628020021060240200041386a41106a2802002202450d00200241186c21042006210203400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200441686a22040d000b0b200041386a410c6a280200450d00200610020b200f2015470d010b0b2015220f2015460d040c030b101c000b2013210f0b200f2015460d010b200041e8006a41086a211c200041e8006a410c6a2102200041e8006a41306a2105200041e8006a41286a2106200041e8006a41206a210b200041e8006a41186a210c200041e8006a41106a210d0340200f41086a2802002104200f29030021032005200f413c6a2802003602002006200f41346a290200370300200b200f412c6a290200370300200c200f41246a290200370300200d200f411c6a290200370300200041e8006a41086a2207200f41146a2902003703002000200f410c6a29020037036820044106460d01200041c0016a41306a220e2005280200360200200041c0016a41286a22082006290300370300200041c0016a41206a2209200b290300370300200041c0016a41186a2210200c290300370300200041c0016a41106a2211200d290300370300200041c0016a41086a22122007290300370300200020002903683703c00120072004360200200220002903c001370200200241086a2012290300370200200241106a2011290300370200200241186a2010290300370200200241206a2009290300370200200241286a2008290300370200200241306a200e28020036020020002003370368201c1038200f41c0006a220f2015470d000b0b02402014450d00201310020b102e2101200041e8006a41086a220242003703002000420037036841ba1d4107200041e8006a1003200041c8026a41086a22042002290300370300200020002903683703c802420021030240024002400240024002400240024002400240200041c8026a411041d02d410041001000417f460d0020004200370368200041c8026a4110200041e8006a41084100100041016a41084d0d01200029036821030b200242003703002000420037036841c11d4107200041e8006a100320042002290300370300200020002903683703c802200041c8026a411041d02d410041001000417f460d0320004200370368024002400240200041c8026a4110200041e8006a41084100100041016a41084d0d002000290368210a200041e8006a41086a220242003703002000420037036841cf084107200041e8006a1003200041c8026a41086a2002290300370300200020002903683703c802200041c8026a411041d02d410041001000417f460d0720004200370368200041c8026a4110200041e8006a41084100100041016a41084d0d012000290368200a7e22224200510d084200210a0240200120037d2022824200520d0010480b102e2103200041e8006a41086a220242003703002000420037036841d6084107200041e8006a1003200041c8026a41086a22042002290300370300200020002903683703c80202400240200041c8026a411041d02d410041001000417f460d0020004200370368200041c8026a4110200041e8006a41084100100041016a41084d0d06200029036821014201210a0c010b0b200242003703002000420037036841cf084107200041e8006a100320042002290300370300200020002903683703c802200041c8026a411041d02d410041001000417f460d0920004200370368200041c8026a4110200041e8006a41084100100041016a41084d0d02200029036822224200510d0a0240200342002001200a501b7d2022824200520d00102c0b200041c8026a41086a22024200370300200042003703c80241ad0b4107200041c8026a100320004198026a41086a2002290300370300200020002903c8023703980220004198026a411041d02d410041001000417f460d05200041003a006820004198026a4110200041e8006a41014100100041016a41014d0d0b20002d00682102200041c8026a41086a22044200370300200042003703c80241ad0b4107200041c8026a1003200041e8006a41086a2004290300370300200020002903c802370368200041e8006a411010052002450d05200041f0026a24000f0b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c432103b000b41f4214122102d000b41f4214122102d000b41ac3b103b000b41f4214122102d000b41b431103b000b41c1214133102d000bdd91010b017f017e017f017e057f017e047f017e187f027e027f230041f0026b22002400102e2101200041286a41086a220242003703002000420037032841b0164107200041286a1003200041086a41086a200229030037030020002000290328370308024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200041086a411041d02d410041001000417f460d00200042003703900202400240200041086a411020004190026a41084100100041016a41084d0d0020002903900222034200510d0320012003824200520d1d200041286a41086a2202420037030020004200370328419b164107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411041d02d410041001000417f460d052000410036029002200041086a411020004190026a41044100100041016a41044d0d012000280290022202450d1d200041e0016a1047200041286a41086a220442003703002000420037032841b00f4107200041286a1003200041086a41086a200429030037030020002000290328370308410021040240200041086a411041d02d410041001000417f460d002000200041086a360290012000411036029401200042003703900220004100200041086a411020004190026a41084100100022042004417f461b2204410820044108491b220d36029801200441074d0d05200029039002210e200041003602900220004198016a4100200041086a411020004190026a4104200d100022042004417f461b2204410420044104491b200d6a360200200441034d0d05200028029002210420004190026a20004190016a103a200028029002220f450d0520002802e801220d20046a2000290294022203422088a76b211002402003a7450d00200f10020b20102002490d080c070b102e210e20002802e801220d20024f0d060c070b41c1214133102d000b41c1214133102d000b41f4214122102d000b41ac39103b000b41c1214133102d000b41f4214122102d000b0240200420024f0d00200d200420026b6a2202200d4f0d0820002802e001200241286c6a290320210e0c010b200041286a41086a220242003703002000420037032841a9164107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411041d02d410041001000417f460d082000420037039002200041086a411020004190026a41084100100041016a41084d0d01200029039002200e7c210e0b200041286a41086a220242003703002000420037032841b0164107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411041d02d410041001000417f460d03200042003703900202400240200041086a411020004190026a41084100100041016a41084d0d0020002903900222034200510d06200e20037c427f7c220e200e2003827d2103024020002802e401450d0020002802e00110020b20032001520d17200041e8006a1047200041286a41086a2202420037030020004200370328419b164107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411041d02d410041001000417f460d072000410036029002200041086a411020004190026a41044100100041016a41044d0d012000280290022115102e21030240024020002802702214450d002000280268220241206a2903002003520d0020004190026a41186a2204200241186a29000037030020004190026a41106a220d200241106a29000037030020004190026a41086a2210200241086a290000370300200020022900003703900241201001220f450d12200241286a2102200f200029039002370000200f41186a2004290300370000200f41106a200d290300370000200f41086a20102903003700002000200f3602e00120004281808080103702e401412021104101210d0240201441286c41586a2211450d000340200241206a2903002003520d01200041c8006a41186a200241186a2204290000370300200041c8006a41106a200241106a2216290000370300200041c8006a41086a200241086a22172900003703002000200229000037034820004190016a41186a2218200429000037030020004190016a41106a2219201629000037030020004190016a41086a2216201729000037030020002002290000370390010240200d20002802e401470d00200041e0016a200d410110860120002802e001210f0b200241286a2102200f20106a2204200029039001370000200441186a2018290300370000200441106a2019290300370000200441086a2016290300370000200041e0016a41086a200d41016a220d360200201041206a2110201141586a22110d000b0b20002802e40121022014200d6b2015490d010c160b410021024101210f4100210d201441006b20154f0d150b200041286a41086a220442003703002000420037032841a2164107200041286a1003200041086a41086a200429030037030020002000290328370308200041086a411041d02d410041001000417f460d0a2000420037039002200041086a411020004190026a41084100100041016a41084d0d03200029039002210e20004190026a41106a2002360200200041a4026a200d3602002000200d20146b20156a2219360298022000200e20037c2203370390022000200f36029c02200041003602e801200042013703e001200041e0016a41004108102720002802e00120002802e80122046a20033700002000200441086a22043602e801200041e0016a20044104102720002802e00120002802e80122046a20193600002000200441046a22103602e80120004190016a2000419c026a10a201200028029001210d200041e0016a2010200028029801220410272000200420002802e80122116a22163602e801201120002802e00122106a200d2004101e1a0240200028029401450d00200d10020b200041286a41086a220442003703002000420037032841b00f4107200041286a1003200041086a41086a200429030037030020002000290328370308200041086a4110201020161004024020002802e401450d00201010020b02402002450d00200f10020b41082118200041286a41086a220242003703002000420037032841c50f4107200041286a1003200041086a41086a200229030037030020002000290328370308410021140240024002400240200041086a411041d02d410041001000417f460d0020004210370294012000200041086a3602900120004190026a20004190016a103a2000280290022215450d1341082118200028029402211b20004190026a41086a2802002202450d0120024105744105752214ad4203862203a722044100480d122003422088a74100470d12200410012218450d152002410574220d41606a410576211020182104201521020340200420021043200210447c370300200441086a2104200241206a2102200d41606a220d0d000b201041016a21020c030b410121154100211b0c010b410021140b410021020b2000410036029802200042013703900220004190026a41004104102720002802900220002802980222046a20023600002000200441046a3602980220004190016a41086a2204200028029802360200200020002903900237039001024002402002450d002002410374210f2018210d0340200d2903002103410810012202450d152000200236029002200042083702940220004190026a41004108102720004190026a41086a22022002280200221141086a2202360200201120002802900222106a2003370000200028029402211120004190016a2004280200200210272000280290012217200428020022166a20102002101e1a2004201620026a220236020002402011450d00201010020b200d41086a210d200f41786a220f0d000c020b0b200028029801210220002802900121170b2000280294012104200041286a41086a220d4200370300200042003703284181114107200041286a1003200041086a41086a200d29030037030020002000290328370308200041086a411020172002100402402004450d00201710020b02402014450d00201810020b200041286a41086a220242003703002000420037032841b7164107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411041d02d410041001000417f460d0b2000410036029002200041086a411020004190026a41044100100041016a41044d0d042000280290022102200041a8016a4200370300200041a0016a420037030020004198016a42003703002000420037039001200220196a220dad42287e2203422088a70d0c2003a72202417f4c0d0d4108210402402002450d00200210012204450d140b2000200d3602e401200020043602e001200041003602e80120004190026a41186a221020004190016a41186a29030037030020004190026a41106a220f20004190016a41106a29030037030020004190026a41086a20004190016a41086a290300370300200020002903900137039002200041e0016a200d10850120002802e00120002802e801221141286c6a2102024002400240200d4102490d0041012104034020024200370300200241206a2010290300370300200241186a200f290300370300200241106a20004190026a41086a290300370300200241086a200029039002370300200241286a2102200441016a2204200d490d000b201120046a417f6a21110c010b200d450d010b200220002903900237030820024200370300200241106a20004198026a290300370300200241186a20004190026a41106a290300370300200241206a20004190026a41186a290300370300201141016a21110b200041e0016a41086a2202201136020020004190026a41086a2002280200360200200020002903e0013703900220004190026a10b7010240200028029402450d0020002802900210020b201b450d15201510020c150b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41f4214122102d000b41c439103b000b41f4214122102d000b41cc362002200d103c000b41f4214122102d000b41f4214122102d000b41f4214122102d000b105e000b105f000b1041000b41c1214133102d000b41d900212a0c070b41d900212a0c060b41d900212a0c050b41d900212a0c040b2002450d00200f1002200028026c0d010c020b200028026c450d010b200028026810020b200041286a41086a220242003703002000420037032841b00f4107200041286a1003200041086a41086a20022903003703002000200029032837030802400240200041086a411041d02d410041001000417f460d002000200041086a360290012000411036029401200042003703900220004100200041086a411020004190026a41084100100022022002417f461b2202410820024108491b220436029801200241074d0d0b2000290390022103200041003602900220004198016a4100200041086a411020004190026a41042004100022022002417f461b22024104200241044922021b20046a36020020020d0b20004190026a20004190016a103a2000280290022205450d0b200028029402210620032001520d01200041286a41086a22024200370300200042003703284181114107200041286a1003200041086a41086a2204200229030037030020002000290328370308200041086a41101005200442003703002000420037030841b00f4107200041086a10032002200429030037030020002000290308370328200041286a411041d02d410041001000417f460d082000200041286a360290012000411036029401200042003703900220004100200041286a411020004190026a41084100100022022002417f461b22024108200241084922041b22023602980120040d09200041003602900220004198016a4100200041286a411020004190026a41042002100022042004417f461b2204410420044104491b20026a360200200441034d0d09200028029002210720004190026a20004190016a103a2000280290022208450d0920002902940221094108210a200041086a41086a220242003703002000420037030841b00f4107200041086a1003200041286a41086a2204200229030037030020002000290308370328200041286a411010052002420037030020004200370308418f114107200041086a100320042002290300370300200020002903083703284100210b02400240200041286a411041d02d410041001000417f460d0020004210370294012000200041286a3602900120004190026a20004190016a10b601200028029002220a450d052000290294022103200041086a41086a2202420037030020004200370308418f114107200041086a1003200041286a41086a200229030037030020002000290308370328200041286a411010052003422088a7210b2003a7210c0c010b4100210c0b102e2103200041286a41086a220242003703002000420037032841a9164107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411041d02d410041001000417f460d072000420037039002200041086a411020004190026a41084100100041016a41084d0d0d200020002903900220037c3703e002200041286a41086a220242003703002000420037032841c6104107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411041d02d410041001000417f460d062000420037039002200041086a411020004190026a41084100100041016a41084d0d0c2009422088a72111200a200b41286c22026a210f02402007450d0020002903900221034100200a6b20026b21042007210d200f210203402002200a460d01200241586a22102903004200510d01200241606a2003103d200441286a210420102102200d417f6a220d0d000b0b20004190026a104720002802980221042000280290022102200028029402210d200041f8016a200f360200200041fc016a41003a000020004180026a20073602002000200d3602e401200020023602e001200020023602e80120002002200441286c6a3602ec01200020113602f0012000200a3602f40120004184026a200041e0026a360200200041003a00880220004190026a200041e0016a10b90102400240024002400240024002400240024002400240024002400240024002400240024002400240024002402000290390024200510d00417f4100200041ec016a280200200041e0016a41086a2802006b41286d2202200041f0016a2802006b2204200420024b1b220241016a220420042002491b2204ad42287e2203422088a70d1b2003a72202417f4c0d1a4108211202402002450d00200210012212450d160b201220004190026a41086a2202290300370300201241206a200241206a290300370300201241186a200241186a290300370300201241106a200241106a290300370300201241086a200241086a290300370300200020123602482000200436024c410121132000410136025020004190016a41286a200041e0016a41286a28020036020020004190016a41206a200041e0016a41206a29030037030020004190016a41186a200041e0016a41186a29030037030020004190016a41106a2214200041e0016a41106a29030037030020004190016a41086a200041e0016a41086a290300370300200020002903e0013703900120004190026a20004190016a10b90102402000290390024201520d0020004190026a41086a21022000419c016a2115412821104101210d0340200041e8006a41206a220f200241206a290300370300200041e8006a41186a2211200241186a290300370300200041e8006a41106a2216200241106a290300370300200041e8006a41086a2217200241086a290300370300200020022903003703680240200d2004470d00200041c8006a2004417f4100201528020020004190016a41086a2802006b41286d221820142802006b2219201920184b1b221841016a221920192018491b1049200028024821120b0240201220106a22042000290368370300200441206a200f290300370300200441186a2011290300370300200441106a2016290300370300200441086a2017290300370300200041c8006a41086a200d41016a220f36020020004190026a20004190016a10b9012000290390024201520d00201041286a2110200028024c2104200f210d0c010b0b200d41016a21130b024020004198016a220428020022022000419c016a280200220d460d0020042002200d20026b41586a41286e41286c6a41286a3602000b0240200028029401450d0020002802900110020b200028024c211a201341144b0d01201341014d0d022013417f6a210f2012201341286c6a41586a211103402013200f2202417f6a220f490d2102402013200f6b220d4102490d002012200241286c6a221041206a22042903002012200f41286c6a220241206a221629030022035a0d0020004190026a41186a2217200241186a221829030037030020004190026a41106a2219200241106a221429030037030020004190026a41086a2215200241086a221b290300370300200020022903003703900220022010290300370300201b201041086a2903003703002014201041106a2903003703002018201041186a290300370300201620042903003703000240200d4103490d00410221042011210203402004200d4f0d290240200241c8006a221029030020035a0d002004417f6a200d4f0d29200241206a2010290300370300200241186a200241c0006a290300370300200241106a200241386a290300370300200241086a200241306a2903003703002002200241286a221029030037030020102102200441016a2204200d490d010c020b0b200221100b2010200029039002370300201041186a2017290300370300201041106a2019290300370300201041086a2015290300370300201020033703200b201141586a2111200f0d000c030b0b0240200041e8016a22042802002202200041ec016a280200220d460d0020042002200d20026b41586a41286e41286c6a41286a3602000b024020002802e401450d0020002802e00110020b4100211a41082112410021130c010b2013410176221cad42287e2203422088a70d192003a72202417f4c0d184108211d02402002450d0020021001221d450d130b4100210420004100360298012000420437039001201241586a211e201241a87f6a211f4104210d20004190016a41086a21202013212103402021211641002121410121100240024002402016417f6a2202450d0002400240024002400240024002402012200241286c6a41206a29030020122016417e6a221041286c6a41206a29030022035a0d00410021112010450d02201f201641286c6a2102034020032002290300220e5a0d02200241586a2102200e21032010417f6a22100d000c030b0b02402010450d00201f201641286c6a210241022110034020032002290300220e540d04200241586a2102200e21032016201041016a2210470d000b41002121201621102004200028029401470d090c080b41022110410021212004200028029401470d080c070b201021110b024020162011490d00201620134b0d140240201620116b22104101762217450d00201e201641286c6a21022012201141286c6a210f034020004190026a41206a2218200f41206a221929030037030020004190026a41186a2214200f41186a221529030037030020004190026a41106a221b200f41106a222129030037030020004190026a41086a2222200f41086a22232903003703002000200f29030037039002200241086a22242903002103200241106a2225290300210e200241186a22262903002127200229030021282019200241206a2229290300370300201520273703002021200e37030020232003370300200f202837030020292018290300370300202620142903003703002025201b290300370300202420222903003703002002200029039002370300200241586a2102200f41286a210f2017417f6a22170d000b0b2011450d030c020b201120161055000b201620106b2211450d010b201041094d0d010b201121212004200028029401470d030c020b201620134b0d0d2012201141286c6a2117034020162011417f6a2221490d0f0240201620216b22104102490d002012201141286c6a221141206a220f2903002012202141286c6a220241206a221829030022035a0d0020004190026a41186a2219200241186a221429030037030020004190026a41106a2215200241106a221b29030037030020004190026a41086a2222200241086a22232903003703002000200229030037039002200220112903003703002023201141086a290300370300201b201141106a2903003703002014201141186a2903003703002018200f290300370300024020104103490d004102210f201721020340200f20104f0d090240200241c8006a221129030020035a0d00200f417f6a20104f0d0b200241206a2011290300370300200241186a200241c0006a290300370300200241106a200241386a290300370300200241086a200241306a2903003703002002200241286a221129030037030020112102200f41016a220f2010490d010c020b0b200221110b2011200029039002370300201141186a2019290300370300201141106a2015290300370300201141086a2022290300370300201120033703200b2021450d01201741586a2117202121112010410a490d000b0b2004200028029401470d010b20004190016a107a20202802002104200028029001210d0b200d20044103746a22022010360204200220213602002020200441016a2204360200024020044102490d00200028029001210d03400240024002400240200d2004417f6a4103746a2202280200450d00200d20044103746a221141746a280200220f200228020422104d0d00200441024d0d05200d2004417d6a22144103746a28020422022010200f6a4d0d01200441034d0d05201141646a2802002002200f6a4d0d010c050b20044103490d0120022802042110200d2004417d6a22144103746a28020421020b20022010490d010b2004417e6a21140b2004201441016a22154d0d06200420144d0d07200d201441037422226a2202280204222320022802006a2202200d201541037422246a2204280200221b490d08200220134b0d092012201b41286c6a22182004280204221941286c22046a210f200241286c210d024002400240024002402002201b6b221120196b220220194f0d00201d200f200241286c2204101e221120046a211020194101480d0120024101480d01201e200d6a210d200f21020340200d200241586a2216201041586a2217201041786a290300200241786a29030054220f1b2204290300370300200d41206a200441206a290300370300200d41186a200441186a290300370300200d41106a200441106a290300370300200d41086a200441086a29030037030020102017200f1b2110201820162002200f1b22024f0d04200d41586a210d2011210420112010490d000c050b0b201d20182004101e220220046a211020194101480d01201120194c0d012012200d6a2116200221042018210203402002200f2004200f41206a290300200441206a2903005422111b220d290300370300200241206a200d41206a290300370300200241186a200d41186a290300370300200241106a200d41106a290300370300200241086a200d41086a2903003703002004200441286a20111b2104200241286a2102200f41286a200f20111b220f20164f0d04201020044b0d000c040b0b200f21020c010b201821020b201d21040b20022004201020046b220d200d4128706b101e1a2020280200220220144d0d0a200028029001220d20226a2204202320196a3602042004201b360200200220154d0d0b200d20246a2204200441086a200220156b41037441786a10391a20202002417f6a2204360200200441014b0d000b0b20210d000b0240200028029401450d0020002802900110020b201c450d00201d10020b2000201a360294022000201236029002200020133602980220004190026a104a0240201a450d00201210020b200041286a41086a2202420037030020004200370328418d104107200041286a1003200041086a41086a2002290300370300200020002903283703084100211102400240200041086a411041d02d410041001000417f460d0020004210370294012000200041086a3602900120004190026a20004190016a103a2000280290022217450d0f20004198026a2802002111200028029402211e0c010b410121174100211e0b200041a8026a4200370300200041a0026a420037030020004198026a420037030020004200370390022011ad2203421b88a70d0b2003420586a72202417f4c0d0c024002402002450d002002100122020d010c120b410121020b200020113602940120002002360290012000410036029801200041c8006a41186a220d20004190026a41186a290300370300200041c8006a41106a220f20004190026a41106a290300370300200041c8006a41086a221620004190026a41086a290300370300200020002903900237034820004190016a41002011108601200028029001221020002802980122244105746a210202400240024020114102490d0041012104034020022000290348370000200241186a200d290300370000200241106a200f290300370000200241086a2016290300370000200241206a2102200441016a22042011490d000b202420046a417f6a21240c010b2011450d010b20022000290348370000200241186a200041c8006a41186a290300370000200241106a200041c8006a41106a290300370000200241086a200041c8006a41086a290300370000202441016a21240b2009a7211f20004190016a41086a22232024360200200a200b41286c6a2118200028029401212941002113410021164100212620070d0f0c0e0b41ccc100200f2010103c000b41dcc100200f417f6a2010103c000b41acc10020152004103c000b41acc10020142004103c000b201b20021055000b200220131029000b41bcc10020142002103c000b41b4c300103b000b20162011417f6a22214f0d010b202120161055000b201620131029000b1066000b1067000b41c1214133102d000b419201212a0c060b4106212a0c050b41d900212a0c040b41d900212a0c030b41d900212a0c020b4128212a0c010b4126212a0b0340024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240202a0e9601080d94010e95010f101112131415161718191a1b1c1d1e292a2b2c88012f3031323334353638393a3b3c3d3e404155565758595b5c5d5e5f8e0160616263646566676c757677787e7f8001810182018301840185018601797a7c7d6d6e6f707172733f748d0168696a6b5a7b87014243900144454748494a4b4c4d4e4f515253549101920150468f019301372d2e1f2021890122238a0124258b0126278c01280001020405060703090a0b0c0c0b2018200a460d9f01418b01212a0c8a020b201841586a2202290300210320004190026a41186a2204201841786a221929030037030020004190026a41106a220d201841706a221429030037030020004190026a41086a220f201841686a22152903003703002000201841606a22182903003703900220004190016a41186a221d201929030037030020004190016a41106a22252014290300370300202320152903003703002000201829030037039001200041c8006a41186a22182004290300370300200041c8006a41106a2219200d290300370300200041c8006a41086a2214200f290300370300200020002903900237034820034200510d9f01418c01212a0c89020b200041e0016a41186a22152018290300370300200041e0016a41106a221b2019290300370300200041e0016a41086a22212014290300370300200020002903483703e0010c87020b2007417f6a210720152018290300370300201b201929030037030020212014290300370300200020002903483703e0014100211620222102418d01212a0c87020b200041e8006a41186a22122015290300370300200041e8006a41106a2220201b290300370300200041e8006a41086a22222021290300370300200020002903e00137036820042012290300370300200d2020290300370300200f202229030037030020002000290368370390022007450d9301418e01212a0c86020b201641ff01710d9901418f01212a0c85020b200a2002460d9b01419001212a0c84020b200241586a222229030021032004200241786a2216290300370300200d200241706a2212290300370300200f200241686a22202903003703002000200241606a220229030037039002201d201629030037030020252012290300370300202320202903003703002000200229030037039001201820042903003703002019200d2903003703002014200f290300370300200020002903900237034820034200520d9c010c9b010b200041286a41186a2004290300370300200041286a41106a200d290300370300200041286a41086a200f29030037030020002000290390023703280c8e010b201341ff01710d9101419301212a0c81020b2018200a460d9101419401212a0c80020b201841586a22022903002103200041e0016a41186a2204201841786a220d290300370300200041e0016a41106a220f201841706a2216290300370300200041e0016a41086a2219201841686a22142903003703002000201841606a22182903003703e00120004190016a41186a200d29030037030020004190016a41106a201629030037030020232014290300370300200020182903003703900120004190026a41186a220d200429030037030020004190026a41106a2204200f29030037030020004190026a41086a220f2019290300370300200020002903e001370390022003500d9101419501212a0cff010b200041286a41186a200d290300370300200041286a41106a2004290300370300200041286a41086a200f290300370300200020002903900237032841002113410021164101212a0cfe010b20004190026a41186a2204200041286a41186a29030037030020004190026a41106a220d200041286a41106a29030037030020004190026a41086a220f200041286a41086a2903003703002000200029032837039002200041e0016a20004190026a10b50120002802e0014101470d8b014103212a0cfd010b200041e0016a41086a280200211820004190016a41186a2219200429030037030020004190016a41106a2214200d2903003703002023200f290300370300200020002903900237039001200041086a41186a22152019290300370300200041086a41106a22192014290300370300200041086a41086a22142023290300370300200020002903900137030820042015290300370300200d2019290300370300200f20142903003703002000200029030837039002202420184d0d8b014105212a0cfc010b201020184105746a2218200029039002370000201841186a2004290300370000201841106a200d290300370000201841086a200f290300370000202641016a212641002107200221184100450d86014106212a0cfb010b4100450d8d014107212a0cfa010b200c450d93014108212a0cf9010b200a10024109212a0cf8010b20244105742221410575221b201141057441057522022002201b4b1b2218450d9201410a212a0cf7010b20172102201021044100210d410b212a0cf6010b20102017460d9201410c212a0cf5010b2002200441201006450d9201410d212a0cf4010b41071001220f450d9201410e212a0cf3010b2000200f36029002200042073702940220004190026a41004107102720004190026a41086a220f200f280200221141076a221936020020112000280290026a221641002800bf1036000020004190016a41086a22112019360200201641046a41002f00c3103b0000201641066a41002d00c5103a0000200020002903900237039001412010012216450d9201410f212a0cf2010b2000201636029002200042203702940220004190026a410041201027200f200f280200221941206a22163602002019200028029002220f6a20024120101e1a200028029402211420004190016a2011280200201610272000280290012219201128020022156a200f2016101e1a2011201520166a22163602002014450d92014110212a0cf1010b200f10024111212a0cf0010b200028029401210f200041286a41086a221142003703002000420037032820192016200041286a1003200041086a41086a201129030037030020002000290328370308200041086a41101005200f450d91014112212a0cef010b201910024113212a0cee010b200241206a2102200441206a2104200d41016a220d2018490d89014114212a0ced010b201020216a21022024210d201b4104490d8f0141fc00212a0cec010b20004190026a41206a2118200041d0026a2119200041f0026a211420004190036a2115200041a8026a210f200041a0026a211120004198026a21162024210d41fd00212a0ceb010b200f420037030020114200370300201642003703002000420037039002201820022204460de10141fe00212a0cea010b200441606a20004190026a412010060de101418001212a0ce9010b200f42003703002011420037030020164200370300200042003703900220192004460de101418101212a0ce8010b200441406a20004190026a412010060de101418301212a0ce7010b200f42003703002011420037030020164200370300200042003703900220142004460de101418401212a0ce6010b200441a07f6a20004190026a412010060de101418601212a0ce5010b200f420037030020114200370300201642003703002000420037039002200441807f6a210220152004460de101418701212a0ce4010b200220004190026a412010060de101418901212a0ce3010b200d417c6a210d200220106b41057541034b0d86014115212a0ce2010b20102002460d86014116212a0ce1010b20004190026a41206a2104200041a8026a210f200041a0026a211120004198026a21164117212a0ce0010b200f42003703002011420037030020164200370300200042003703900220042002460d86014118212a0cdf010b200241606a20004190026a412010060d860141fa00212a0cde010b200d417f6a210d2010200241606a2202470d830141fb00212a0cdd010b4100450d8f01411a212a0cdc010b200d41016a22022024202420024b1b2124411b212a0cdb010b20002029360294012000201036029001200020243602980120004190026a20004190016a10a20120002802980221042000280290022102200041286a41086a220d420037030020004200370328418d104107200041286a1003200041086a41086a200d29030037030020002000290328370308200041086a4110200220041004200028029402450d8e01411c212a0cda010b20021002411d212a0cd9010b2029450d8d01411e212a0cd8010b20101002411f212a0cd7010b2000202636029002200041286a41086a220242003703002000420037032841cd104107200041286a1003200041086a41086a2204200229030037030020002000290328370308200041086a411020004190026a41041004200242003703002000420037032841b70f4107200041286a10032004200229030037030020002000290328370308200041086a411041d02d410041001000417f460d8c014120212a0cd6010b2000410036029002200041086a411020004190026a41044100100041016a41044d0d8c014121212a0cd5010b20002802900241016a21020c8c010b410121024122212a0cd3010b2000200236029002200041286a41086a220242003703002000420037032841b70f4107200041286a1003200041086a41086a200229030037030020002000290328370308200041086a411020004190026a41041004201e450d8b014123212a0cd2010b201710024124212a0cd1010b201f450d8a014125212a0cd0010b200810024126212a0ccf010b2006450d89014127212a0cce010b200510024128212a0ccd010b20004190026a412c6a212520004190026a410472212620004190026a41206a210d20004190016a412c6a2122200041e0016a41086a2123200041e0016a4104722120200041e0016a410c6a21290c88010b20004190026a41286a200041e0016a41286a290300370300200d200041e0016a41206a29030037030020004190026a41186a200041e0016a41186a29030037030020004190026a41106a200041e0016a41106a29030037030020042023290300370300200020002903e0013703900220004190026a410210ba014129212a0ccb010b200041e0026a10bb0120002802e002210241062112200041e0026a41086a2210280200220f450d9001412a212a0cca010b20022903002103200041c8006a41186a2211200241206a290000370300200041c8006a41106a2216200241186a290000370300200041c8006a41086a2217200241106a290000370300200020022900083703484106211220032001520d900141e100212a0cc9010b200f417f6a2218ad42287e2203422088a70db50141e200212a0cc8010b2003a72204417f4c0db50141e400212a0cc7010b2004450db50141e500212a0cc6010b2004100122190daf010cae010b4108211941e600212a0cc4010b20004190026a41086a220441003602002000201836029402200020193602900220004190026a4100200f41286c41586a41286e220f108201200420042802002218200f6a360200200028029002201841286c6a200241286a200f41286c101e1a2023200428020036020020002000290390023703e001200041e0016a10bc0120002802e401450db30141e700212a0cc3010b20002802e001100241e800212a0cc2010b200041e8006a41186a22142011290300370300200041e8006a41106a22152016290300370300200041e8006a41086a221b20172903003703002000200029034837036841071001220f450dac0141e900212a0cc1010b2000200f36029002200042073702940220004190026a41004107102720042004280200220f41076a2218360200200f2000280290026a220f41002800eb2236000020232018360200200f41046a41002f00ef223b0000200f41066a41002d00f1223a000020002000290390023703e00141201001220f450dac0141ea00212a0cc0010b2000200f36029002200042203702940220004190026a41004120102720042004280200221841206a220f360200201820002802900222196a22182000290368370000201841086a201b290300370000201841106a2015290300370000201841186a20142903003700002000280294022115200041e0016a2023280200200f102720002802e0012218202328020022146a2019200f101e1a20232014200f6a22143602002015450db00141eb00212a0cbf010b2019100241ec00212a0cbe010b20002802e401211d200041086a41086a220f42003703002000420037030820182014200041086a1003200041286a41086a2219200f29030037030020002000290308370328200041286a411041d02d410041001000417f460daf0141ed00212a0cbd010b2000421037020c2000200041286a36020820004190026a200041086a10bd0120002802900222124106460daf0141ee00212a0cbc010b200041e0016a41286a202641286a280200360200200041e0016a41206a202641206a290200370300200041e0016a41186a202641186a290200370300200041e0016a41106a202641106a2902003703002023202641086a290200370300200020262902003703e001200f42003703002000420037030820182014200041086a10032019200f29030037030020002000290308370328200041286a411010050caf010b4106211241ef00212a0cba010b20004190026a41286a220f200041e0016a41286a2219280200360200200d200041e0016a41206a221429030037030020004190026a41186a2215200041e0016a41186a221b29030037030020004190026a41106a2221200041e0016a41106a222429030037030020042023290300370300200020002903e00137039002201d450dae0141f000212a0cb9010b2018100241f100212a0cb8010b20124106460dad0141f200212a0cb7010b2019200f2802003602002014200d290300370300201b2015290300370300202420212903003703002023200429030037030020002000290390023703e001200f2019280200360200200d20142903003703002015201b290300370300202120242903003703002004202329030037030020252000290348370200202541086a2017290300370200202541106a2016290300370200202541186a2011290300370200200020002903e0013703900220004190016a20004190026a41cc00101e1a412b212a0cb6010b20002802e402450d7d412c212a0cb5010b20021002412d212a0cb4010b20124106460d7c412e212a0cb3010b2020200029029001370200202041086a20004190016a41086a290200370200202041106a20004190016a41106a290200370200202041186a20004190016a41186a290200370200202041206a20004190016a41206a290200370200202041286a20004190016a41286a280200360200200020123602e001200041e8006a41186a2215202241186a290000370300200041e8006a41106a221b202241106a290000370300200041e8006a41086a2221202241086a29000037030020002022290000370368200041e0026a104720002802e00221242010280200221d41286c2217450d7c412f212a0cb2010b4100211441002119202421020c7c0b4102211120180d82010c81010b200d200229000037000020004190026a41186a201529030037030020004190026a41106a201b29030037030020004190026a41086a2021290300370300200d41086a200241086a290000370000200d41106a200241106a290000370000200d41186a200241186a2900003700002000200029036837039002410910012204450d7c4131212a0caf010b200020043602482000420937024c200041c8006a410041091027200041c8006a41086a22102010280200220441096a220f360200200420002802486a221141002900f922370000200041286a41086a2204200f360200201141086a41002d0081233a000020002000290348370328200041c8006a20004190026a10be01200028024c211820002802482111200041286a20042802002010280200220f102720002802282210200428020022166a2011200f101e1a20042016200f6a22163602002018450d7c4132212a0cae010b201110024133212a0cad010b200028022c2118200041086a41086a220f42003703002000420037030820102016200041086a10032004200f29030037030020002000290308370328200041286a411041d02d410041001000417f460d7b4134212a0cac010b200041003a0048200041286a4110200041c8006a41014100100041016a41014d0d7b4136212a0cab010b20002d00482111200f42003703002000420037030820102016200041086a10032004200f29030037030020002000290308370328200041286a411010052018450d7d4137212a0caa010b201010024138212a0ca9010b201141ff01714102460d7c4139212a0ca8010b201420114101716a211420192011417f734101716a2119413a212a0ca7010b200241286a2102201741586a22170d72413b212a0ca6010b201920146a210220002802e402450d7a413c212a0ca5010b20241002413d212a0ca4010b201d20026b210220124103470d7b41da00212a0ca3010b20002d00e40141ff01714102470d7b41db00212a0ca2010b20190d7e41dc00212a0ca1010b20020d7c41dd00212a0ca0010b202328020010460c790b2014200220196a4d0d7941d000212a0c9e010b410910012204450d810141d100212a0c9d010b2000200436029002200042093702940220004190026a41004109102720004190026a41086a22042004280200221041096a220f36020020102000280290026a2211410029009823370000200041c8006a41086a2210200f360200201141086a41002d00a0233a0000200020002903900237034841201001220f450d810141d200212a0c9c010b2000200f36029002200042203702940220004190026a41004120102720042004280200221141206a220f360200201120002802900222166a22112000290368370000201141086a2021290300370000201141106a201b290300370000201141186a20152903003700002000280294022117200041c8006a2010280200200f102720002802482211201028020022186a2016200f101e1a20102018200f6a220f3602002017450d810141d300212a0c9b010b2016100241d400212a0c9a010b200028024c2110200041286a41086a22164200370300200042003703282011200f200041286a1003200041086a41086a201629030037030020002000290328370308200041086a411010052010450d800141d500212a0c99010b2011100241d600212a0c98010b20022019720d7f41d800212a0c97010b20004190026a41286a200041e0016a41286a290300370300200d200041e0016a41206a29030037030020004190026a41186a200041e0016a41186a29030037030020004190026a41106a200041e0016a41106a29030037030020042023290300370300200020002903e0013703900220004190026a410110ba010c530b201241077122024103460d7341c000212a0c95010b20020d5241c100212a0c94010b20002802e4012202450d5441c200212a0c93010b20024101470d7141cc00212a0c92010b2029280200450d5341cd00212a0c91010b202328020010020c530b4100211941002114410041006a210220002802e4020d660c650b20002d00e4014101470d4d41cf00212a0c8e010b202310bf010c4d0b20232802002110200041e0016a41106a2802002202450d6c41c400212a0c8c010b200241186c21042010210241c500212a0c8b010b200241046a280200450d6c41c600212a0c8a010b2002280200100241c700212a0c89010b200241106a280200450d6b41c800212a0c88010b2002410c6a280200100241c900212a0c87010b200241186a2102200441686a22040d6741ca00212a0c86010b2029280200450d4941cb00212a0c85010b201010020c490b200041f0026a24000f0b200d417f6a210d41010d340c330b200d417f6a210d41010d310c300b200d417e6a210d41010d2e0c2d0b200d417d6a210d41010d2b0c2a0b200d417c6a210d41010d280c270b101c000b41c1214133102d000b1064000b1065000b4187254139102d000b41c1214133102d000b41c1214133102d000b41f316411c102d000b41b43820182024103c000b419201212a0c740b4101212a0c730b4100212a0c720b4102212a0c710b4104212a0c700b4107212a0c6f0b4107212a0c6e0b4107212a0c6d0b418a01212a0c6c0b4107212a0c6b0b4107212a0c6a0b4107212a0c690b4107212a0c680b4107212a0c670b419101212a0c660b4109212a0c650b4114212a0c640b410b212a0c630b4113212a0c620b4113212a0c610b41d900212a0c600b41d900212a0c5f0b4111212a0c5e0b4113212a0c5d0b4115212a0c5c0b41fd00212a0c5b0b41fb00212a0c5a0b4117212a0c590b41fa00212a0c580b4119212a0c570b411b212a0c560b411a212a0c550b411b212a0c540b411a212a0c530b411b212a0c520b411a212a0c510b411b212a0c500b411a212a0c4f0b411b212a0c4e0b411a212a0c4d0b411b212a0c4c0b411d212a0c4b0b411f212a0c4a0b41f900212a0c490b41f800212a0c480b4122212a0c470b4124212a0c460b4126212a0c450b4128212a0c440b4129212a0c430b4129212a0c420b4129212a0c410b4129212a0c400b4129212a0c3f0b4129212a0c3e0b4129212a0c3d0b4129212a0c3c0b4129212a0c3b0b4129212a0c3a0b412b212a0c390b412b212a0c380b412d212a0c370b41e000212a0c360b41df00212a0c350b4130212a0c340b4130212a0c330b41d900212a0c320b4133212a0c310b41de00212a0c300b4135212a0c2f0b4138212a0c2e0b4137212a0c2d0b4138212a0c2c0b413a212a0c2b0b413d212a0c2a0b413d212a0c290b413c212a0c280b413e212a0c270b413e212a0c260b413f212a0c250b413f212a0c240b413f212a0c230b413f212a0c220b41ce00212a0c210b41c300212a0c200b41ca00212a0c1f0b41c500212a0c1e0b41c700212a0c1d0b41c900212a0c1c0b41d900212a0c1b0b41d900212a0c1a0b41d400212a0c190b41d600212a0c180b41d700212a0c170b41d900212a0c160b41e600212a0c150b41d900212a0c140b41d900212a0c130b41f700212a0c120b41e300212a0c110b41f600212a0c100b41e800212a0c0f0b41ec00212a0c0e0b41f500212a0c0d0b41f400212a0c0c0b41ef00212a0c0b0b41f100212a0c0a0b41f300212a0c090b418001212a0c080b41ff00212a0c070b418301212a0c060b418201212a0c050b418601212a0c040b418501212a0c030b418901212a0c020b418801212a0c010b418d01212a0c000b0b41c1214133102d000b1057000b1056000b41f4214122102d000b41f4214122102d000b41be164135102d000b41c1214133102d000b200f20131055000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41dcc1002004417f6a200d103c000b41ccc1002004200d103c000ba50c03047f017e177f23004180026b22012400200141b0016a41086a22024200370300200142003703b0014191264107200141b0016a1003200141086a2002290300370300200120012903b0013703000240024002400240024002402001411041d02d410041001000417f460d002001200136021020014110360214200141003602b0012001410020014110200141b0016a41044100100022022002417f461b2202410420024104491b2203360218200241034d0d0320012802b0012204ad42d8007e2205422088a70d052005a72202417f4c0d042002450d012002100122060d02101c000b200041003602082000420837020020014180026a24000f0b410821060b20012004360224200120063602202001410036022802402004450d0020014180016a41086a210720014180016a4104722108200121094100210a4110210b4100210c0340200141003602b001200141106a41086a220d41002009200b200141b0016a41042003100022022002417f461b2202410420024104491b20036a3602000240024002400240200241034d0d0020012802b001210e200141b0016a200141106a10bd0120012802b0014106460d0020014180016a41286a200141b0016a41286a220f29030037030020014180016a41206a200141b0016a41206a221029030037030020014180016a41186a2211200141b0016a41186a221229030037030020014180016a41106a2213200141b0016a41106a22142903003703002007200141b0016a41086a2215290300370300200120012903b00137038001200141e0016a41186a22164200370300200141e0016a41106a22174200370300200141e0016a41086a22184200370300200142003703e001200d200d28020022024100200128021022092001280214220b200141e0016a41202002100022022002417f461b2202412020024120491b6a220336020002402002411f4d0d00200141306a41186a22022016290300370300200141306a41106a220d2017290300370300200141306a41086a22162018290300370300200120012903e001370330200141d0006a41086a2217200841086a290200370300200141d0006a41106a2218200841106a290200370300200141d0006a41186a2219200841186a290200370300200141d0006a41206a221a200841206a290200370300200141d0006a41286a221b200841286a28020036020020012008290200370350200128028001221c4106460d01200c41016a210c200f201b2802003602002010201a290300370300201220192903003703002014201829030037030020152017290300370300200720162903003703002013200d29030037030020112002290300370300200120012903503703b0012001200129033037038001200a2001280224470d04200141206a1074200141206a41086a280200210a200128022021060c040b0240024020012802800122024103460d0020020d022001280284012202450d0220024101470d012001418c016a280200450d0220014188016a280200100220012802202103200a0d030c040b20012d0084014101470d012007104b20012802202103200a0d020c030b20014188016a2802002103024020014180016a41106a2802002202450d00200241186c21082003210203400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200841686a22080d000b0b2001418c016a280200450d00200310020b20012802202103200a450d010b200a41d8006c210820032102034020021038200241d8006a2102200841a87f6a22080d000b0b2001280224450d03200310020c030b2006200a41d8006c6a2202201c3602002002411c6a2012290300370200200241146a20142903003702002002410c6a2015290300370200200220012903b001370204200241246a20102903003702002002412c6a200f2802003602002002200e36023020022001290380013702342002413c6a2007290300370200200241c4006a2013290300370200200241cc006a2011290300370200200141206a41086a200a41016a220a360200200c2004490d000b200128022021060b2006450d00200020012902243702042000200636020020014180026a24000f0b41c1214133102d000b1059000b1058000b8d0402057f017e230041c0006b220224000240024002400240410810012203450d002002200336023020024208370234200241306a4100410810272002280230200228023822036a42e4cab5d3c3ac99b83a3700002002200341086a360238200241086a200228023836020020022002290330370300410410012203450d002002200336023020024204370234200241306a41004104102720022802302203200228023822046a20013600002002200441046a220136023820022802342105200220022802082001102720022802002204200228020822066a20032001101e1a2002200620016a220136020802402005450d00200310020b20022802042103200241306a41086a220542003703002002420037033020042001200241306a1003200241086a20052903003703002002200229033037030002402002411041d02d410041001000417f460d002002200236021020024110360214200242003703302002410020024110200241306a41084100100022012001417f461b2201410820014108491b360218200141074d0d0220022903302107200241306a200241106a103a20022802302201450d022002200229023437032020002001360208200020073703002000200229032037020c200041146a200241286a2802003602002003450d040c030b2000410036020820030d020c030b101c000b41c1214133102d000b200410020b200241c0006a24000bda0101027f0240024020002802002201450d0020014103470d0120002d00044101470d01200041086a22012802001038200128020010020f0b20002802042201450d00024020014101470d002000410c6a280200450d01200041086a28020010020f0b0240200041106a2802002202450d00200041086a2802002101200241186c210203400240200141046a280200450d00200128020010020b0240200141106a280200450d002001410c6a28020010020b200141186a2101200241686a22020d000b0b2000410c6a280200450d00200041086a28020010020f0b0b0a00200020012002100b0bc80403067f017e097f230041d0006b220224002002410036023020012001280208220341002001280200220420012802042205200241306a41042003100022032003417f461b2203410420034104491b6a220636020802400240024002400240200341034d0d0020022802302207ad2208421b88a70d042008420586a72203417f4c0d032003450d012003100122090d02101c000b20004100360200200241d0006a24000f0b410121090b20022007360204200220093602002002410036020802402007450d00200241306a41186a210a200241306a41106a210b410021034100210c0340200a4200370300200b4200370300200241306a41086a220d420037030020024200370330200141086a410020042005200241306a412020061000220e200e417f461b220e4120200e4120491b20066a220636020002400240200e411f4d0d00200c41016a210c200241106a41186a220f200a290300370300200241106a41106a2210200b290300370300200241106a41086a2211200d2903003703002002200229033037031020032002280204470d012002107c200241086a2802002103200228020021090c010b2000410036020002402002280204450d00200910020b200241d0006a24000f0b200920034105746a220e2002290310370000200e41186a200f290300370000200e41106a2010290300370000200e41086a2011290300370000200241086a200341016a2203360200200c2007490d000b0b20002002290300370200200041086a200241086a280200360200200241d0006a24000f0b1067000b1066000b2c02017f017e230041106b2201240020002902102102200120002902083703002001200237030820011054000b070020001054000bab0303017f017e047f230041306b220224002000104321030240410810012204450d002002200436022020024208370224200241206a4100410810272002280220200228022822046a42f3e885d3a3ac98b63a3700002002200441086a360228200241106a41086a200228022836020020022002290320370310412010012204450d00200320017c21012002200436022020024220370224200241206a41004120102720022802202205200228022822066a22042000290000370000200441086a200041086a290000370000200441106a200041106a290000370000200441186a200041186a2900003700002002200641206a220036022820022802242106200241106a20022802182000102720022802102204200228021822076a20052000101e1a2002200720006a220036021802402006450d00200510020b2002280214210520022001370308200241206a41086a220642003703002002420037032020042000200241206a1003200241106a41086a200629030037030020022002290320370310200241106a4110200241086a4108100402402005450d00200410020b200241306a24000f0b101c000bcb0501097f230041306b22012400200041086a28020021022001410036022820014201370320200141206a4100410410272001280220200128022822036a20023600002001200341046a360228200141086a220420012802283602002001200129032037030002400240024002402002450d0020002802002100200241d8006c21050340200141106a41086a2203410036020020014201370310200041306a2802002102200141106a41004104102720032003280200220641046a2207360200200620012802106a2002360000200141206a200010d80120012802202108200141106a2007200141206a41086a22062802002202102720032002200328020022076a2209360200200720012802106a20082002101e1a02402001280224450d00200810020b200141106a20094120102720032003280200220741206a22023602002007200128021022086a220341086a2000413c6a290000370000200341106a200041c4006a290000370000200341186a200041cc006a2900003700002003200041346a2900003700002002417f4c0d03024002402002450d002002100122030d010c060b410121030b200641003602002001200236022420012003360220200141206a41002002102720062006280200220720026a22033602002007200128022022066a20082002101e1a2001280224210202402001280214450d00200810020b200120042802002003102720012802002207200428020022086a20062003101e1a2004200820036a220336020002402002450d00200610020b200041d8006a2100200541a87f6a22050d000c020b0b20012802082103200128020021070b20012802042100200141206a41086a22024200370300200142003703204191264107200141206a1003200141106a41086a200229030037030020012001290320370310200141106a411020072003100402402000450d00200710020b200141306a24000f0b1019000b101c000be50c03037f017e047f230041a0016b22032400200341086a220442003703002003420037030041852741072003100320034180016a41086a200429030037030020032003290300370380010240024020034180016a411041d02d410041001000417f460d00200341003602400240024020034180016a4110200341c0006a41044100100041016a41044d0d00024020032802402205450d0020032005417f6a104020032802084106460d00200341c0006a41086a2204200341086a290300370300200341c0006a41386a200341386a290300370300200341c0006a41306a200341306a290300370300200341c0006a41286a200341286a290300370300200341c0006a41206a200341206a290300370300200341c0006a41186a200341186a290300370300200341c0006a41106a200341106a290300370300200320032903002206370340024002400240200428020022044103460d0020040d02200341cc006a2802002204450d0220044101470d01200341d4006a280200450d02200341d0006a280200100220062000580d030c070b200341cc006a2d00004101470d01200341d0006a102220062000580d020c060b200341c0006a41106a28020021070240200341c0006a41186a2802002204450d00200441186c21082007210403400240200441046a280200450d00200428020010020b0240200441106a280200450d002004410c6a28020010020b200441186a2104200841686a22080d000b0b200341d4006a280200450d00200710020b20062000560d040b2003200541016a360240200341086a220442003703002003420037030041852741072003100320034180016a41086a22082004290300370300200320032903003703800120034180016a4110200341c0006a41041004200341c0006a41106a200141086a290300370300200341c0006a41186a200141106a290300370300200341c0006a41206a200141186a290300370300200341c0006a41286a200141206a290300370300200341f0006a200141286a29030037030020032000370340200320023a007820032001290300370348410810012201450d01200320013602002003420837020420034100410810272003280200200328020822016a42e4cab5d383cedcb73a3700002003200141086a360208200820032802083602002003200329030037038001410410012201450d01200341c0006a41086a21022003200136020020034204370204200341004104102720032802002204200328020822016a20053600002003200141046a22013602082003280204210820034180016a20032802880120011027200328028001220520032802880122076a20042001101e1a2003200720016a22073602880102402008450d00200410020b200328028401210841002104200341003602980120034201370390012003290340210020034190016a41004108102720032802900120032802980122016a20003700002003200141086a2209360298012003200210d8012003280200210220034190016a20092003280208220110272003200120032802980122096a220a3602980120092003280290016a20022001101e1a02402003280204450d00200210020b02400240200341f8006a2d000022014103714102460d0020014101470d01410121040c010b410221040b20034190016a200a4101102720034190016a41086a22012001280200220241016a2209360200200220032802900122016a20043a0000200341086a2204420037030020034200370300200520072003100320034180016a41086a2004290300370300200320032903003703800120034180016a41102001200910040240200328029401450d00200110020b02402008450d00200510020b024002400240200328024822014103460d0020010d02200341cc006a2802002201450d0220014101470d01200341d4006a280200450d02200341d0006a2802001002200341a0016a24000f0b200341cc006a2d00004101470d01200341d0006a1022200341a0016a24000f0b0240200341c0006a41186a2802002204450d00200341c0006a41106a2802002101200441186c210403400240200141046a280200450d00200128020010020b0240200141106a280200450d002001410c6a28020010020b200141186a2101200441686a22040d000b0b200341d4006a280200450d00200341d0006a28020010020b200341a0016a24000f0b41c1214133102d000b101c000b41f4214122102d000b4184c000103b000b810a03057f017e067f230041c0016b220224000240024002400240410810012203450d002002200336029001200242083702940120024190016a41004108102720022802900120022802980122036a42e4cab5d383cedcb73a3700002002200341086a36029801200241e0006a41086a2002280298013602002002200229039001370360410410012203450d002002200336029001200242043702940120024190016a410041041027200228029001220320022802980122046a20013600002002200441046a2201360298012002280294012105200241e0006a20022802682001102720022802602204200228026822066a20032001101e1a2002200620016a220136026802402005450d00200310020b2002280264210520024190016a41086a2203420037030020024200370390012004200120024190016a1003200241086a41086a20032903003703002002200229039001370308024002400240200241086a411041d02d410041001000417f460d002002200241086a3602182002411036021c200242003703900120024100200241086a411020024190016a41084100100022012001417f461b2201410820014108491b360220200141074d0d06200229039001210720024190016a200241186a10bd012002280290014106460d06200241e0006a41286a20024190016a41286a290300370300200241e0006a41206a20024190016a41206a290300370300200241e0006a41186a20024190016a41186a290300370300200241e0006a41106a20024190016a41106a290300370300200241e0006a41086a20024190016a41086a2903003703002002200229039001370360200241003a0030200241186a41086a2201200128020022012002280218200228021c200241306a41012001100041016a220141014b6a360200024020014102490d0020022d0030220141034f0d00200241386a2206200241ec006a290200370300200241c0006a2208200241e0006a41146a290200370300200241c8006a2209200241e0006a411c6a290200370300200241d0006a220a200241e0006a41246a290200370300200241d8006a220b200241e0006a412c6a2802003602002002200229026437033020022802602103200241286a41066a220c200241e0006a41066a2d00003a0000200241286a41046a220d200241e0006a41046a2f00003b01002002200228006036022820034106460d0720002003360208200020073703002000200229033037020c20002002280228360039200041386a20013a0000200041146a20062903003702002000411c6a2008290300370200200041246a20092903003702002000412c6a200a290300370200200041346a200b2802003602002000413d6a200d2f01003b00002000413f6a200c2d00003a000020050d020c030b200228026022010d0420022802642201450d0620014101460d05200241e8006a28020021030240200241e0006a41106a2802002201450d00200141186c21002003210103400240200141046a280200450d00200128020010020b0240200141106a280200450d002001410c6a28020010020b200141186a2101200041686a22000d000b0b200241ec006a280200450d06200310020c060b200041063602082005450d010b200410020b200241c0016a24000f0b101c000b20014103470d0120022d00644101470d01200241e8006a104b41c1214133102d000b200241ec006a280200450d00200241e8006a280200100241c1214133102d000b41c1214133102d000b080041fc31103b000b960201057f230041206b220224000240410810012203450d002002200336021020024208370214200241106a4100410810272002280210200228021822036a42e4cab5d3e38e9db93a3700002002200341086a360218200241086a200228021836020020022002290310370300410410012203450d002002200336021020024204370214200241106a41004104102720022802102203200228021822046a20013600002002200441046a220136021820022802142105200220022802082001102720022802002204200228020822066a20032001101e1a2002200620016a220136020802402005450d00200310020b2002280204210320002004200110da0102402003450d00200410020b200241206a24000f0b101c000bc70302057f017e230041206b220124000240410810012202450d002001200236021020014208370214200141106a4100410810272001280210200128021822026a42f3e885d3a3ac98b63a3700002001200241086a360218200141086a200128021836020020012001290310370300412010012202450d002001200236021020014220370214200141106a41004120102720012802102203200128021822046a22022000290000370000200241086a200041086a290000370000200241106a200041106a290000370000200241186a200041186a2900003700002001200441206a220036021820012802142104200120012802082000102720012802002202200128020822056a20032000101e1a2001200520006a220036020802402004450d00200310020b2001280204210342002106200141106a41086a220442003703002001420037031020022000200141106a1003200141086a200429030037030020012001290310370300024002402001411041d02d410041001000417f460d002001420037031020014110200141106a41084100100041016a41084d0d01200129031021060b02402003450d00200210020b200141206a240020060f0b41c1214133102d000b101c000bc70302057f017e230041206b220124000240410810012202450d002001200236021020014208370214200141106a4100410810272001280210200128021822026a42f3e885d3c3cdd8b73a3700002001200241086a360218200141086a200128021836020020012001290310370300412010012202450d002001200236021020014220370214200141106a41004120102720012802102203200128021822046a22022000290000370000200241086a200041086a290000370000200241106a200041106a290000370000200241186a200041186a2900003700002001200441206a220036021820012802142104200120012802082000102720012802002202200128020822056a20032000101e1a2001200520006a220036020802402004450d00200310020b2001280204210342002106200141106a41086a220442003703002001420037031020022000200141106a1003200141086a200429030037030020012001290310370300024002402001411041d02d410041001000417f460d002001420037031020014110200141106a41084100100041016a41084d0d01200129031021060b02402003450d00200210020b200141206a240020060f0b41c1214133102d000b101c000bb80201047f230041206b2202240020024100360208200242013703002001280200210320024100410410272002280200200228020822046a20033600002002200441046a2203360208200220034120102720022802002204200228020822056a22032001290004370000200341086a2001410c6a290000370000200341106a200141146a290000370000200341186a2001411c6a2900003700002002200541206a220136020802402001417f4c0d00024002402001450d002001100122030d01101c000b410121030b200220013602142002200336021020024100360218200241106a41002001102720022002280218220320016a360218200320022802106a20042001101e1a200041086a20022802183602002000200229031037020002402002280204450d00200410020b200241206a24000f0b1019000bc808010d7f230041d0006b220124000240410810012202450d00200120023602082001420837020c200141086a4100410810272001280208200128021022026a42e4cab5d383cedcb73a3700002001200241086a360210200141c0006a41086a200128021036020020012001290308370340410410012202450d00200120023602082001420437020c200141086a41004104102720012802082203200128021022026a20003600002001200241046a2202360210200128020c2104200141c0006a20012802482002102720012802402205200128024822066a20032002101e1a2001200620026a220236024802402004450d00200310020b20012802442103200141c0006a41086a220442003703002001420037034020052002200141c0006a1003200141306a41086a200429030037030020012001290340370330200141306a4110100502402003450d00200510020b410810012202450d00200120023602082001420837020c200141086a4100410810272001280208200128021022026a42e4cab5d3e38e9db93a3700002001200241086a360210200141c0006a41086a200128021036020020012001290308370340410410012202450d00200120023602082001420437020c200141086a41004104102720012802082203200128021022026a20003600002001200241046a2202360210200128020c2104200141c0006a20012802482002102720012802402205200128024822066a20032002101e1a2001200620026a220236024802402004450d00200310020b20012802442103200141c0006a41086a220442003703002001420037034020052002200141c0006a1003200141306a41086a200429030037030020012001290340370330200141306a4110100502402003450d00200510020b200141086a20001042200128020c210720012802082108024020012802102202450d0020024105742109200141086a410472210420082102034020042002290000370000200441186a200241186a290000370000200441106a200241106a290000370000200441086a200241086a29000037000020012000360208410810012203450d022001200336024020014208370244200141c0006a410041081027200141c0006a41086a22032003280200220541086a360200200520012802406a42e4cab5d3e3ee9bba3a370000200141306a41086a2205200328020036020020012001290340370330200141c0006a200141086a10452001280244210a2001280240210b200141306a20052802002003280200220610272001280230220c2005280200220d6a200b2006101e1a2005200d20066a22063602000240200a450d00200b10020b2001280234210b2003420037030020014200370340200c2006200141c0006a10032005200329030037030020012001290340370330200141306a411010050240200b450d00200c10020b200241206a2102200941606a22090d000b0b02402007450d00200810020b200141d0006a24000f0b101c000b810604047f017e097f037e230041e0006b22012400200141c0006a41086a220242003703002001420037034041c7114107200141c0006a1003200141086a2002290300370300200120012903403703000240024002400240024002402001411041d02d410041001000417f460d0020014100360240410020014110200141c0006a41044100100022022002417f461b220341034d0d0320012802402204ad42287e2205422088a70d042005a72202417f4c0d052002450d012002100122060d02101c000b2000410036020820004208370200200141e0006a24000f0b410821060b200120043602142001200636021020014100360218024002402004450d002003410420034104491b2107200141c0006a41186a2108200141c0006a41086a2109410021034100210a034020084200370300200141c0006a41106a220b42003703002009420037030020014200370340410020014110200141c0006a41202007100022022002417f461b2202411f4d0d02200141206a41186a220c2008290300370300200141206a41106a220d200b290300370300200141206a41086a220e20092903003703002001200129034037032020014200370340410020014110200141c0006a41082002412020024120491b20076a2207100022022002417f461b220241074d0d02200a41016a210a2002410820024108491b2102200129034021052008200c290300370300200b200d2903003703002009200e29030037030020012001290320370340024020032001280214470d00200141106a1078200141106a41086a2802002103200128021021060b200220076a21072006200341286c6a220220012903403703002009290300210f200b29030021102008290300211120022005370320200241186a2011370300200241106a2010370300200241086a200f370300200141106a41086a200341016a2203360200200a2004490d000b200128021021060b2006450d012000200129021437020420002006360200200141e0006a24000f0b2001280214450d00200610020b41c1214133102d000b1056000b1057000bf81505037f017e087f017e047f230041f0006b22002400200041086a41086a220142003703002000420037030841c81d4107200041086a1003200041d0006a41086a200129030037030020002000290308370350024002400240024002400240200041d0006a411041d02d410041001000417f460d00200042003703080240024002400240200041d0006a4110200041086a41084100100041016a41084d0d002000200029030842017c370340200041086a41086a220142003703002000420037030841c81d4107200041086a1003200041d0006a41086a2202200129030037030020002000290308370350200041d0006a4110200041c0006a41081004200142003703002000420037030841cf1d4107200041086a100320022001290300370300200020002903083703500240200041d0006a411041d02d410041001000417f460d0020004200370308200041d0006a4110200041086a41084100100041016a41084d0d02200020002903082203370330200041086a41086a220142003703002000420037030841c11d4107200041086a1003200041d0006a41086a200129030037030020002000290308370350200041d0006a411041d02d410041001000417f460d0920004200370308200041d0006a4110200041086a41084100100041016a41084d0d0320032000290308510d0020002003370340200041086a41086a220142003703002000420037030841c11d4107200041086a1003200041d0006a41086a2202200129030037030020002000290308370350200041d0006a4110200041c0006a410810042000102e370340200142003703002000420037030841ba1d4107200041086a10032002200129030037030020002000290308370350200041d0006a4110200041c0006a410810040b200041086a41086a220142003703002000420037030841d61d4108200041086a1003200041d0006a41086a2001290300370300200020002903083703504100210102400240200041d0006a411041d02d410041001000417f460d00200042103702442000200041d0006a360240200041086a200041c0006a103a20002802082204450d0b200041106a2802002101200028020c21050c010b41012104410021050b2000410036024820004208370340200041c0006a20014105742206410575108501200028024821022000280240210702402006450d002007200241286c6a21012002200641606a4105766a2108200421020340200041086a41186a2209200241186a290000370300200041086a41106a220a200241106a290000370300200041086a41086a220b200241086a29000037030020002002290000370308200041086a10432103200041086a1044210c200041d0006a41186a220d2009290300370300200041d0006a41106a2209200a290300370300200041d0006a41086a220a200b290300370300200020002903083703502001200c20037c370300200141206a200d290300370300200141186a2009290300370300200141106a200a290300370300200141086a2000290350370300200141286a2101200241206a2102200641606a22060d000b200841016a21020b02402005450d00200410020b200041c0006a41086a20023602002000280244210820072002410041202002676b10c401200041086a41086a220142003703002000420037030841de1d4107200041086a1003200041d0006a41086a200129030037030020002000290308370350200041d0006a411041d02d410041001000417f460d0520004100360208200041d0006a4110200041086a41044100100041016a41044d0d032000280208210b2000410036024820004201370340200041c0006a4100200241286c220941286d2201200b2001200b491b1086012000280248210a2000280240210e0240200b450d00200e200a4105746a2102200041086a41086a21062007210103402009450d01200041086a41206a200141206a290300370300200041086a41186a200141186a290300370300200041086a41106a200141106a2903003703002006200141086a290300370300200041d0006a41086a220d200641086a290000370300200041d0006a41106a2204200641106a290000370300200041d0006a41186a2205200641186a2900003703002000200129030037030820002006290000370350200241186a2005290300370000200241106a2004290300370000200241086a200d29030037000020022000290350370000200941586a2109200a41016a210a200241206a2102200141286a2101200b417f6a220b0d000b0b02402008450d00200710020b200041c8006a200a360200200aad2203421b88a70d062003420586a72201417f4c0d072000280244210f024002402001450d002001100122010d01101c000b410121010b2000200a36020c2000200136020820004100360210200041086a4100200a108601200020002802102201200a6a360210200028020820014105746a200e200a4105742202101e1a200041306a41086a200028021036020020002000290308370330200041c0006a200041306a10a2012000280248210620002802402101200041086a41086a220942003703002000420037030841e4084107200041086a1003200041d0006a41086a200929030037030020002000290308370350200041d0006a411020012006100402402000280244450d00200110020b02402000280234450d00200028023010020b410021062000410036024820004201370340200041c0006a4100200241057510860120002802482101200028024021100240200a4105742209450d00200041086a41186a220a200e41186a290000370300200041086a41106a220b200e41106a290000370300200041086a41086a220d200e41086a2900003703002000200e290000370308200141016a2104200e41206a2102200941606a2109201020014105746a210102400340200041d0006a41186a2205200a290300370300200041d0006a41106a2207200b290300370300200041d0006a41086a2208200d29030037030020002000290308370350200141186a2005290300370000200141106a2007290300370000200141086a2008290300370000200120002903503700002009450d01200a200241186a290000370300200b200241106a290000370300200d200241086a29000037030020002002290000370308200441016a2104200241206a2102200941606a2109200141206a21010c000b0b200421010b200041c0006a41086a20013602002000280244210d02402001450d002001410574210241002106200041086a41086a210a201021010340200041086a2006103220002802082209200a2802002001412010040240200028020c450d00200910020b200141206a2101200641016a2106200241606a22020d000b0b200041086a10302000280208220120002802101031210b0240200028020c450d00200110020b0240200b20064d0d00200041106a210a200621010340200041086a103020002802082202200a280200103121090240200028020c450d00200210020b200141016a21020240200920014d0d00200041086a2001103220002802082201200a2802001005200028020c450d00200110020b20022101200b2002470d000b0b200041086a103020002802102102200028020821012000200636025020012002200041d0006a410410040240200028020c450d00200110020b0240200d450d00201010020b0240200f450d00200e10020b200041f0006a24000f0b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41f4214122102d000b41f4214122102d000b1066000b1067000b41f4214122102d000b41c1214133102d000bba0103027f017e017f024002400240200041046a280200220320016b20024f0d00200120026a220220014922010d01200341017422044100200220011b2201200420014b1b2204ad42287e2205a722014100480d012005422088a74100470d01024002402003450d0020002802002106200110012202450d04200220062001200341286c2203200320014b1b101e1a200610020c010b200110012202450d030b20002002360200200041046a20043602000b0f0b1041000b101c000bf40403067f017e027f230041306b22012400200041086a28020021022001410036022820014201370320200141206a4100410410272001280220200128022822036a20023600002001200341046a360228200141086a220420012802283602002001200129032037030002400240024002402002450d0020002802002200200241286c6a21050340200141106a41086a2203410036020020014201370310200141106a41004120102720032003280200220241206a2206360200200220012802106a220241186a200041186a290000370000200241106a200041106a290000370000200241086a200041086a29000037000020022000290000370000200041206a2903002107200141106a20064108102720032003280200220641086a22023602002006200128021022086a20073700002002417f4c0d03024002402002450d002002100122030d010c060b410121030b200141206a41086a220641003602002001200236022420012003360220200141206a41002002102720062006280200220920026a22033602002009200128022022066a20082002101e1a2001280224210202402001280214450d00200810020b200120042802002003102720012802002209200428020022086a20062003101e1a2004200820036a220336020002402002450d00200610020b200041286a22002005470d000c020b0b20012802082103200128020021090b20012802042102200141206a41086a220042003703002001420037032041c7114107200141206a1003200141106a41086a200029030037030020012001290320370310200141106a411020092003100402402002450d00200910020b200141306a24000f0b1019000b101c000be60101037f0240024002402000280200220128020022024103460d0020020d0220012802042202450d0220024101470d012001410c6a280200450d02200141086a2802001002200028020010020f0b20012d00044101470d01200141086a104b200028020010020f0b0240200141106a2802002203450d00200141086a2802002102200341186c210303400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200341686a22030d000b0b2001410c6a280200450d00200141086a28020010020b200028020010020bd60403047f017e087f230041c0006b2203240020024103742104410021050240024002400240024002402002450d0020044103752206ad4202862207a722084100480d042007422088a74100470d04200810012209450d05200120046a220a2001460d010c020b4104210941002106200120046a220a2001470d010b4101210c410021040c010b20024103742108200a41786a210b410021022009210403402004200120026a41046a280200360200200441046a21042008200241086a2202470d000b200b20016b41037641016a21054101210c410021044100210803402001280200210d0240024002402004200822026b200141046a280200220b4f0d002002200b6a22082002490d052004410174220e20082008200e491b220e4100480d052004450d01200e1001220f450d06200f200c200e20042004200e4b1b101e210f200c1002200e2104200f210c0c020b2002200b6a21080c010b200e2104200e1001220c450d040b200c20026a200d200b101e1a200141086a2201200a470d000b0b200341206a41186a22014200370300200341206a41106a22024200370300200341206a41086a2208420037030020034200370320200c20092005200341206a1007200341186a2001290300370300200341106a2002290300370300200341086a20082903003703002003200329032037030002402004450d00200c10020b02402006450d00200910020b20002003290300370000200041186a200341186a290300370000200041106a200341106a290300370000200041086a200341086a290300370000200341c0006a24000f0b1041000b101c000b14002006200710082008ad10092009ad100900000b0b0041e70a4122100800000b7901047f0240024002400240200041046a2802002201450d002001418080808004710d03200028020021022001410174220310012204450d022004200220032001200120034b1b101e1a200210020c010b410410012204450d01410421030b20002004360200200041046a20033602000f0b101c000b1050000b05001041000ba60101047f200141086a28020021024104210302400240410410012204450d002004200236000020012802002105024002402002450d00200241046a22032002490d0320034108200341084b1b22034100480d03200310012201450d02200120042003410420034104491b101e1a200410020c010b200421010b200141046a20052002101e1a20002003360204200020013602002000200241046a3602080f0b101c000b1041000b0600200010010b0600200010020b2500200020002000200020002000200028020020002802042000280208200028020c104d000b080041a4321054000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b05001041000b830101057f410421010240024002400240200041046a2802002202450d00200241d0006c2201417f4c0d0320002802002103200110012204450d02200420032001200241286c2205200520014b1b101e1a20031002200241017421010c010b41a00110012204450d010b20002004360200200041046a20013602000f0b101c000b1069000b05001041000b850101057f410421010240024002400240200041046a2802002202450d0020024180808010710d03200028020021012002410674220310012204450d0220042001200320024105742205200520034b1b101e1a20011002200241017421010c010b41800110012204450d010b20002004360200200041046a20013602000f0b101c000b106b000b05001041000b840101057f410421010240024002400240200041046a2802002202450d0020024180066c2201417f4c0d0320002802002103200110012204450d0220042003200120024180036c2205200520014b1b101e1a20031002200241017421010c010b41800c10012204450d010b20002004360200200041046a20013602000f0b101c000b106d000b05001041000b05001041000b830101057f410421010240024002400240200041046a2802002202450d00200241d0006c2201417f4c0d0320002802002103200110012204450d02200420032001200241286c2205200520014b1b101e1a20031002200241017421010c010b41a00110012204450d010b20002004360200200041046a20013602000f0b101c000b1070000b05001041000b850101057f410421010240024002400240200041046a2802002202450d00200241808080c000710d03200028020021012002410474220310012204450d0220042001200320024103742205200520034b1b101e1a20011002200241017421010c010b412010012204450d010b20002004360200200041046a20013602000f0b101c000b1072000b05001041000b05001041000b840101057f410421010240024002400240200041046a2802002202450d00200241b0016c2201417f4c0d0320002802002103200110012204450d02200420032001200241d8006c2205200520014b1b101e1a20031002200241017421010c010b41e00210012204450d010b20002004360200200041046a20013602000f0b101c000b1075000b05001041000b820101057f410421010240024002400240200041046a2802002202450d00200241306c2201417f4c0d0320002802002103200110012204450d02200420032001200241186c2205200520014b1b101e1a20031002200241017421010c010b41e00010012204450d010b20002004360200200041046a20013602000f0b101c000b1077000b05001041000b830101057f410421010240024002400240200041046a2802002202450d00200241d0006c2201417f4c0d0320002802002103200110012204450d02200420032001200241286c2205200520014b1b101e1a20031002200241017421010c010b41a00110012204450d010b20002004360200200041046a20013602000f0b101c000b1079000b05001041000b850101057f410421010240024002400240200041046a2802002202450d00200241808080c000710d03200028020021012002410474220310012204450d0220042001200320024103742205200520034b1b101e1a20011002200241017421010c010b412010012204450d010b20002004360200200041046a20013602000f0b101c000b107b000b05001041000b850101057f0240024002400240200041046a2802002201450d0020014180808010710d03200028020021022001410674220310012204450d0220042002200320014105742205200520034b1b101e1a20021002200141017421010c010b41800110012204450d01410421010b20002004360200200041046a20013602000f0b101c000b107d000b05001041000b7901047f0240024002400240200041046a2802002201450d002001418080808004710d03200028020021022001410174220310012204450d022004200220032001200120034b1b101e1a200210020c010b410410012204450d01410421030b20002004360200200041046a20033602000f0b101c000b107f000b05001041000b860101057f410421010240024002400240200041046a2802002202450d0020024180808020710d03200028020021012002410574220310012204450d0220042001200320024104742205200520034b1b101e1a20011002200241017421010c010b41c00010012204450d010b20002004360200200041046a20013602000f0b101c000b108101000b05001041000bba0103027f017e017f024002400240200041046a280200220320016b20024f0d00200120026a220220014922010d01200341017422044100200220011b2201200420014b1b2204ad42287e2205a722014100480d012005422088a74100470d01024002402003450d0020002802002106200110012202450d04200220062001200341286c2203200320014b1b101e1a200610020c010b200110012202450d030b20002002360200200041046a20043602000b0f0b1041000b101c000bba0103027f017e017f024002400240200041046a280200220320016b20024f0d00200120026a220220014922010d01200341017422044100200220011b2201200420014b1b2204ad42187e2205a722014100480d012005422088a74100470d01024002402003450d0020002802002106200110012202450d04200220062001200341186c2203200320014b1b101e1a200610020c010b200110012202450d030b20002002360200200041046a20043602000b0f0b1041000b101c000ba20103037f017e017f024002400240200041046a280200220220014f0d00200241017422032001200320014b1b2204ad420c7e2205a722014100480d012005422088a74100470d01024002402002450d0020002802002106200110012203450d042003200620012002410c6c2202200220014b1b101e1a200610020c010b200110012203450d030b20002003360200200041046a20043602000b0f0b1041000b101c000ba20103037f017e017f024002400240200041046a280200220220014f0d00200241017422032001200320014b1b2204ad42287e2205a722014100480d012005422088a74100470d01024002402002450d0020002802002106200110012203450d04200320062001200241286c2202200220014b1b101e1a200610020c010b200110012203450d030b20002003360200200041046a20043602000b0f0b1041000b101c000bba0103027f017e017f024002400240200041046a280200220320016b20024f0d00200120026a220220014922010d01200341017422044100200220011b2201200420014b1b2204ad4205862205a722014100480d012005422088a74100470d01024002402003450d0020002802002106200110012202450d0420022006200120034105742203200320014b1b101e1a200610020c010b200110012202450d030b20002002360200200041046a20043602000b0f0b1041000b101c000b0e0002402001450d00200010020b0bc00d010f7f230041e0066b220424000240200128020422052f01be032206410a4b0d00200441a8036a41206a2207200341206a290300370300200441a8036a41186a2208200341186a290300370300200441a8036a41106a2209200341106a290300370300200441a8036a41086a220a200341086a290300370300200420032903003703a8032005200128020c220b4105746a220341e0036a200341c0036a220c2006200b6b41057410391a200341d8036a200241186a290000370000200341d0036a200241106a290000370000200341c8036a200241086a290000370000200c20022900003700002005200b41286c6a220341286a2003200541be036a22052f0100200b6b41286c10391a200341206a2007290300370300200341186a2008290300370300200341106a2009290300370300200341086a200a290300370300200320042903a803370300200520052f010041016a3b0100200441b3036a200141086a280000360000200041003a000020002003360260200041106a200128020c360000200420012900003700ab03200020042900a803370001200041086a200441af036a290000370000200441e0066a24000f0b2001280208210d2001280200210e024041a0061001220b450d00200b200441a8036a41b803101e220b41003b01be03200b41003602b803200b41c0036a200441c8006a41e002101e210f200441286a41186a220c20054198056a290200370300200441286a41106a221020054190056a290200370300200441286a41086a221120054188056a290200370300200441a8036a41086a2206200541f8016a290300370300200441a8036a41106a220720054180026a290300370300200441a8036a41186a220820054188026a290300370300200441a8036a41206a220920054190026a290300370300200420054180056a290200370328200420052903f0013703a803200f200541a0056a200541be036a220a2f010041796a2212410574101e210f200b20054198026a201241286c101e210b200a41063b0100200b20123b01be03200441186a200c290300370300200441106a2010290300370300200441086a201129030037030020042004290328370300200441c8006a41206a2009290300370300200441c8006a41186a2008290300370300200441c8006a41106a2007290300370300200441c8006a41086a2006290300370300200420042903a803370348200441003602242004200b36022002400240200128020c220141064b0d002009200341206a2903003703002008200341186a2903003703002007200341106a2903003703002006200341086a290300370300200420032903003703a803200520014105746a220341e0036a200341c0036a220b200a2f010020016b41057410391a200341d8036a200241186a290000370000200341d0036a200241106a290000370000200341c8036a200241086a290000370000200b20022900003700002005200141286c6a220341286a2003200a2f010020016b41286c10391a200341206a2009290300370300200341186a2008290300370300200341106a2007290300370300200341086a2006290300370300200320042903a803370300200a200a2f010041016a3b01000c010b200c200241186a2900003703002010200241106a2900003703002011200241086a290000370300200420022900003703282009200341206a2903003703002008200341186a2903003703002007200341106a2903003703002006200341086a290300370300200420032903003703a803200f20014105746a41c07e6a200f200141796a22024105746a2203200b2f01be0320026b41057410391a200341186a200c290300370000200341106a2010290300370000200341086a201129030037000020032004290328370000200b200141286c6a220141907e6a200141e87d6a2203200b2f01be0320026b41286c10391a200141887e6a2009290300370300200141807e6a2008290300370300200141f87d6a2007290300370300200141f07d6a2006290300370300200320042903a803370300200b200b2f01be0341016a3b01be030b200041013a000020002004290300370001200041246a200e360000200041286a20053600002000412c6a200d360000200041306a2004290320370300200041386a2004290348370300200041096a200441086a290300370000200041116a200441106a290300370000200041196a200441186a290300370000200041d0006a200441c8006a41186a290300370300200041c8006a200441c8006a41106a290300370300200041c0006a200441c8006a41086a290300370300200041d8006a200441e8006a29030037030020002003360260200441e0066a24000f0b101c000ba108010a7f230041c0026b220424000240200128020422052f018e022206410a4b0d00200441286a41086a2207200241086a28020036020020042002290200370328200441386a41086a2208200341086a280200360200200420032902003703382005200128020c2202410c6c2203410c6a22096a200520036a220a200620026b410c6c10391a200a41086a2007280200360200200a200429032837020020054184016a220620096a200620036a22032005418e026a22052f010020026b410c6c10391a200341086a200828020036020020032004290338370200200520052f010041016a3b0100200128020c210520004100360200200041106a2005360200200020062005410c6c6a360230200020012902003702042000410c6a200141086a280200360200200441c0026a24000f0b2001280208210b2001280200210c024041900210012206450d002006200441386a418802101e220641003b018e022006410036028802200441386a41086a220a200541d0006a280200360200200441286a41086a2207200541d4016a280200360200200420052902483703382004200541cc016a2902003703282006200541d4006a2005418e026a22082f010041796a2209410c6c220d101e22064184016a200541d8016a200d101e210d200841063b0100200620093b018e02200441086a200a28020036020020042004290338370300200441106a41086a200728020036020020042004290328370310200441003602242004200636022002400240200128020c220941064b0d002007200241086a28020036020020042002290200370328200a200341086a2802003602002004200329020037033820052009410c6c2201410c6a22036a200520016a220220082f010020096b410c6c10391a200241086a20072802003602002002200429032837020020054184016a220220036a200220016a220120082f010020096b410c6c10391a200141086a200a28020036020020012004290338370200200820082f010041016a3b01000c010b2007200241086a28020036020020042002290200370328200a200341086a2802003602002004200329020037033820062009410c6c220141b87f6a22026a2006200141ac7f6a22036a220120062f018e02200941796a22086b410c6c10391a200141086a200728020036020020012004290328370200200d20026a200d20036a220120062f018e0220086b410c6c10391a200141086a200a28020036020020012004290338370200200620062f018e0241016a3b018e020b200041013602002000200c36020420002001360230200041086a20053602002000410c6a200b360200200041106a20042903003702002000411c6a2004290310370200200041286a2004290320370200200041186a200441086a280200360200200041246a200441106a41086a280200360200200441c0026a24000f0b101c000bf307010d7f23004180036b220624000240200128020422072f018e02410a4b0d00200641c8006a41086a200241086a28020036020020062002290200370348200641f8006a41086a200341086a280200360200200620032902003703782001200641c8006a200641f8006a2004108b0120004100360200200020012902003702042000410c6a200141086a29020037020020064180036a24000f0b2001280208210820012802002109024041c0021001220a450d004100210b200a200641f8006a418802101e220a41003b018e02200a410036028802200a200629024837029002200a4198026a200641c8006a41086a220c290200370200200a41a0026a200641d8006a290200370200200a41a8026a200641e0006a290200370200200a41b0026a200641e8006a290200370200200a41b8026a200641f0006a290200370200200c200741d0006a28020036020020062007290248370348200641f8006a41086a220d200741d4016a2802003602002006200741cc016a290200370378200a200741d4006a2007418e026a220e2f0100220f41796a2210410c6c2211101e22124184016a200741d8016a2011101e1a20124190026a220a200741ac026a200f417a6a220f410274101e1a200e41063b0100201220103b018e020240200f450d000340200a280200220e200b3b018c02200e201236028802200a41046a210a200b41016a220b200f490d000b0b200641386a41086a220b200c280200360200200641286a41086a220a200d2802003602002006200629034837033820062006290378370328200641086a200b28020036020020062006290338370300200641106a41086a200a28020036020020062006290328370310200620093602242006201236022002400240200128020c220b41064b0d002006200736027c2006200936027820062008360280012006200b36028401200641386a41086a200241086a28020036020020062002290200370338200641c8006a41086a200341086a28020036020020062003290200370348200641f8006a200641386a200641c8006a2004108b010c010b2006201236027c200620093602782006200b41796a360284012006200641206a36028001200641386a41086a200241086a28020036020020062002290200370338200641c8006a41086a200341086a28020036020020062003290200370348200641f8006a200641386a200641c8006a2004108b010b2000200936020420004101360200200041086a20073602002000410c6a2008360200200041106a20062903003702002000411c6a2006290310370200200041286a2006290320370200200041186a200641086a280200360200200041246a200641106a41086a28020036020020064180036a24000f0b101c000b890301077f230041206b22042400200041046a22052802002106200028020c2107200441086a2208200141086a28020036020020042001290200370300200441106a41086a2209200241086a2802003602002004200229020037031020062007410c6c2202410c6a220a6a200620026a220120062f018e0220076b410c6c10391a200141086a20082802003602002001200429030037020020064184016a2201200a6a200120026a220220062f018e0220076b410c6c10391a200241086a200928020036020020022004290310370200200620062f018e0241016a3b018e0220064190026a2206200028020c22074102746a41086a2006200741016a22074102746a220620052802002f018e0220076b41027410391a200620033602000240200028020c220041016a220620052802002f018e0222034b0d0020004102744194026a21000340200641016a22072006490d012005280200220220006a2802002201200236028802200120063b018c02200041046a210020072106200720034d0d000b0b200441206a24000bd40c02117f017e230041c0076b220624000240200128020422072f01be03410a4b0d00200641f8006a41186a200241186a290000370300200641f8006a41106a200241106a290000370300200641f8006a41086a200241086a2900003703002006200229000037037820064188046a41206a200341206a29030037030020064188046a41186a200341186a29030037030020064188046a41106a200341106a29030037030020064188046a41086a200341086a29030037030020062003290300370388042001200641f8006a20064188046a2004108d01200041003a0000200041046a20012902003702002000410c6a200141086a290200370200200641c0076a24000f0b2001280208210820012802002109024041d0061001220a450d004100210b200a20064188046a41b803101e220a41003b01be03200a41003602b803200a41c0036a200641f8006a419003101e210c200641286a41186a220d20074198056a290000370300200641286a41106a220e20074190056a290000370300200641286a41086a220f20074188056a290000370300200620074180056a29000037032820064188046a41206a221020074190026a29030037030020064188046a41186a221120074188026a29030037030020064188046a41106a221220074180026a29030037030020064188046a41086a2213200741f8016a290300370300200620072903f00137038804200c200741a0056a200741be036a22142f0100221541796a2216410574101e1a200a20074198026a201641286c101e220c41a0066a220a200741bc066a2015417a6a2215410274101e1a201441063b0100200c20163b01be0302402015450d000340200a2802002216200b3b01bc032016200c3602b803200a41046a210a200b41016a220b2015490d000b0b200641f8006a41206a220b2010290300370300200641f8006a41186a220a2011290300370300200641f8006a41106a22162012290300370300200641f8006a41086a22152013290300370300200641d8006a41086a2210200f290300370300200641d8006a41106a2211200e290300370300200641d8006a41186a2212200d290300370300200620062903880437037820062006290328370358200641086a41186a2012290300370300200641086a41106a2011290300370300200641086a41086a201029030037030020062006290358370308200641286a41206a200b290300370300200d200a290300370300200e2016290300370300200f201529030037030020062006290378370328200620093602542006200c36025002400240200128020c220b41064b0d002006200736025c20062009360258200620083602602006200b360264200641f8006a41186a200241186a290000370300200641f8006a41106a200241106a290000370300200641f8006a41086a200241086a2900003703002006200229000037037820064188046a41206a200341206a29030037030020064188046a41186a200341186a29030037030020064188046a41106a200341106a29030037030020064188046a41086a200341086a2903003703002006200329030037038804200641d8006a200641f8006a20064188046a2004108d010c010b2006200c36025c200620093602582006200b41796a3602642006200641d0006a360260200641f8006a41186a200241186a290000370300200641f8006a41106a200241106a290000370300200641f8006a41086a200241086a2900003703002006200229000037037820064188046a41206a200341206a29030037030020064188046a41186a200341186a29030037030020064188046a41106a200341106a29030037030020064188046a41086a200341086a2903003703002006200329030037038804200641d8006a200641f8006a20064188046a2004108d010b20002006290308370001200041246a2009360200200041286a20073602002000412c6a2008360200200041386a2006290328370300200041096a200641086a41086a290300370000200041116a200641086a41106a290300370000200041196a200641086a41186a290300370000200041c0006a200641286a41086a290300370300200041c8006a200641286a41106a290300370300200041d0006a200641286a41186a290300370300200041d8006a200641c8006a29030037030020062903502117200041013a0000200041306a2017370200200641c0076a24000f0b101c000bb804010b7f230041d0006b22042400200041046a22052802002106200028020c2107200441086a41186a2208200141186a290000370300200441086a41106a2209200141106a290000370300200441086a41086a220a200141086a29000037030020042001290000370308200441286a41206a2201200241206a290300370300200441286a41186a220b200241186a290300370300200441286a41106a220c200241106a290300370300200441286a41086a220d200241086a29030037030020042002290300370328200620074105746a220241e0036a200241c0036a220e20062f01be0320076b41057410391a200241d8036a2008290300370000200241d0036a2009290300370000200241c8036a200a290300370000200e20042903083700002006200741286c6a220241286a200220062f01be0320076b41286c10391a200241206a2001290300370300200241186a200b290300370300200241106a200c290300370300200241086a200d29030037030020022004290328370300200620062f01be0341016a3b01be03200641a0066a2206200028020c22024102746a41086a2006200241016a22024102746a220620052802002f01be0320026b41027410391a200620033602000240200028020c220241016a220620052802002f01be0322034b0d00200241027441a4066a21020340200641016a22012006490d012005280200220020026a280200220720003602b803200720063b01bc03200241046a210220012106200120034d0d000b0b200441d0006a24000b8614010e7f230041d0006b220424004100210502404101417f100d2206417f460d002004410036020820044204370300200441386a41ae0d4103102a200441106a41b10d410f102a200441cc006a2207200441106a41086a220528020036020020042004290310370244200441106a41106a2208200441386a41106a22092903003703002005200441386a41086a220a290300370300200420042903383703102004106a2004280204210b2004280200220c2004280208220d4105746a220e2004290310370200200e4100360218200e41086a2005290300370200200e41106a2008290300370200200e411c6a41013602002004200d41016a220d360208200441386a41ae0d4103102a200441106a41c00d410f102a2007200528020036020020042004290310370244200820092903003703002005200a290300370300200420042903383703100240200d200b470d002004106a200441086a280200210d2004280200210c2004280204210b0b200c200d4105746a220e2004290310370200200e4100360218200e41106a2008290300370200200e41086a2005290300370200200e411c6a4102360200200441086a200d41016a220e360200200441386a41ae0d4103102a200441106a41cf0d410c102a2007200528020036020020042004290310370244200820092903003703002005200a290300370300200420042903383703100240200e200b470d002004106a200441086a280200210e2004280204210b2004280200210c0b200c200e4105746a2208200429031037020020084100360218200841106a200441106a41106a220d290300370200200841086a200441106a41086a22052903003702002008411c6a4103360200200441086a2207200e41016a220e360200200441386a41ae0d4103102a200441106a41db0d410a102a200441cc006a2209200528020036020020042004290310370244200d200441386a41106a220a2903003703002005200441386a41086a220f290300370300200420042903383703100240200e200b470d002004106a2007280200210e2004280200210c2004280204210b0b200c200e4105746a2208200429031037020020084100360218200841106a200d290300370200200841086a20052903003702002008411c6a41043602002007200e41016a2208360200200441386a41ae0d4103102a200441106a41e50d4106102a2009200528020036020020042004290310370244200d200a2903003703002005200f2903003703002004200429033837031002402008200b470d002004106a200441086a28020021082004280200210c0b200c20084105746a2205200429031037020020054101360218200541106a200441106a41106a220b290300370200200541086a200441106a41086a2903003702002005411c6a2006360200200441086a200841016a2205360200200b200241086a290000370300200441106a41186a200241106a290000370300200441306a200241186a2900003703002004200336021020042006360214200420022900003703184104210702400240410410012210450d00201020053600000240024002402005450d00200c20054105746a2111200441c0006a210341042107410421080340200441386a200c105120042802382105410121064100210b024020032802002202450d0020024100480d042002210b200210012206450d050b200620052002101e210a0240200428023c450d00200510020b200441386a200c410c6a220f105120042802382109024002400240200b20026b2003280200220d490d002002200d6a2105200b2106200a220e20026a2009200d101e1a200428023c0d010c020b2002200d6a22052002490d05200b4101742206200520052006491b22064100480d0520061001210e0240200b450d00200e450d07200e200a2006200b200b20064b1b101e210b200a1002200b20026a2009200d101e1a200428023c0d010c020b200e450d06200e20026a2009200d101e1a200428023c450d010b200910020b2003410036020020044201370338200c41186a2802002102200441386a104f2004280238220d2003280200220b6a21090240024002400240024002400240024020024101470d00200941023a00002003200b41016a2202360200200c411c6a280200210c200428023c220920026b41034b0d01200241046a220b2002490d0b2009410174220a200b200b200a491b220a4100480d0b200a1001210b2009450d02200b450d0c200b200d200a20092009200a4b1b101e1a200d10020c030b200941013a00002003200b41016a2202360200200c411c6a280200210c200428023c220920026b41034b0d00200241046a220b2002490d0a2009410174220a200b200b200a491b220a4100480d0a200a1001210b2009450d03200b450d0b200b200d200a20092009200a4b1b101e1a200d10020c040b200d210b0c050b200b450d090b2004200a36023c0c020b200b450d070b2004200a36023c0b2004200b3602380b200b20026a200c3600002003200241046a220c360200200428023c210a0240024002400240200620056b200c4f0d002005200c6a22022005490d072006410174220d20022002200d491b22094100480d0720091001210d2006450d01200d450d08200d200e20092006200620094b1b101e2106200e1002200620056a200b200c101e1a200a0d020c030b2005200c6a210220062109200e220d20056a200b200c101e1a200a0d010c020b200d450d06200d20056a200b200c101e1a200a450d010b200b10020b0240024002400240200720086b20024f0d00200820026a22052008490d0720074101742206200520052006491b22064100480d072007450d0120061001220b450d08200b201020062007200720064b1b101e210b2010100220062107200b221020086a200d2002101e1a20090d020c030b200820026a2105201020086a200d2002101e1a20090d010c020b20062107200610012210450d06201020086a200d2002101e1a2009450d010b200d10020b20052108200f41146a220c2011470d000c020b0b410421050b41052000200120102005200441106a100e210202402007450d00201010020b02402002417f460d00410121050240200241eb0d4104200441106a100f2202450d002002417d470d04410021050b200428020021030240200441086a2802002202450d00200241057421062003210203400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241206a2102200641606a22060d000b0b2004280204450d0420031002200441d0006a240020050f0b200428020021060240200441086a2802002202450d00200241057421052006210203400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241206a2102200541606a22050d000b0b02402004280204450d00200610020b200441d0006a240041000f0b1041000b101c000b41fc3a103b000b200441d0006a240020050bbe0701047f23004190016b220424000240024002400240024002400240024002402003450d0020022802000d0120034101460d0220022802100d0320034103490d0420022802200d0520022802042103200241146a2802002105200241246a2802002106200441186a4200370300200441106a4200370300200441086a42003703002004420037030002400240024002402001280204220720032004412010102202417e460d0020020d0a200441206a41186a200141206a290000370300200441206a41106a200141186a290000370300200441206a41086a200141106a290000370300200420012900083703202005450d01200441c0006a41186a4200370300200441c0006a41106a4200370300200441c0006a41086a42003703002004420037034020072006200441c0006a412010102202417e460d0320020d0c20012802002101412010012202450d0b2004200236028001200442203702840120044180016a41004120102720042802800120042802880122036a22022004290300370000200441e0006a41086a200341206a2203360200200241086a200441086a290300370000200241106a200441106a290300370000200241186a200441186a29030037000020042004290380013703602004200336028801412010012202450d0b2004200236028001200442203702840120044180016a41004120102720042802800120042802880122036a22022004290340370000200441f0006a41086a200341206a2203360200200241086a200441c0006a41086a290300370000200241106a200441c0006a41106a290300370000200241186a200441c0006a41186a290300370000200420042903800137037020042003360288012001200441206a200441e0006a200441f0006a1094010c020b2000410536020020044190016a24000f0b20012802002101412010012202450d092004200236024020044220370244200441c0006a4100412010272004280240200428024822036a2202200429030037000020044180016a41086a200341206a2203360200200241086a200441086a290300370000200241106a200441106a290300370000200241186a200441186a290300370000200420042903403703800120042003360248200441003602402001200441206a20044180016a200441c0006a1094010b2000410436020020044190016a24000f0b2000410536020020044190016a24000f0b41bc3441004100103c000b41ec3f103b000b41cc3441014101103c000b41ec3f103b000b41dc3441022003103c000b41ec3f103b000b41cc31103b000b101c000b41cc31103b000bc50301027f230041d0006b2204240002400240024002400240024002402003450d0020022802000d0120034101460d0220022802100d0320022802042103200241146a2802002102200441186a4200370300200441106a4200370300200441086a420037030020044200370300024002400240024002402001280204220520032004412010102203417e460d0020030d09200441206a41186a200141206a290000370300200441206a41106a200141186a290000370300200441206a41086a200141106a29000037030020042001290008370320200441c0006a2001280200200441206a2004412010950120042802402201450d0120042802442103200520022001200441c0006a41086a28020010112202417e460d0320020d0a2003450d02200110020c020b20004105360200200441d0006a24000f0b2005200241bd0e412010112202417e460d0220020d090b20004104360200200441d0006a24000f0b2000410536020002402003450d00200110020b200441d0006a24000f0b20004105360200200441d0006a24000f0b419c3441004100103c000b41ec3f103b000b41ac3441014101103c000b41ec3f103b000b41cc31103b000b41e431103b000b41e431103b000b861a05037f017e047f047e027f230041a0076b22042400024002400240024002400240024002400240024002400240024002402003450d0020022802000d0120034101460d0220022802100d0320034103490d0420022802200d0520022802042105200241146a2802002106200241246a3502002107410021022004410036020820044201370300024002402006450d0020044100200610272004280200200441086a220828020022096a210a024020064101460d00410021020340200a20026a41003a0000200241026a2103200241016a220b210220032006490d000b2009200b6a2109200a200b6a210a0b200a41003a00002008200941016a2202360200200428020021030c010b410121030b024002400240200128020420052003200210102206417e460d0020060d09200441e8036a2002412020024120491b22066a41004100412020066b2006411f4b1b10171a200441e8036a20032006101e1a2002411f4d0d0b200441106a41186a200441e8036a41186a290000370300200441106a41106a200441e8036a41106a290000370300200441106a41086a200441e8036a41086a290000370300200420042900e803370310200441306a41186a200141206a290000370300200441306a41106a200141186a290000370300200441306a41086a200141106a29000037030020042001290008370330200128020022022802002206417f460d0a2002200641016a360000200241046a220a200441306a1096012206450d012006280200450d01200641086a290300210c0c020b200041053602002004280204450d0f0c0e0b2002280210200441306a200241146a280200280214111400210c0b200220022802002206417f6a360000200c2007540d092006450d072002200636000002400240200a200441106a1096012206450d002006280200450d00200641086a290300210d0c010b2002280210200441106a200241146a280200280214111400210d0b20022002280200417f6a360000024002400240410810012206450d00200420063602e803200442083702ec03200441e8036a41004108102720042802e80320042802f00322066a42f3e885d3a3ec9bb73a3700002004200641086a3602f00320044188016a41086a20042802f003360200200420042903e80337038801412010012206450d00200420063602e803200442203702ec03200441e8036a41004120102720042802e803220a20042802f003220b6a22062004290330370000200641086a200441306a41086a290300370000200641106a200441306a41106a290300370000200641186a200441306a41186a2903003700002004200b41206a22063602f00320042802ec03210520044188016a20042802900120061027200428028801220b20042802900122096a200a2006101e1a2004200920066a22063602900102402005450d00200a10020b200428028c01210a4200210e200441e8036a41086a22054200370300200442003703e803200b2006200441e8036a100320044188016a41086a2005290300370300200420042903e80337038801024020044188016a411041d02d410041001000417f460d00200442003703e80320044188016a4110200441e8036a41084100100041016a41084d0d0220042903e803210e0b0240200a450d00200b10020b410810012206450d00200420063602e803200442083702ec03200441e8036a41004108102720042802e80320042802f00322066a42f3e885d3a3ec9bb73a3700002004200641086a3602f00320044188016a41086a20042802f003360200200420042903e80337038801412010012206450d00200420063602e803200442203702ec03200441e8036a41004120102720042802e803220a20042802f003220b6a22062004290310370000200641086a200441106a41086a290300370000200641106a200441106a41106a290300370000200641186a200441106a41186a2903003700002004200b41206a22063602f00320042802ec03210520044188016a20042802900120061027200428028801220b20042802900122096a200a2006101e1a2004200920066a22063602900102402005450d00200a10020b200428028c01210a4200210f200441e8036a41086a22054200370300200442003703e803200b2006200441e8036a100320044188016a41086a2005290300370300200420042903e80337038801024020044188016a411041d02d410041001000417f460d00200442003703e80320044188016a4110200441e8036a41084100100041016a41084d0d0320042903e803210f0b0240200a450d00200b10020b200e200f560d0d200d20077c220e200d580d0e41a00610012206450d002006200441e8036a41b803101e220641003b01be03200641003602b803200641c0036a20044188016a41e002101e1a200441d0006a41086a220a4200370300200441e4006a41c43d360200200420063602542004410036025020042002360260200441d0006a41047221020240200441306a200441106a41201006450d002004417f360250200441e8036a41186a2206200441306a41186a290300370300200441e8036a41106a2209200441306a41106a290300370300200441e8036a41086a200441306a41086a290300370300200420042903303703e803200420023602702004200a2802003602682004200428025436026c20044188016a200441e8006a200441e8036a1097014101210a20044188016a41106a280200210b20044188016a410c6a280200210820044188016a41086a2802002105200428028c01211002402004280288014101470d00200441e8006a41186a2006290300370300200441e8006a41106a2009290300370300200441e8006a41086a200441e8036a41086a290300370300200420042903e8033703684100210a0b41900210012206450d01200c20077d21072006200441e8036a418802101e220641003b018e02200641003602880202400240200a450d0020042006360288012004420037028c012005200b41286c6a2106200441e8036a20044188016a109801200441e8036a1099010c010b20044184046a200441f0006a2903003702002004418c046a200441f8006a29030037020020044194046a20044180016a290300370200200420053602ec03200420103602e803200420083602f0032004200b3602f4032004200441d0006a410c6a3602f803200420042903683702fc03200441a8016a420037030020044100360298012004420037038801200420063602a401200441e8036a20044188016a109a0121060b20064201370300200620073703082004417f360250200441e8036a41186a2206200441106a41186a290300370300200441e8036a41106a2209200441106a41106a290300370300200441e8036a41086a2208200441106a41086a290300370300200420042903103703e803200420023602702004200441d0006a41086a2802003602682004200428025436026c20044188016a200441e8006a200441e8036a1097014101210a20044188016a41106a280200210b20044188016a410c6a280200211020044188016a41086a2802002105200428028c01211102402004280288014101470d00200441e8006a41186a2006290300370300200441e8006a41106a2009290300370300200441e8006a41086a2008290300370300200420042903e8033703684100210a0b41900210012206450d012006200441e8036a418802101e220641003b018e02200641003602880202400240200a450d0020042006360288012004420037028c012005200b41286c6a2106200441e8036a20044188016a109801200441e8036a1099010c010b20044184046a200441f0006a2903003702002004418c046a200441f8006a29030037020020044194046a20044180016a290300370200200420053602ec03200420113602e803200420103602f0032004200b3602f4032004200441d0006a410c6a3602f803200420042903683702fc03200441a8016a420037030020044100360298012004420037038801200420063602a401200441e8036a20044188016a109a0121060b200642013703002006200e370308200441003602500b200441e8036a200441d0006a200441106a109b0102400240024020042802f0032206450d0020042802e803220a2006200441106a200441d0006a108e01450d010b200441d8006a290300210720042802542102024020042802ec03450d0020042802e80310020b2002450d0120012802002106200420073702ec03200420023602e8032006200441e8036a109c010c010b024020042802ec03450d00200a10020b20044188016a41086a200241086a2802003602002004200229020037038801200441e8036a20044188016a109d01200441e8036a109e010b2000410436020020042802040d0f0c100b101c000b41c1214133102d000b41c1214133102d000b41ec3341004100103c000b41ec3f103b000b41fc3341014101103c000b41ec3f103b000b418c3441022003103c000b41ec3f103b000b41cc31103b000b109f01000b41ec3f103b000b418c3c103b000b41a43c103b000b41bc3c103b000b200310020b200441a0076a24000b811a06047f017e047f017e037f057e230022042105200441c0086b4160712204240002400240024002400240024002400240024002400240024002400240024002400240024002402003450d0020022802000d0120034101460d0220022802100d0320034103490d0420022802200d0520022802042106200241146a2802002107200241246a3502002108410021022004410036020820044201370300024002402007450d0020044100200710272004280200200441086a2209280200220a6a210b024020074101460d00410021020340200b20026a41003a0000200241026a2103200241016a220c210220032007490d000b200a200c6a210a200b200c6a210b0b200b41003a00002009200a41016a2202360200200428020021030c010b410121030b024002400240200128020420062003200210102207417e460d0020070d09200441106a41186a200141206a290000370300200441106a41106a200141186a290000370300200441186a200141106a2900003703002004200129000837031020012802002207280200220b417f460d0a2007200b41016a360000200741046a200441106a109601220b450d01200b280200450d01200b41086a290300210d0c020b200041053602002004280204450d140c130b2007280210200441106a200741146a280200280214111400210d0b20072007280200417f6a360000200d2008540d08200441c8046a41186a220b4200370300200441c8046a41106a220c4200370300200441c8046a41086a22014200370300200442003703c80420032002200441c8046a1012200441e8016a41186a2206200b290300370300200441e8016a41106a220a200c290300370300200441e8016a41086a22092001290300370300200420042903c8043703e801200b2006290300370300200c200a29030037030020012009290300370300200420042903e8013703c80441201001220e450d0d2004200e3602e801200442203702ec01200441e8016a41004120102720042802e80120042802f001220f6a220e20042903c80437000020044180086a41086a2210200f41206a220f360200200e41086a2001290300370000200e41106a200c290300370000200e41186a200b290300370000200420042903e801370380082004200f3602f00120044180086a20102802004120102720102010280200220e41206a220f360200200e20042802800822106a220e2004290310370000200e41086a200441106a41086a290300370000200e41106a200441106a41106a290300370000200e41186a200441106a41186a290300370000200b4200370300200c420037030020014200370300200442003703c8042010200f200441c8046a10122006200b290300370300200a200c29030037030020092001290300370300200420042903c8043703e801200441306a41186a2006290300370300200441306a41106a200a290300370300200441306a41086a2009290300370300200420042903e8013703300240200428028408450d00201010020b200441306a200441106a41201006450d1041a0061001220b450d0d200b200441c8046a41b803101e220b41003b01be03200b41003602b803200b41c0036a200441e8016a41e002101e1a2004200b36025020044200370254200441306a200441106a41201006450d09200441a0016a41186a200441306a41186a290300370300200441a0016a41106a200441306a41106a290300370300200441a0016a41086a200441306a41086a290300370300200420042903303703a0012002417f4c0d0a024002402002450d0020021001220b0d010c0f0b4101210b0b200420023602cc042004200b3602c804200441003602d004200441c8046a410020021027200420042802d004220b20026a3602d004200b20042802c8046a20032002101e1a200441e8016a41086a220c20042802d004360200200420042903c8043703e80141900210012202450d0d200441d0006a41086a210b2002200441c8046a418802101e220241003b018e022002410036028802200420083703c801200442013703c001200420023602dc01200420042903e8013703d0012004200c2802003602d801200441c8046a41186a2202200441a0016a41186a290300370300200441c8046a41106a220c200441a0016a41106a290300370300200441c8046a41086a200441a0016a41086a290300370300200420042903a0013703c804200420042802543602b008200420042802503602b4082004200441d0006a3602b808200441e8016a200441b0086a200441c8046a109701200441a0086a41086a200441f4016a290200370300200420042902ec013703a008024020042802e8014101470d0020044180086a41186a2201200229030037030020044180086a41106a2202200c29030037030020044180086a41086a220c200441c8046a41086a2206290300370300200420042903c80437038008200441b0086a41086a200441a0086a41086a220a290300370300200420042903a0083703b0082006200a290300370300200441e4046a200c290300370200200441ec046a2002290300370200200441f4046a20012903003702002004200b3602d804200420042903a0083703c80420042004290380083702dc0420044188026a4200370300200441e8016a41186a20042903d801370300200420042903d0013703f801200420042903c8013703f001200420042903c0013703e801200441c8046a200441e8016a109a011a2004420237036041010d0d0c0c0b200441c8046a41086a200441a0086a41086a290300370300200420042903a0083703c80420042802cc0420042802d40441286c6a22022900102112200220042903d00137001020022900082113200220042903c80137000820022900002114200220042903c0013700002002290020211120024200370020200241186a22022900002115200220042903d8013700002004200b3602d8042004201237037020042013370368200420143703602004201537037820144202520d0b0c0c0b41bc3341004100103c000b41ec3f103b000b41cc3341014101103c000b41ec3f103b000b41dc3341022003103c000b41ec3f103b000b41cc31103b000b109f01000b41943d103b000b41ac3d103b000b1019000b024020042802702202450d002004280274450d00200210020b200420113702ec012004200428027c3602e801200441c8046a200441e8016a109801200441c8046a1099010b200441a0016a41186a220c200441106a41186a290300370300200441a0016a41106a2201200441106a41106a290300370300200441a0016a41086a2206200441106a41086a290300370300200420042903103703a00141900210012202450d002002200441c8046a418802101e220241003b018e0220024100360288022004200d20087d3703c801200442013703c001200441003602d001200420023602dc01200441c8046a41186a200c290300370300200441c8046a41106a2001290300370300200441c8046a41086a2006290300370300200420042903a0013703c804200420042802543602b008200420042802503602b4082004200441d0006a3602b808200441e8016a200441b0086a200441c8046a109701200441a0086a41086a200441f4016a290200370300200420042902ec013703a0080240024020042802e8014101470d0020044180086a41186a2202200441c8046a41186a29030037030020044180086a41106a220c200441c8046a41106a29030037030020044180086a41086a2201200441c8046a41086a2206290300370300200420042903c80437038008200441b0086a41086a200441a0086a41086a220a290300370300200420042903a0083703b0082006200a290300370300200441e4046a2001290300370200200441ec046a200c290300370200200441f4046a20022903003702002004200b3602d804200420042903a0083703c80420042004290380083702dc0420044188026a4200370300200441e8016a41186a20042903d801370300200420042903d0013703f801200420042903c8013703f001200420042903c0013703e801200441c8046a200441e8016a109a011a200442023703800141010d010c030b200441c8046a41086a200441a0086a41086a290300370300200420042903a0083703c80420042802cc0420042802d40441286c6a22022900102111200220042903d00137001020022900082114200220042903c8013700082002290000210d200220042903c0013700002002290020210820024200370020200241186a22022900002112200220042903d8013700002004200b3602d804200420113703900120042014370388012004200d370380012004201237039801200d4202520d020b20042802502202450d030c020b101c000b02402004280290012202450d00200428029401450d00200210020b200420083702ec012004200428029c013602e801200441c8046a200441e8016a109801200441c8046a10990120042802502202450d010b200420042902543702cc04200420023602c8042007200441c8046a109c010b200041043602002004280204450d010b200310020b200524000bd41003027f017e077f230041c0006b22042400024020010d0041d02d2100410021010b20044100360200024002400240024002400240200141034d0d002004200028000022053602002005ad2206421c88a70d012006420486a72207417f4c0d02024002402007450d002007100122080d010c070b410821080b20042005360204200420083602002004410036020802400240024002402005450d002001417c6a2101200041046a2107200441086a2109410021004100210a0340200441003a0030200441306a20072001410047220b101e1a2001450d0320042d0030417f6a220c41034b0d032001200b6b21012007200b6a210702400240024002400240024002400240200c0e0403010400030b20044200370330200441306a20072001410820014108491b220b101e1a200141074d0d0a2007200b6a2107200429033021064103210c0c010b20044200370330200441306a20072001410820014108491b220b101e1a200141074d0d092007200b6a2107200429033021064101210c0b200a41016a210a20002004280204470d040c030b20044100360230200441306a20072001410420014104491b220b101e1a200141034d0d072007200b6a21072004280230210d4100210c0c010b20044100360230200441306a20072001410420014104491b220b101e1a200141034d0d062007200b6a21072004280230210d4102210c0b200a41016a210a20002004280204470d010b200410800120092802002100200428020021080b2001200b6b2101200820004104746a220b200d360204200b200c360200200b41086a20063703002009200041016a2200360200200a2005490d000b20042802042107200428020022080d010c030b41002100410021072008450d020b20042002200820002003110700200441003602182004420137031020042802002101200441106a107e2004280210200428021822006a210a024020014105470d00200a41013a0000200441186a2201200041016a2200360200200441106a20004100102720012802002101200428021021000c070b200a41003a0000200441106a41086a200041016a22003602002004410036022820044201370320200441206a104f2004280220220b2004280228220a6a210c0240024020014104470d00200c41003a0000200441206a41086a200a41016a220a3602000c010b200c41013a0000200441206a41086a200a41016a36020020044100360238200442013703300240024002400240024002400240024002400240024002400240024002400240024002400240200141037122014101460d00024020014102460d0020014103470d02200441086a2903002106200441306a104f20042802302205200441306a41086a220b280200220c6a41043a0000200b200c41016a22013602002004280234220d20016b41074b0d03200141086a220a2001490d1a200d4101742209200a200a2009491b22094100480d1a20091001210a200d450d07200a450d1c200a20052009200d200d20094b1b101e1a200510020c080b20042802042102200441306a104f20042802302205200441386a220b280200220c6a41033a0000200b200c41016a22013602002004280234220d20016b41034b0d03200141046a220a2001490d19200d4101742209200a200a2009491b22094100480d1920091001210a200d450d09200a450d1b200a20052009200d200d20094b1b101e1a200510020c0a0b200441086a2903002106200441306a104f20042802302205200441306a41086a220b280200220c6a41023a0000200b200c41016a22013602002004280234220d20016b41074b0d03200141086a220a2001490d18200d4101742209200a200a2009491b22094100480d1820091001210a200d450d0b200a450d1a200a20052009200d200d20094b1b101e1a200510020c0c0b20042802042102200441306a104f20042802302205200441386a220b280200220c6a41013a0000200b200c41016a22013602002004280234220d20016b41034b0d03200141046a220a2001490d17200d4101742209200a200a2009491b22094100480d1720091001210a200d450d0d200a450d19200a20052009200d200d20094b1b101e1a200510020c0e0b2005210a0c050b2005210a0c070b2005210a0c090b2005210a0c0b0b200a450d140b200420093602342004200a3602300b200b200c41096a360200200a20016a20063700000c090b200a450d110b200420093602342004200a3602300b200b200c41056a360200200a20016a20023600000c060b200a450d0e0b200420093602342004200a3602300b200b200c41096a360200200a20016a20063700000c030b200a450d0b0b200420093602342004200a3602300b200b200c41056a360200200a20016a20023600000b200428023421092004280230210c02400240024002402004280224220d200441206a41086a28020022016b200441306a41086a280200220a4f0d002001200a6a220b2001490d0a200d4101742205200b200b2005491b22054100480d0a200d450d012004280220210220051001220b450d0c200b20022005200d200d20054b1b101e1a200210020c020b2004280220210b0c020b20051001220b450d0a0b200420053602242004200b3602200b200441286a220d2001200a6a360200200b20016a200c200a101e1a02402009450d00200c10020b200d280200210a2004280220210b0b2004280224210c200441106a2000200a1027200441186a22012001280200220d200a6a2201360200200d200428021022006a200b200a101e1a200c450d06200b10020c060b2004280204450d00200428020010020b41af1b41f000102d000b200420002001101e1a41af1b41f000102d000b105a000b105b000b1041000b2000ad4220862001ad84210602402007450d00200810020b200441c0006a240020060f0b101c000ba30501097f230041e0026b220424000240024020002802000d002000417f360000200441306a41186a2205200141186a290000370300200441306a41106a2206200141106a290000370300200441306a41086a2207200141086a290000370300200420012900003703302004200041046a3602182004200041086a28020036021020042000280204360214200441b8026a200441106a200441306a10970141012108200441b8026a41106a2802002109200441c4026a280200210a200441b8026a41086a280200210b20042802bc02210c024020042802b8024101470d00200441106a41186a2005290300370300200441106a41106a2006290300370300200441106a41086a200729030037030020042004290330370310410021080b41900210012201450d012001200441306a418802101e220141003b018e022001410036028802024002402008450d00200420013602b802200442003702bc02200b200941286c6a2101200441306a200441b8026a109801200441306a1099010c010b200441cc006a200441186a290300370200200441d4006a200441206a290300370200200441dc006a200441286a2903003702002004200b3602342004200c3602302004200a3602382004200936023c20042000410c6a36024020042004290310370244200441d8026a4200370300200441003602c802200442003703b802200420013602d402200441306a200441b8026a109a0121010b200441b8026a41086a200241086a280200360200200420022902003703b802200441306a41086a200341086a2802003602002004200329020037033020042001411c6a200441b8026a200441306a10d20102402004280200450d0020042802042201450d00200441086a280200450d00200110020b20004100360000200441e0026a24000f0b10c301000b101c000be60602097f017e230041206b22052400024002400240024020012802002206417f460d002001200641016a360000200141046a20021096012206450d02200628022021072006411c6a28020022082f018e022209450d01410f210a0c030b109f01000b4101210a0c010b4116210a0b034002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200a0e170a090c0d160e0f1314151012110708000102030406050b0b0b20082009410c6c6a210b41002109200821064110210a0c280b20032006280200200641086a280200220c2004200c2004491b1006220d450d174111210a0c270b200d411e76417f73410271417f6a220c450d254112210a0c260b200c4101470d194113210a0c250b200941016a21092006410c6a2206200b470d170c160b4100417f4101200c20044b1b200c2004461b220c0d214114210a0c230b200541013a000c20052d000c4101710d11410d210a0c220b2007450d1e410e210a0c210b2007417f6a2107200820094102746a4190026a28020022082f018e0222090d0e4101210a0c200b200541003a000c20052d000c410171450d140c150b2008418e026a2f010021090c0f0b20002001280210200220032004200141146a28020028020c1113000c190b20082009410c6c6a22064184016a2802002204450d134103210a0c1c0b2006418c016a2802002206417f4c0d134105210a0c1b0b2006450d134106210a0c1a0b2006100122090d13410a210a0c190b101c000b410021090c120b410121094107210a0c160b200520063602142005200936021020054100360218200541106a41002006102720052005280218220c20066a360218200c200528021022096a20042006101e1a2005290214210e4108210a0c150b2000200e370204200020093602004109210a0c140b20012001280200417f6a360000200541206a24000f0b1019000b410f210a0c110b4102210a0c100b4115210a0c0f0b4101210a0c0e0b4100210a0c0d0b4110210a0c0c0b4101210a0c0b0b410d210a0c0a0b4102210a0c090b410c210a0c080b4104210a0c070b410b210a0c060b4107210a0c050b4108210a0c040b4109210a0c030b4116210a0c020b4112210a0c010b4114210a0c000b0bbe0301087f230041106b220224002000280204210302400240200028020022042f01be0322050d00410a21060c010b410421060b037f024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020060e0c050a0800010203040709060b0b0b2003417f6a2103200420054102746a41a0066a28020022042f01be032205450d0b410421060c150b20054105742107200441c0036a210041002105410521060c140b20012000412010062208450d0b410621060c130b4100210920084100480d11410721060c120b200041206a2100200541016a2105200741606a22070d0c410021060c110b200441be036a2f01002105200241003a000c20022d000c410171450d090c0a0b41002109410821060c0f0b200220093a000c20022d000c4101710d0a410221060c0e0b20030d0b0c0a0b200241013a000c20022d000c410171450d03410121060c0c0b200241106a24002004200541286c6a0f0b200241106a240041000f0b410a21060c090b410221060c080b410921060c070b410221060c060b410121060c050b410521060c040b410121060c030b410b21060c020b410321060c010b410821060c000b0bad04010c7f230041106b220324002001280208210420012802002105200141086a2106200141046a210702400240200128020422082f01be0322090d00410a210a0c010b4104210a0b03400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200a0e0c050a0800010203040709060b0b0b20012005417f6a2205360200200620043602002007200820094102746a41a0066a280200220836020020082f01be032209450d0b4104210a0c150b2009410574210b200841c0036a210c410021094105210a0c140b2002200c41201006220d450d0b4106210a0c130b4100210e200d4100480d114107210a0c120b200c41206a210c200941016a2109200b41606a220b0d0c4100210a0c110b200841be036a2f01002109200341003a000c20032d000c410171450d090c0a0b4100210e4108210a0c0f0b2003200e3a000c20032d000c4101710d0a4102210a0c0e0b20050d0b0c0a0b200341013a000c20032d000c410171450d034101210a0c0c0b2000200536020420004100360200200041086a20083602002000410c6a2004360200200041106a2009360200200341106a24000f0b20004201370200200041086a20083602002000410c6a2004360200200041106a2009360200200341106a24000f0b410a210a0c090b4102210a0c080b4109210a0c070b4102210a0c060b4101210a0c050b4105210a0c040b4101210a0c030b410b210a0c020b4103210a0c010b4108210a0c000b0bb20301097f23002102200141046a280200210320012802082104200241306b220241186a2205200128020022063602002002411c6a2207410036020020022003360214200220034100472208360210024002402003450d002003417f6a2101200241106a41047221092006210a03402005200a28029002220a3602002007410036020020022001360214200220014100473602102001417f6a2201417f470d000c020b0b200241106a41047221090b200241086a200941086a28020036020020022009290200370300200241106a41086a220a20063602002002411c6a22054100360200200220033602142002200836021002402003450d002003417f6a21010340200a200620062f018e024102746a4190026a28020022063602002005410036020020022001360214200220014100473602102001417f6a2201417f470d000b0b200241106a41086a28020022012f018e0221062002411c6a280200210a200228021421052000410036020c20002005360210200041146a2001360200200041186a200a3602002000411c6a200636020020002004360220200041086a200241086a280200360200200020022903003702000bf00202067f027e230041206b22012400200141086a200010ca01024020012802082202450d00200141186a2103200141146a2104034020032802002105200428020021060240200128020c450d00200210020b02402006450d002005450d00200610020b200141086a200010ca01200128020822020d000b0b2000280208210320002802002102024002400240024020002802042206280288022205450d00200632018c0221072001200536020c2001200241016a2202360208200120074220862003ad842207370310200610022005450d020c010b2003ad210741002105200610024100450d010b024002402005280288022206450d00200532018c0221082001200636020c2001200241016a36020820012008422086200742ffffffff0f83843703102005100220060d010c020b41002106200510024100450d010b2006210503402006280288022206450d02200510022006210520060d000b0b200141206a24000f0b20051002200141206a24000bcc0b01117f230041c0076b2202240020002802102203200328020041016a360200200241d8006a41086a200041086a29020037030020022000290200370358200241206a41186a22032000412c6a290000370300200241206a41106a2204200041246a290000370300200241206a41086a22052000411c6a29000037030020022000290014370320200241f8006a41206a200141206a290300370300200241f8006a41186a200141186a290300370300200241f8006a41106a200141106a290300370300200241f8006a41086a200141086a2903003703002002200129030037037820024188046a200241d8006a200241206a200241f8006a108801024002400240024002400240024020022d008804450d00200241086a20024191046a290000370300200241106a20024199046a290000370300200241186a200241a1046a2900003703002005200241c8046a2903003703002004200241d0046a2903003703002003200241d8046a290300370300200241206a41206a200241e0046a29030037030020022002290089043703002002200241c0046a290300370320200241bc046a2802002106200241b8046a280200210420022802e804210720024188046a412c6a280200210320024188046a41246a2802002100200241b0046a28020022012802b8032205450d0120012f01bc0321082002200536027c2002200041016a2209360278200220033602800120022008360284014100450d020c030b20024188046a41106a280200210020024188046a41086a2802002101200241c0076a24002001200041286c6a0f0b2002200136027c2002200036027820022003360280012003210941010d010b200241c0046a210020024188046a4101722101200241d4006a210a200241bc046a210b200241b8046a210c200241b4046a210d200241b0046a210e200241ac046a210f0340200241c8006a41086a2003360200200a20083602002002200536024c20022009360248200241d8006a41186a200241186a2203290300370300200241d8006a41106a200241106a2205290300370300200241d8006a41086a200241086a220829030037030020022002290300370358200241f8006a41206a200241206a41206a2209290300370300200241f8006a41186a200241206a41186a2210290300370300200241f8006a41106a200241206a41106a2211290300370300200241f8006a41086a200241206a41086a22122903003703002002200229032037037820024188046a200241c8006a200241d8006a200241f8006a20042006108c0120022d008804450d0302402008200141086a2900003703002005200141106a2900003703002003200141186a2900003703002012200041086a2903003703002011200041106a2903003703002010200041186a2903003703002009200041206a2903003703002002200129000037030020022000290300370320200c2802002104200d2802002103200e28020022082802b8032205450d00200b2802002106200f28020041016a210920082f01bc0321080c010b0b41d00610012200450d030c010b2009210341d00610012200450d020b200020024188046a41b803101e220041003b01be03200041003602b803200041c0036a200241f8006a419003101e2101200020032802003602a006200320003602002003200328020441016a36020420002802a006220341003b01bc03200320003602b803200120002f01be0322034105746a22012002290300370000200141186a200241186a290300370000200141106a200241106a290300370000200141086a200241086a2903003700002000200341286c6a220141106a200241206a41106a290300370300200141086a200241206a41086a29030037030020012002290320370300200141206a200241206a41206a290300370300200141186a200241206a41186a290300370300200041a0066a200341016a22014102746a2004360200200020002f01be0341016a3b01be03200420013b01bc03200420003602b8030b200241c0076a240020070f0b101c000bf10101047f230041106b220324000240024020012802002204417f460d002001200441016a3600000240024002400240200141046a20021096012204450d0020042802102205450d0020042802182202417f4c0d052002450d012002100122040d02101c000b200020012802102002200141146a2802002802101106000c020b410121040b200320023602042003200436020020034100360208200341002002102720032003280208220420026a3602082004200328020022066a20052002101e1a20002003290204370204200020063602000b20012001280200417f6a360000200341106a24000f0b109f01000b1019000b890b07027f017e107f017e047f017e027f230041f0026b22022400024020002802000d002000417f36000020024180016a41086a2203200141086a2802003602002002200129020037038001200220024180016a109d01200241286a41206a200241206a280200360200200241286a41186a200241186a290300370300200241286a41106a200241106a290300370300200241286a41086a200241086a2903003703002002200229030037032820024180016a200241286a10c801024020022903a00122044202510d002000410c6a2105200041046a2106200241f8016a411c6a210720024180016a41146a2108200241bc016a2109200241a0026a410c6a210a20024180016a41286a210b200241b0016a210c200241b4016a210d200241b8016a210e20024180016a41206a210f0340200241e0006a41186a220120024180016a41186a2210290300370300200241e0006a41106a221120024180016a41106a2212290300370300200241e0006a41086a22132003290300370300200241d0006a41086a2214200941086a280200360200200220022903800137036020022009290200370350200b2903002115200c2802002116200d2802002117200e2802002118200241c8016a41086a22192014280200360200200220022903503703c8012010200129030037030020122011290300370300200320132903003703002002200229036037038001200241b8026a41086a220120063602002002200041086a2802003602b802200220062802003602bc02200241f8016a200241b8026a20024180016a1097010240024020022802f8014101470d00200241d8016a41086a22012003290300370300200241d8016a41106a22112012290300370300200241d8016a41186a2213201029030037030020022002290380013703d80120022902fc01211a2003200241f8016a410c6a29020037030020122005360200200820022903d801370200200841086a2001290300370200200841106a2011290300370200200841186a20132903003702002002201a37038001200241f8016a41086a2015370300200241f8016a41106a2016360200200241f8016a41146a2017360200200241f8016a41186a2018360200200720022903c801370200200741086a2019280200360200200220043703f80120024180016a200241f8016a109a011a0c010b200241f8016a41086a2214280200200241f8016a41106a221b28020041286c6a211102402004500d0020112004370300201120153703080b024002402016450d00201141106a211302402011280210221c450d00201341046a280200450d00201c10020b201320173602042013201636020020112018360218410121130c010b410021130b20032019280200360200200220022903c80137038001200241f8016a20024180016a109801200f200241f8016a41206a2802003602002010200241f8016a41186a2903003703002012201b29030037030020032014290300370300200220022903f80137038001200241b8026a20024180016a10ca01024020022802b802450d002011411c6a21100340200241a0026a41106a200241b8026a41106a290300370300200241a0026a41086a22122001290300370300200220022903b8023703a002200241e0026a41086a2012280200360200200220022903a0023703e0022001200a41086a2802003602002002200a2902003703b802200241d0026a2010200241e0026a200241b8026a10d201024020022802d002450d0020022802d4022212450d00200241d0026a41086a280200450d00201210020b200241b8026a20024180016a10ca0120022802b8020d000b0b20024180016a1099012013201645720d002017450d00201610020b20024180016a200241286a10c801200f29030022044202520d000b0b200241286a109e0120004100360000200241f0026a24000f0b10c301000bb20301097f23002102200141046a280200210320012802082104200241306b220241186a2205200128020022063602002002411c6a2207410036020020022003360214200220034100472208360210024002402003450d002003417f6a2101200241106a41047221092006210a03402005200a2802a006220a3602002007410036020020022001360214200220014100473602102001417f6a2201417f470d000c020b0b200241106a41047221090b200241086a200941086a28020036020020022009290200370300200241106a41086a220a20063602002002411c6a22054100360200200220033602142002200836021002402003450d002003417f6a21010340200a200620062f01be034102746a41a0066a28020022063602002005410036020020022001360214200220014100473602102001417f6a2201417f470d000b0b200241106a41086a28020022012f01be0321062002411c6a280200210a200228021421052000410036020c20002005360210200041146a2001360200200041186a200a3602002000411c6a200636020020002004360220200041086a200241086a280200360200200020022903003702000bc70302077f027e23004190016b220124002001200010c801024020012903204202510d00200141c8006a4104722102200141386a2103200141346a2104200141306a2105200141206a21060340200141c8006a41086a200341086a29030037030020012003290300370348024020052802002207450d002004280200450d00200710020b20014180016a41086a200241086a2802003602002001200229020037038001200141d8006a20014180016a109801200141d8006a1099012001200010c80120062903004202520d000b0b20002802082105200028020021070240024002400240200028020422022802b8032203450d0020023201bc032108200120033602042001200741016a2207360200200120084220862005ad842208370308200210022003450d020c010b2005ad210841002103200210024100450d010b0240024020032802b8032202450d0020033201bc032109200120023602042001200741016a36020020012009422086200842ffffffff0f83843703082003100220020d010c020b41002102200310024100450d010b20022103034020022802b8032202450d02200310022002210320020d000b0b20014190016a24000f0b2003100220014190016a24000b080041ec3a1054000b950301067f230041106b22022400200241003a000b2002410b6a20012802002203200128020422044100472205101e1a2001200420056b22063602042001200320056a22053602000240024002400240024002402004450d0020022d000b2204450d0120044101470d022002410036020c2002410c6a20052006410420064104491b2204101e1a200141046a200620046b3602002001200520046a360200200641034d0d03200041046a200228020c360200200041023a0000200241106a24000f0b200041033a0000200241106a24000f0b200110212203450d0320022003360204200141046a22062802002104200241003a000b2002410b6a2001280200220720044100472205101e1a2006200420056b3602002001200720056a3602002004450d0220022d000b220141034f0d02200020013a0001200041013a0000200041046a2003360200200241106a24000f0b200041033a0000200241106a24000f0b200041033a0000200241106a24000f0b200041033a0000200241046a1022200241106a24000f0b200041033a0000200241106a24000bc905020f7f037e23004180016b22022400200241e0006a10302002280260220320022802681031210402402002280264450d00200310020b200241003602082002420137030020024100200410860120022802082105024002402004450d00200228020020054105746a2103200241306a41086a2106200241106a41186a2107200241106a41106a2108410021090340200241306a200910320240024002402002280230220a2006280200220b41d02d410041001000417f470d002007420037030020084200370300200241106a41086a420037030020024200370310200941016a210920022802340d010c020b200241e0006a41186a220c4200370300200241e0006a41106a220d4200370300200241e0006a41086a220e420037030020024200370360200a200b200241e0006a412041001000220b417f460d04200b411f4d0d04200241c0006a41186a220b200c290300370300200241c0006a41106a220f200d290300370300200241c0006a41086a2210200e29030037030020022002290360370340200c200b290300370300200d200f290300370300200e201029030037030020022002290340370360200b200c2903002211370300200f200d29030022123703002010200e2903002213370300200241106a41086a2013370300200820123703002007201137030020022002290360221137034020022011370310200941016a21092002280234450d010b200a10020b20032002290310370000200341186a2007290300370000200341106a2008290300370000200341086a200241106a41086a290300370000200341206a210320092004490d000b200520096a21050b200241086a2005360200200241c0006a41086a200536020020022002290300370340200241e0006a200241c0006a10a2012002350268422086200235026084211102402002280244450d00200228024010020b20024180016a240020110f0b41eb1a4133102d000bee0201077f230041206b22022400200141086a28020021032002410036021820024201370310200241106a4100410410272002280210200228021822046a20033600002002200441046a360218200241086a2205200228021836020020022002290310370300024002402003450d0020012802002101200341057421060340412010012203450d022002200336021020024220370214200241106a410041201027200241106a41086a22032003280200220441206a22033602002004200228021022076a22042001290000370000200441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a2900003700002002280214210420022005280200200310272002280200200528020022086a20072003101e1a2005200820036a36020002402004450d00200710020b200141206a2101200641606a22060d000b0b20002002290300370200200041086a2005280200360200200241206a24000f0b101c000bf80101017f23004180026b22022400024002402001450d00200220003602080c010b200241d02d360208410021010b2002200136020c20024188016a200241086a101d0240200228029001450d00200241106a20024188016a41f800101e1a20024188016a200241106a41f800101e1a20024188016a2002419c016a200241dc016a10a401024020024198016a2802002200450d0020022802900121012000410c6c210003400240200141046a280200450d00200128020010020b2001410c6a2101200041746a22000d000b0b024020024194016a280200450d0020024190016a28020010020b20024180026a240042010f0b4184351054000ba11903017f017e237f230041900d6b220324002003200029030022043703f00c200341106a41086a220042003703002003420037031041d12d4107200341106a1003200341086a220520002903003703002003200329031037030020034110200341f00c6a41081004200042003703002003420037031041d82d4107200341106a10032005200029030037030020032003290310370300200341102001412010040240024002400240410710012200450d002003200036021020034207370214200341106a4100410710272003280210200328021822056a220041002800c72d360000200341f00c6a41086a200541076a2205360200200041046a41002f00cb2d3b0000200041066a41002d00cd2d3a0000200320032903103703f00c20032005360218410810012200450d002003200036021020034208370214200341106a41004108102720032802102205200328021822006a2004427f7c3700002003200041086a220036021820032802142106200341f00c6a20032802f80c2000102720032802f00c220720032802f80c22086a20052000101e1a2003200820006a22003602f80c02402006450d00200510020b20032802f40c2105200341106a41086a220642003703002003420037031020072000200341106a1003200341086a2006290300370300200320032903103703002003411020014120100402402005450d00200710020b200341106a41086a220042003703002003420037031041df2d4107200341106a1003200341086a220120002903003703002003200329031037030020034110200241201004200042003703002003420037031041d12d4107200341106a100320012000290300370300200320032903103703002003411041d02d410041001000417f460d01200342003703100240024020034110200341106a41084100100041016a41084d0d0020032903104200510d04200341106a41086a220042003703002003420037031041d12d4107200341106a1003200341086a2000290300370300200320032903103703002003411041d02d410041001000417f460d052003420037031020034110200341106a41084100100041016a41084d0d012003290310210441002108200341106a410041e00c10171a2004427f7c2104410021094100210a4100210b4100210c4100210d4100210e4100210f410021104100211141002112410021134100211441002115410021164100211741002118410021194100211a4100211b4100211c4100211d4100211e4100211f4100212041002121410021224100212341002124410021254100212641002102410021270340200341f00c6a42002004427f7c2004501b220410a801200341106a202722004103704105746a220141186a200341f00c6a41186a290200370000200141106a200341f00c6a41106a290200370000200141086a200341f00c6a41086a290200370000200120032902f00c370000200041016a21274100210141002107024003402000200041036e2205417d6c6a4102470d01200341106a20016a220041df006a2d000022022000411f6a2d000022067120022006722000413f6a2d000071722108200041de006a2d000022022000411e6a2d000022067120022006722000413e6a2d000071722109200041dd006a2d000022022000411d6a2d000022067120022006722000413d6a2d00007172210a200041dc006a2d000022022000411c6a2d000022067120022006722000413c6a2d00007172210b200041db006a2d000022022000411b6a2d000022067120022006722000413b6a2d00007172210c200041da006a2d000022022000411a6a2d000022067120022006722000413a6a2d00007172210d200041d9006a2d00002202200041196a2d00002206712002200672200041396a2d00007172210e200041d8006a2d00002202200041186a2d00002206712002200672200041386a2d00007172210f200041d7006a2d00002202200041176a2d00002206712002200672200041376a2d000071722110200041d6006a2d00002202200041166a2d00002206712002200672200041366a2d000071722111200041d5006a2d00002202200041156a2d00002206712002200672200041356a2d000071722112200041d4006a2d00002202200041146a2d00002206712002200672200041346a2d000071722113200041d3006a2d00002202200041136a2d00002206712002200672200041336a2d000071722114200041d2006a2d00002202200041126a2d00002206712002200672200041326a2d000071722115200041d1006a2d00002202200041116a2d00002206712002200672200041316a2d000071722116200041d0006a2d00002202200041106a2d00002206712002200672200041306a2d000071722117200041cf006a2d000022022000410f6a2d000022067120022006722000412f6a2d000071722118200041ce006a2d000022022000410e6a2d000022067120022006722000412e6a2d000071722119200041cd006a2d000022022000410d6a2d000022067120022006722000412d6a2d00007172211a200041cc006a2d000022022000410c6a2d000022067120022006722000412c6a2d00007172211b200041cb006a2d000022022000410b6a2d000022067120022006722000412b6a2d00007172211c200041ca006a2d000022022000410a6a2d000022067120022006722000412a6a2d00007172211d200041c9006a2d00002202200041096a2d00002206712002200672200041296a2d00007172211e200041c8006a2d00002202200041086a2d00002206712002200672200041286a2d00007172211f200041c7006a2d00002202200041076a2d00002206712002200672200041276a2d000071722120200041c6006a2d00002202200041066a2d00002206712002200672200041266a2d000071722121200041c5006a2d00002202200041056a2d00002206712002200672200041256a2d000071722122200041c4006a2d00002202200041046a2d00002206712002200672200041246a2d000071722123200041c3006a2d00002202200041036a2d00002206712002200672200041236a2d000071722124200041c2006a2d00002202200041026a2d00002206712002200672200041226a2d000071722125200041c1006a2d00002202200041016a2d00002206712002200672200041216a2d000071722126200041c0006a2d0000220220002d00002206712002200672200041206a2d000071722102200141800c460d01200341106a20012005410574200541036e41e0006c6b6a6a220041e1006a20263a0000200041e0006a20023a0000200041e2006a20253a0000200041e3006a20243a0000200041e4006a20233a0000200041e5006a20223a0000200041e6006a20213a0000200041e7006a20203a0000200041e8006a201f3a0000200041e9006a201e3a0000200041ea006a201d3a0000200041eb006a201c3a0000200041ec006a201b3a0000200041ed006a201a3a0000200041ee006a20193a0000200041ef006a20183a0000200041f0006a20173a0000200041f1006a20163a0000200041f2006a20153a0000200041f4006a20133a0000200041f3006a20143a0000200041f5006a20123a0000200041f6006a20113a0000200041f7006a20103a0000200041f8006a200f3a0000200041f9006a200e3a0000200041fa006a200d3a0000200041fb006a200c3a0000200041fc006a200b3a0000200041fd006a200a3a0000200041fe006a20093a0000200041ff006a20083a0000200141e0006a210120052100200741016a22074111490d000b0b202741d100470d000b200320263a00f10c200320023a00f00c200320253a00f20c200320243a00f30c200320233a00f40c200320223a00f50c200320213a00f60c200320203a00f70c2003201f3a00f80c2003201e3a00f90c2003201d3a00fa0c2003201c3a00fb0c2003201b3a00fc0c2003201a3a00fd0c200320193a00fe0c200320183a00ff0c200320173a00800d200320163a00810d200320153a00820d200320133a00840d200320143a00830d200320123a00850d200320113a00860d200320103a00870d2003200f3a00880d2003200e3a00890d2003200d3a008a0d2003200c3a008b0d2003200b3a008c0d2003200a3a008d0d200320093a008e0d200320083a008f0d200341106a41086a220042003703002003420037031041e62d4107200341106a1003200341086a220120002903003703002003200329031037030020034110200341f00c6a41201004200341003602f00c200042003703002003420037031041ed2d4107200341106a1003200120002903003703002003200329031037030020034110200341f00c6a41041004200341900d6a24000f0b41c1214133102d000b41c1214133102d000b101c000b41f4214122102d000b4184c200103b000b41f4214122102d000ba80601057f230041d0096b22022400024002402001450d00200220003602080c010b200241d02d360208410021010b2002200136020c200241a0066a200241086a10200240024020022d00a8064107460d00200241106a200241a0066a418003101e1a20024190036a200241106a418003101e1a20024190066a20024190036a1026200241a0066a41086a22014200370300200242003703a00641ed2d4107200241a0066a1003200241b0096a41086a2001290300370300200220022903a0063703b009200241b0096a411041d02d410041001000417f460d01200241003602a00602400240200241b0096a4110200241a0066a41044100100041016a41044d0d0020022802a0062103200241a0096a41086a20024190066a41086a28020036020020022002290390063703a009410710012201450d01200220013602a006200242073702a406200241a0066a41004107102720022802a00620022802a80622006a220141002800e02e360000200241b0096a41086a200041076a2200360200200141046a41002f00e42e3b0000200141066a41002d00e62e3a0000200220022903a0063703b009200220003602a806410410012201450d01200220013602a006200242043702a406200241a0066a41004104102720022802a006220020022802a80622016a20033600002002200141046a22013602a80620022802a4062104200241b0096a20022802b8092001102720022802b009220320022802b80922056a20002001101e1a2002200520016a22053602b80902402004450d00200010020b20022802b4092100200241c0096a200241a0096a105120022802c809210420022802c0092101200241a0066a41086a22064200370300200242003703a00620032005200241a0066a1003200241b0096a41086a2006290300370300200220022903a0063703b009200241b0096a4110200120041004024020022802c409450d00200110020b02402000450d00200310020b024020022802a409450d0020022802a00910020b200241a0066a20024190036a418003101e1a200241a0066a10a601200241d0096a240042010f0b41c1214133102d000b101c000b4184351054000b41f4214122102d000bec0e04037f017e037f017e230041a0086b2201240020014180036a2000418003101e1a200141386a4200370300200141306a4200370300200141286a4200370300200141206a4200370300200141186a4200370300200141106a4200370300200141086a42003703002001420037030002400240024002400240200141c0056a200141c0001006450d00200141a0056a21000c010b20014188066a41186a420037030020014188066a41106a420037030020014188066a41086a42003703002001420037038806200141a0056a220020014188066a41201006450d010b2001410036029006200142013703880620014188066a41004120102720012802880620012802900622026a22032000290000370000200341186a200041186a290000370000200341106a200041106a290000370000200341086a200041086a2900003700002001200241206a220036029006200129038003210420014188066a20004108102720012802880620012802900622006a20043700002001200041086a220236029006200120014180036a41086a10282001280200210320014188066a20022001280208220010272001200020012802900622056a220636029006200520012802880622026a20032000101e1a02402001280204450d00200310020b200128028c06210020022006200141c0056a200141a0056a1015210302402000450d00200210020b200120014180036a418003101e1a20030d010c020b200120014180036a418003101e1a0c010b41bc3a103b000b20014180036a2001418003101e1a200141186a4200370300200141106a4200370300200141086a420037030020014200370300024002400240024002400240024002400240200141a0056a2200200141201006450d00200010c001200129038003520d06200010c0012104410710012203450d04200120033602002001420737020420014100410710272001280200200128020822026a220341002800d92e36000020014188066a41086a200241076a2202360200200341046a41002f00dd2e3b0000200341066a41002d00df2e3a0000200120012903003703880620012002360208412010012203450d04200442017c21042001200336020020014220370204200141004120102720012802002202200128020822056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002001200541206a22033602082001280204210620014188066a20012802900620031027200128028806220520012802900622076a20022003101e1a2001200720036a22073602900602402006450d00200210020b200128028c0621022001200437038006200141086a2203420037030020014200370300200520072001100320014188066a41086a22062003290300370300200120012903003703880620014188066a411020014180066a4108100402402002450d00200510020b200010432104200342003703002001420037030041bf2041072001100320062003290300370300200120012903003703880620014188066a411041d02d410041001000417f460d072001420037030020014188066a4110200141084100100041016a41084d0d02200420012903002208540d08410810012203450d04200120033602002001420837020420014100410810272001280200200128020822036a42f3e885d3a3ac98b63a3700002001200341086a36020820014188066a41086a20012802083602002001200129030037038806412010012203450d04200420087d21042001200336020020014220370204200141004120102720012802002202200128020822056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002001200541206a22003602082001280204210320014188066a20012802900620001027200128028806220520012802900622066a20022000101e1a2001200620006a22003602900602402003450d00200210020b200128028c0621022001200437038006200141086a2203420037030020014200370300200520002001100320014188066a41086a2003290300370300200120012903003703880620014188066a411020014180066a4108100420014188066a2103200121002002450d01200510020c010b2001210020014188066a21030b200120014180036a41c002101e22014188066a200141086a419802101e1a20014188066a200141a0026a10c101200041086a220242003700002000420037000041ed2d410720001003200341086a2002290000370000200320002900003700002003411041d02d410041001000417f460d032001410036020020034110200141044100100041016a41044d0d012001200128020041016a36028006200041086a220242003700002000420037000041ed2d410720001003200341086a2002290000370000200320002900003700002003411020014180066a41041004200141a0086a24000f0b41c1214133102d000b41c1214133102d000b101c000b41f4214122102d000b41d43a103b000b41f4214122102d000b41fc3c103b000bc51505047f017e027f017e027f23004190096b22022400024002402001450d00200220003602000c010b200241d02d360200410021010b20022001360204200241f0056a2002101d20024180066a280200210320022802fc05210420022802f805210520022903f0052106200241f8016a20024184066a41e400101e1a024002400240024002400240024002402005450d00200241f0006a200241f8016a41e400101e1a200241f8046a200241f0006a41e400101e1a200241003602f005200241f0056a2002280200220720022802042201410420014104491b2200101e1a2002200120006b3602042002200720006a3602000240200141034d0d0020022802f0052208ad4280037e2209422088a70d082009a72201417f4c0d07024002402001450d002001100122070d01101c000b410821070b2002200836020c20022007360208410021012002410036021002402008450d00200241f0056a41086a210a410021000340200241f0056a2002102002400240200a2d00004107460d00200041016a2100200241f8016a200241f0056a418003101e1a2001200228020c470d01200241086a106c200241086a41086a2802002101200228020821070c010b02402001450d0020014180036c2100200741186a210103400240200141706a2d00002208411d74411d75417f4a0d000240024020084105460d0020084104470d01200141786a2d00004101470d022001417c6a220828020010382008280200100220014180036a2101200041807d6a22000d030c040b200141786a2d00004101470d012001280200450d012001417c6a280200100220014180036a2101200041807d6a22000d020c030b200141746a2d00004101470d00200141786a220828020010382008280200100220014180036a2101200041807d6a22000d010c020b20014180036a2101200041807d6a22000d000b0b200228020c450d03200710020c030b200720014180036c6a200241f8016a418003101e1a200241086a41086a200141016a220136020020002008490d000b0b2007450d00200229020c2109200241f0056a200241f8046a41e400101e1a2005450d01200241086a200241f0056a41e400101e1a200241fc006a200436020020024180016a2003360200200220053602782002200637037020024184016a200241086a41e400101e2101200241ec016a2009370200200220073602e801200241f0006a2001200241c4016a220310a40120022903702206500d06200241f0056a2006427f7c10a801200241f0056a2001412010060d06200241e8016a2802002100200241f0016a28020021012002410036028005200242043703f804200241f8046a20014180036c22084180036d108401200228028005210720022802f8042105024002402001450d0020052007410c6c6a21010340200241f0056a2000102620022802f005450d0220004180036a2100200241f8016a41086a220a200241f0056a41086a280200360200200220022903f0053703f801200141086a200a280200360200200120022903f801370200200741016a21072001410c6a2101200841807d6a22080d000b0b200241003602f0050b20024180056a200736020020022802fc042108200241f8016a200520052007410c6c6a10a901200241f0056a20022802f8012201200228028002104c024020022802fc01450d00200110020b02402007450d002007410c6c21002005210103400240200141046a280200450d00200128020010020b2001410c6a2101200041746a22000d000b0b02402008450d00200510020b02402003200241f0056a41201006450d0041d90a410e1008200341201013200241f0056a412010130b200241c4016a200241f0056a412010060d05200241ec016a2802002104200241f0006a41f8006a2802002105200241f0016a280200210a200241f8046a200241f0006a41f800101e1a2005200a4180036c6a210720052101200a450d03200241f0056a41096a2108200521010340200141086a2d0000210020012903002106200241f8016a200141096a41f702101e1a20004107460d03200241f0056a41086a20003a0000200220063703f0052008200241f8016a41f702101e1a200241f0056a10a60120014180036a22012007470d000c050b0b02402003450d002003410c6c21012005210203400240200241046a280200450d00200228020010020b2002410c6a2102200141746a22010d000b0b2004450d00200510020b4184351054000b20014180036a21010b20012007460d002005200a4180036c6a210803402001220041086a2d000022074107460d0120004180036a210102402007411d74411d75417f4a0d00200041146a2800002103200041106a280000210a02400240200741077122074105460d0020074104470d01200a41ff01714101470d02200310382003100220082001470d030c040b200a41ff01714101470d01200041186a280000450d012003100220082001470d020c030b2000410c6a2d000041ff01714101470d00200a1038200a100220082001470d010c020b20082001470d000b0b02402004450d00200510020b1034200241f0056a41086a22014200370300200242003703f00541e72e4107200241f0056a1003200241f8016a41086a2001290300370300200220022903f0053703f8014100210b02400240024002400240200241f8016a411041d02d410041001000417f460d00200242103702f4082002200241f8016a3602f008200241f0056a200241f0086a101620022802f0052204450d02200241f8056a280200210820022802f405210b0c010b41042104410021080b4100210a02400240024002400240024020024188056a2802002008470d000240024002402008450d0020024180056a280200210141002107200421000340200141086a280200220a200041086a280200470d0202402001280200220520002802002203460d0020052003200a10060d040b2001410c6a21012000410c6a2100200741016a22072008490d000b4101210a20080d040c060b4101210a200b0d060c070b20042008410c6c6a21074100210a0c030b4100210a0b2008450d020b20042008410c6c6a21070b2004210103402001410c6a21000240200141046a280200450d00200128020010020b2000210120072000470d000b0b200b450d010b200410020b200a450d01200241f0056a10aa0120022802f8052107024020024180066a2802002201450d002001410c6c21002007210103400240200141046a280200450d00200128020010020b2001410c6a2101200041746a22000d000b0b0240200241fc056a280200450d00200710020b200241f8016a41186a22014200370300200241f8016a41106a22004200370300200241f8016a41086a22074200370300200242003703f801200241f8016a1014200241f0086a41186a2001290300370300200241f0086a41106a2000290300370300200241f0086a41086a2007290300370300200220022903f8013703f0080240200241ac056a2201200241f0086a41201006450d0041d90a410e1008200141201013200241f0086a412010130b2001200241f0086a412010060d02024020024188056a2802002200450d0020024180056a28020021012000410c6c210003400240200141046a280200450d00200128020010020b2001410c6a2101200041746a22000d000b0b024020024184056a280200450d0020024180056a28020010020b20024190096a240042010f0b41c1214133102d000b418c3a103b000b41a43a103b000b41f439103b000b41dc39103b000b105d000b105c000b8b0401067f230041306b22022400024002400240410710012203450d002002200336021020024207370214200241106a4100410710272002280210200228021822046a220341002800c72d360000200241086a200441076a2204360200200341046a41002f00cb2d3b0000200341066a41002d00cd2d3a00002002200229031037030020022004360218410810012203450d002002200336021020024208370214200241106a41004108102720022802102204200228021822036a20013700002002200341086a220336021820022802142105200220022802082003102720022802002206200228020822076a20042003101e1a2002200720036a220736020802402005450d00200410020b20022802042104200241106a41086a220342003703002002420037031020062007200241106a1003200241086a2003290300370300200220022903103703002002411041d02d410041001000417f460d02200241286a4200370300200241106a41106a4200370300200342003703002002420037031020024110200241106a4120410010002203417f460d012003411f4d0d0120002002290310370000200041186a200241106a41186a290300370000200041106a200241106a41106a290300370000200041086a200241106a41086a29030037000002402004450d00200610020b200241306a24000f0b101c000b41c1214133102d000b41f4214122102d000bc50103037f017e027f4100210302400240024002400240200220016b2204450d002004410c6d2205ad4203862206a722044100480d032006422088a74100470d03200410012207450d0420012002470d010c020b410421074100210520012002460d010b4100210320072104034020012802002108200441046a200141086a28020036020020042008360200200441086a2104200341016a21032001410c6a22012002470d000b0b2000200536020420002007360200200020033602080f0b1041000b101c000be40703037f027e057f23004180016b22012400200141e0006a41086a220242003703002001420037036041e62d4107200141e0006a1003200141c0006a41086a2203200229030037030020012001290360370340200141c0006a41101005200242003703002001420037036041ed2d4107200141e0006a10032003200229030037030020012001290360370340200141c0006a41101005200342003703002001420037034041d12d4107200141c0006a100320022003290300370300200120012903403703600240024002400240200141e0006a411041d02d410041001000417f460d0020014200370340200141e0006a4110200141c0006a41084100100041016a41084d0d0220012903402104200141c0006a41086a220242003703002001420037034041d12d4107200141c0006a1003200141e0006a41086a200229030037030020012001290340370360200141e0006a411010054201a7450d010c030b4200a70d020b41f4214122102d000b41c1214133102d000b200141d82d10d901200141c0006a41086a220242003703002001420037034041e72e4107200141c0006a1003200141e0006a41086a20022903003703002001200129034037036041002102024002400240200141e0006a411041d02d410041001000417f460d00200142103702242001200141e0006a360220200141c0006a200141206a101620012802402203450d0220012902442105200141c0006a41086a220242003703002001420037034041e72e4107200141c0006a1003200141e0006a41086a200229030037030020012001290340370360200141e0006a411010052005422088a721022005a721060c010b41042103410021060b200141206a41df2d10d901200141e0006a41186a22074200370300200141e0006a41106a22084200370300200141e0006a41086a2209420037030020014200370360200141e0006a1014200141c0006a41186a220a2007290300370300200141c0006a41106a22072008290300370300200141c0006a41086a2208200929030037030020012001290360370340200020043703002000412c6a200141186a290300370000200041246a200141106a2903003700002000411c6a200141086a29030037000020002001290300370014200020012903403700342000413c6a2008290300370000200041c4006a2007290300370000200041cc006a200a290300370000200020033602082000410c6a2006360200200041106a2002360200200041ec006a200141206a41186a290300370000200041e4006a200141206a41106a290300370000200041dc006a200141206a41086a2903003700002000200129032037005420014180016a24000f0b41c1214133102d000bda10040d7f017e017f017e230041d0016b220224001034200241b0016a41086a22034200370300200242003703b00141ed2d4107200241b0016a1003200241a0016a41086a2003290300370300200220022903b0013703a0010240200241a0016a411041d02d410041001000417f460d00200241003602080240200241a0016a4110200241086a41044100100041016a41044d0d0020022802082104200241003602c801200242043703c001200241c0016a200410840120022802c801210520022802c00121060240024002400240024002402004450d0020062005410c6c6a2107410021080340410710012203450d02200220033602082002420737020c200241086a410041071027200241086a41086a22032003280200220941076a220a360200200920022802086a220b41002800e02e36000020024180016a41086a2209200a360200200b41046a41002f00e42e3b0000200b41066a41002d00e62e3a0000200220022903083703800141041001220b450d022002200b3602082002420437020c200241086a41004104102720032003280200220a41046a220b360200200a2002280208220c6a2008360000200228020c210d20024180016a2009280200200b1027200228028001220a2009280200220e6a200c200b101e1a2009200e200b6a220e3602000240200d450d00200c10020b200228028401210d200241a0016a41086a220b4200370300200242003703a001200a200e200241a0016a10032003200b290300370300200220022903a001370308200241086a411041d02d410041001000417f460d0420024100360280014100200241086a411020024180016a41044100100022032003417f461b220c41034d0d062002280280012203417f4c0d03024002402003450d00200310012209450d0420094100200310171a0c010b410121090b20034100200241086a411020092003200c4104200c4104491b1000220c200c417f461b4b0d052009450d06200841016a21082003ad220f422086200f84210f200b4200370300200242003703a001200a200e200241a0016a1003200241b0016a41086a200b290300370300200220022903a0013703b001200241b0016a411010050240200d450d00200a10020b20072009360200200741046a200f3702002007410c6a210720082004490d000b200520086a21050b200241c8016a200536020020022802c4012108200241086a200620062005410c6c6a10a90120024180016a200228020822032002280210104c0240200228020c450d00200310020b02402005450d002005410c6c21092006210303400240200341046a280200450d00200328020010020b2003410c6a2103200941746a22090d000b0b02402008450d00200610020b200241086a41186a20024180016a41186a290300370300200241086a41106a220920024180016a41106a290300370300200241086a41086a20024180016a41086a22072903003703002002200229038001370308200241b0016a41086a22044200370300200242003703b00141df2d4107200241b0016a1003200241a0016a41086a22082004290300370300200220022903b0013703a001200241a0016a4110200241086a41201004200241086a10aa01200241003602c801200242013703c001200241c0016a41004120102720022802c00120022802c801220b6a2203200229021c370000200341086a200241246a290200370000200341106a2002412c6a290200370000200341186a200241346a2902003700002002200b41206a22033602c8012002290308210f200241c0016a20034108102720022802c00120022802c80122036a200f3700002002200341086a22033602c801200241c0016a20034120102720022802c00120022802c801220b6a2203200229023c370000200341086a200241c4006a290200370000200341106a200241cc006a290200370000200341186a200241d4006a2902003700002002200b41206a22033602c801200241c0016a20034120102720022802c00120022802c801220b6a2203200229025c370000200341086a200241e4006a290200370000200341106a200241ec006a290200370000200341186a200241f4006a2902003700002002200b41206a22103602c801200928020021052002410036028801200242013703800120024180016a41004104102720022802800120022802880122036a20053600002002200341046a36028801200820022802880136020020022002290380013703a00120022802102106024002402005450d002005410c6c210c2006210b0340200241b0016a200b105120042802002203417f4c0d0420022802b001210a024002402003450d002003100122090d010c050b410121090b200741003602002002200336028401200220093602800120024180016a41002003102720072007280200220d20036a2209360200200d200228028001220e6a200a2003101e1a2002280284012103024020022802b401450d00200a10020b200241a0016a20082802002009102720022802a001220d2008280200220a6a200e2009101e1a2008200a20096a220936020002402003450d00200e10020b200b410c6a210b200c41746a220c0d000c020b0b20022802a801210920022802a001210d0b20022802a4012103200241c0016a201020091027200220022802c801220820096a22073602c801200820022802c001220b6a200d2009101e1a02402003450d00200d10020b2007ad422086210f200bad211102402005450d002005410c6c21092006210303400240200341046a280200450d00200328020010020b2003410c6a2103200941746a22090d000b0b200f201184210f0240200241146a280200450d00200610020b200241d0016a2400200f0f0b101c000b1019000b41f4214122102d000b200910020b41c1214133102d000b41c1214133102d000b41f4214122102d000b810101047f230041106b220224002002102f2002280208210302402002280204450d00200228020010020b0240410410012204450d002002200436020020024204370204200241004104102720022802002204200228020822056a20033600002002200541046a2203360208200241106a24002003ad4220862004ad840f0b101c000b4802017f017e230041206b220224002002102f200241106a200210a2012002350218422086200235021084210302402002280204450d00200228020010020b200241206a240020030ba56d09047f027e047f017e0b7f017e027f017e0c7f230041a0016b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d0000417f6a220341044b0d000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e050004020301000b200041106a2802002104200241186a41086a2000410c6a2802003602002002200041046a290200370318200241e8006a41086a220342003703002002420037036841b00f4107200241e8006a1003200241d8006a41086a2205200329030037030020022002290368370358200241d8006a4110200241f8006a410041001000417f470d38200342003703002002420037036841b70f4107200241e8006a10032005200329030037030020022002290368370358200241d8006a411041d02d410041001000417f460d0420024100360278200241d8006a4110200241f8006a41044100100041016a41044d0d4320022802782004470d050c590b200041246a2802002104200041286a290300210c200241c0006a200041196a290000370300200241286a41106a200041116a290000370300200241286a41086a200041096a29000037030020022000290001370328200241e8006a41086a220342003703002002420037036841b70f4107200241e8006a1003200241d8006a41086a200329030037030020022002290368370358410021030240200241d8006a411041d02d410041001000417f460d0020024100360278200241d8006a4110200241f8006a41044100100041016a41044d0d42200228027821030b20032004470d36200241e8006a41086a220342003703002002420037036841b00f4107200241e8006a1003200241d8006a41086a200329030037030020022002290368370358200241d8006a411041d02d410041001000417f460d352002200241d8006a3602682002411036026c2002420037037820024100200241d8006a4110200241f8006a41084100100022032003417f461b22034108200341084922041b220336027020040d3e20024100360278200241f0006a4100200241d8006a4110200241f8006a41042003100022042004417f461b22044104200441044922041b20036a36020020040d3e200241f8006a200241e8006a103a2002280278220d450d3e200241f8006a41086a280200210e200228027c210f200241e8006a41086a22034200370300200242003703684181114107200241e8006a1003200241d8006a41086a200329030037030020022002290368370358200241d8006a411041d02d410041001000417f460d34200241003602784100200241d8006a4110200241f8006a41044100100022032003417f461b220441034d0d4a20022802782209ad2206421d88a70d332006420386a72203417f4c0d322003450d052003100122100d060c5a0b200041046a2802002103200241e8006a41086a220442003703002002420037036841b00f4107200241e8006a1003200241d8006a41086a200429030037030020022002290368370358200241d8006a4110200241f8006a410041001000417f470d30200110af01450d2f200241e8006a41086a220442003703002002420037036841c50f4107200241e8006a1003200241d8006a41086a200429030037030020022002290368370358200241d8006a411041d02d410041001000417f460d392002421037022c2002200241d8006a360228200241f8006a200241286a103a20022802782204450d2e20024180016a280200220520034d0d39200228027c21080240200420034105746a22092001460d0020092001412010060d1c0b2002200836027c20022004360278200220053602800120012003200241f8006a10b001200241e8006a41086a220342003703002002420037036841be0f4107200241e8006a1003200241d8006a41086a200329030037030020022002290368370358200241d8006a411041d02d410041001000417f460d2d20024200370378200241d8006a4110200241f8006a41084100100041016a41084d0d472002290378210620012001104422072006200720072006561b22067d10b101200110432107410810012203450d59200220033602782002420837027c200241f8006a410041081027200228027820022802800122036a42f3e885d3a3ac98b63a3700002002200341086a36028001200241286a41086a20022802800136020020022002290378370328412010012203450d59200720067c2106200220033602782002422037027c200241f8006a4100412010272002280278220420022802800122056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a220336028001200228027c2108200241286a20022802302003102720022802282205200228023022016a20042003101e1a2002200120036a220336023002402008450d00200410020b200228022c210820022006370378200241e8006a41086a220442003703002002420037036820052003200241e8006a1003200241d8006a41086a200429030037030020022002290368370358200241d8006a4110200241f8006a41081004410121042008450d58200510020c580b200041046a2802002103410710012204450d58200220043602782002420737027c200241f8006a410041071027200228027820022802800122056a220441002800bf10360000200241286a41086a200541076a2205360200200441046a41002f00c3103b0000200441066a41002d00c5103a0000200220022903783703282002200536028001412010012204450d58200220043602782002422037027c200241f8006a4100412010272002280278220520022802800122086a22042001290000370000200441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a2900003700002002200841206a220436028001200228027c2109200241286a200228023020041027200228022822082002280230220a6a20052004101e1a2002200a20046a220436023002402009450d00200510020b200228022c2105200241e8006a41086a220942003703002002420037036820082004200241e8006a1003200241d8006a41086a200929030037030020022002290368370358200241d8006a4110200241f8006a410041001000210402402005450d00200810020b2004417f470d2b200241e8006a41086a220442003703002002420037036841c6104107200241e8006a1003200241d8006a41086a200429030037030020022002290368370358200241d8006a411041d02d410041001000417f460d2a20024200370378200241d8006a4110200241f8006a41084100100041016a41084d0d452001200229037810b201450d29200241e8006a41086a220442003703002002420037036841cd104107200241e8006a1003200241d8006a41086a200429030037030020022002290368370358410021050240200241d8006a411041d02d410041001000417f460d0020024100360278200241d8006a4110200241f8006a41044100100041016a41044d0d3f200228027821050b200241e8006a41086a2204420037030020024200370368418d104107200241e8006a1003200241d8006a41086a20042903003703002002200229036837035841002109200241d8006a411041d02d410041001000417f460d052002421037022c2002200241d8006a360228200241f8006a200241286a103a20022802782208450d1920024180016a2802002104200228027c210920052003470d4e0c4d0b2000412c6a2802002103200041286a2802002111200041246a2802002112200241c0006a200041196a290000370300200241286a41106a200041116a290000370300200241286a41086a200041096a29000037030020022000290001370328200241e8006a41086a220442003703002002420037036841b00f4107200241e8006a1003200241d8006a41086a200429030037030020022002290368370358200241d8006a4110200241f8006a410041001000417f470d27200241086a200110b30120022802084101470d262002200241286a10b3012002280200450d252002280204210e200241e8006a41086a220442003703002002420037036841b70f4107200241e8006a1003200241d8006a41086a200429030037030020022002290368370358410021040240200241d8006a411041d02d410041001000417f460d0020024100360278200241d8006a4110200241f8006a41044100100041016a41044d0d3d200228027821040b20042003470d24200241e8006a41086a22044200370300200242003703684186104107200241e8006a1003200241d8006a41086a200429030037030020022002290368370358200241d8006a411041d02d410041001000417f460d2320024100360278200241d8006a4110200241f8006a41044100100041016a41044d0d41200e200320022802786b4f0d22200241e8006a41086a220342003703002002420037036841c50f4107200241e8006a1003200241d8006a41086a200329030037030020022002290368370358200241d8006a411041d02d410041001000417f460d3a2002421037026c2002200241d8006a360268200241f8006a200241e8006a103a20022802782213450d2120024180016a280200221420124d0d3a200228027c21150240201320124105746a22032001460d0020032001412010060d3b0b201420114d0d360240201320114105746a2203200241286a460d002003200241286a412010060d370b200241c8006a200241286a10b4012002280250210320022802482105200241e8006a41086a2204420037030020024200370368418d104107200241e8006a1003200241d8006a41086a20042903003703002002200229036837035841002116200241d8006a411041d02d410041001000417f460d052002421037026c2002200241d8006a360268200241f8006a200241e8006a103a20022802782217450d17200228027c211620024180016a28020041057441057522042003200320044b1b22080d060c070b41002004460d540b41dc351054000b410821100b2002200936027c20022010360278200241003602800102402009450d002004410420044104491b210441002103410021050340200242003703684100200241d8006a4110200241e8006a41082004100022082008417f461b220841074d0d442008410820084108491b2108200541016a21052002290368210602402003200228027c470d00200241f8006a1071200241f8006a41086a2802002103200228027821100b200820046a2104201020034103746a2006370300200241f8006a41086a200341016a220336020020052009490d000b200228027821100b2010450d43200229027c2118200241e8006a41086a220342003703002002420037036841c50f4107200241e8006a1003200241d8006a41086a20032903003703002002200229036837035841002119200241d8006a411041d02d410041001000417f460d042002421037026c2002200241d8006a360268200241f8006a200241e8006a103a2002280278221a450d1220024180016a280200210b200228027c21190c050b410121084100210420052003460d470c480b4101211741002003200341004b1b2208450d010b4100210420024190016a210920024188016a210a20024180016a210b2017210303400240200520046a2d0000450d0020094200370300200a4200370300200b420037030020024200370378200241f8006a2003460d002003200241f8006a41201006450d00200241f8006a200310b50120022802784101470d3b200228027c200e4d0d050b200341206a2103200441016a22042008490d000b0b410021032016450d430c420b4101211a4100210b0b200241e8006a41086a22034200370300200242003703684188114107200241e8006a1003200241d8006a41086a200329030037030020022002290368370358200241d8006a411041d02d410041001000417f460d1620024200370378200241d8006a4110200241f8006a41084100100041016a41084d0d392002290378210620011043200110447c2006200bad7e221b540d15200241e8006a41086a2203420037030020024200370368418f114107200241e8006a1003200241d8006a41086a200329030037030020022002290368370358200241d8006a411041d02d410041001000417f460d142002421037026c2002200241d8006a360268200241f8006a200241e8006a10b60120022802782217450d1320024180016a280200221c450d122017290300200c5a0d11200228027c211d200241f8006a104720022802782209200228028001221141286c22056a210a41002103200921040240024002400240200541286d4104490d0020092105410021030340200241286a20052204460d0220032004200241286a4120100622054100476a21032005450d02200441286a2205200241286a460d0220032005200241286a4120100622084100476a21032008450d02200541286a2205200241286a460d0220032005200241286a4120100622084100476a21032008450d02200541286a2205200241286a460d0220032005200241286a4120100622084100476a21032008450d02200a200541286a22056b41286d41034b0d000b200441a0016a21040b02402004200a460d002009201141286c6a21080340200241286a2004460d0220032004200241286a4120100622054100476a21032005450d022008200441286a2204470d000b0b41000d010c020b4101450d010b2003200e4f0d0c0b0240200228027c450d00200910020b200241f8006a200241286a10b50120022802784101470d10024002402018421d88a74103752203200b4105744105752204200420034b1b2208450d0020024180016a2802002109200228027c210a4200210741002104201a210320102105034020052903002106200241106a200310b301200441016a21040240024020022802104101470d002002280214200a490d00200241f8006a200310b4010240200241f8006a41086a28020020094d0d002002280278220e20096a2d0000210b0240200228027c450d00200e10020b200b41ff01710d020c010b200228027c450d00200228027810020b420021060b200341206a2103200541086a2105200620077c210720042008490d000c020b0b420021070b2017201c41286c22056a21042017210302400240200541286d4104490d00200241206a2105200241786a2108200241506a2109200241a87f6a210a20172103034020052003460d02200341086a200241286a41201006450d0220082003460d02200341306a200241286a41201006450d0220092003460d02200341d8006a200241286a41201006450d02200a2003460d0220034180016a200241286a41201006450d022004200341a0016a22036b41286d41034b0d000b0b024020032004460d002017201c41286c6a2105200241206a2104034020042003460d02200341086a200241286a41201006450d022005200341286a2203470d000b0b2007200c520d00200241f8006a41186a2203200241286a41186a290300370300200241f8006a41106a2204200241286a41106a290300370300200241f8006a41086a2205200241286a41086a290300370300200220022903283703782017200c370300201741206a2003290300370300201741186a2004290300370300201741106a200529030037030020172002290378370308201c41144b0d02201c41014d0d03201c417f6a21092017201c41286c6a41586a210e0340201c20092203417f6a2209490d2d0240201c20096b22084102490d002017200341286c6a22052903002017200941286c6a220b29030022065a0d00200b2005290300370300200b2903082107200b41086a200541086a290300370300200241f8006a41186a2211200b41206a2203290300370300200241f8006a41106a2212200b41186a2204290300370300200241f8006a41086a2213200b41106a22012903003703002001200541106a2903003703002004200541186a2903003703002003200541206a2903003703002002200737037841012101024020084103490d0041012104200e21030340200441016a220120084f0d340240200341286a220529030020065a0d00200420084f0d34200341206a200341c8006a290300370300200341186a200341c0006a290300370300200341106a200341386a290300370300200341086a200341306a29030037030020032005290300370300200441026a210a2001210420052103200a2008490d010c020b0b20042101200321050b20052006370300200b200141286c6a22032002290378370308200341206a2011290300370300200341186a2012290300370300200341106a20132903003703000b200e41586a210e20090d000c040b0b200110432106410810012203450d4d200220033602782002420837027c200241f8006a410041081027200228027820022802800122036a42f3e885d3a3ac98b63a3700002002200341086a36028001200241e8006a41086a20022802800136020020022002290378370368412010012203450d4d2006201b20062006201b561b220c7d2107200220033602782002422037027c200241f8006a4100412010272002280278220420022802800122056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a220336028001200228027c2108200241e8006a20022802702003102720022802682205200228027022096a20042003101e1a2002200920036a220336027002402008450d00200410020b200228026c210420022007370378200241e8006a41086a220842003703002002420037036820052003200241e8006a1003200241d8006a41086a200829030037030020022002290368370358200241d8006a4110200241f8006a4108100402402004450d00200510020b0240201b2006580d002001200110442206201b200c7d2207200620062007561b7d10b1010b0240201d450d00201710020b02402019450d00201a10020b2018a7450d3f0c3e0b4101210320160d3f0c400b201c410176221ead42287e2206422088a70d082006a72203417f4c0d074108211f02402003450d0020031001221f450d4c0b410021042002410036027020024204370368201741586a2120201741887f6a212141042105200241e8006a41086a2115201c211603402016210e410021164101210802400240024002400240024002400240200e417f6a2203450d0002400240024002400240024002402017200341286c6a2903002017200e417e6a220841286c6a29030022065a0d00410021092008450d022021200e41286c6a210303402006200329030022075a0d02200341586a2103200721062008417f6a22080d000c030b0b02402008450d002021200e41286c6a2103410221080340200620032903002207540d04200341586a210320072106200e200841016a2208470d000b41002116200e21082004200228026c470d0e0c0d0b41022108410021162004200228026c470d0d0c0c0b200821090b200e2009490d02200e201c4b0d090240200e20096b2208410176220a450d002020200e41286c6a21032017200941286c6a21010340200241f8006a41206a220b200141206a2211290300370300200241f8006a41186a2212200141186a2213290300370300200241f8006a41106a2214200141106a2216290300370300200241f8006a41086a2222200141086a222329030037030020022001290300370378200341086a22242903002106200341106a22252903002107200341186a2226290300211b2003290300210c2011200341206a22272903003703002013201b37030020162007370300202320063703002001200c3703002027200b29030037030020262012290300370300202520142903003703002024202229030037030020032002290378370300200341586a2103200141286a2101200a417f6a220a0d000b0b2009450d010c030b200e20086b22090d020b200921160c020b2009200e1055000b0240200841094b0d00200e201c4b0d042017200941286c6a21120340200e2009417f6a2216490d060240200e20166b22084102490d002017200941286c6a22092903002017201641286c6a221129030022065a0d002011200929030037030020112903082107201141086a200941086a290300370300200241f8006a41186a2213201141206a2203290300370300200241f8006a41106a2214201141186a2201290300370300200241f8006a41086a2222201141106a220a290300370300200a200941106a2903003703002001200941186a2903003703002003200941206a290300370300200220073703784101210a024020084103490d0041012101201221030340200141016a220a20084f0d060240200341286a220929030020065a0d00200120084f0d08200341206a200341c8006a290300370300200341186a200341c0006a290300370300200341106a200341386a290300370300200341086a200341306a29030037030020032009290300370300200141026a210b200a210120092103200b2008490d010c020b0b2001210a200321090b200920063703002011200a41286c6a22032002290378370308200341206a2013290300370300200341186a2014290300370300200341106a20222903003703000b2016450d02201241586a2112201621092008410a490d000c020b0b200921162004200228026c470d070c060b2004200228026c460d050c060b41ccc100200141016a2008103c000b41dcc10020012008103c000b200e2009417f6a22164f0d010b2016200e1055000b200e201c1029000b200241e8006a107a20152802002104200228026821050b200520044103746a22032008360204200320163602002015200441016a2204360200024020044102490d00200228026821050340024002400240024020052004417f6a4103746a2203280200450d00200520044103746a220941746a2802002201200328020422084d0d00200441024d0d0520052004417d6a22124103746a2802042203200820016a4d0d01200441034d0d05200941646a280200200320016a4d0d010c050b20044103490d012003280204210820052004417d6a22124103746a28020421030b20032008490d010b2004417e6a21120b2004201241016a22134d0d04200420124d0d052005201241037422226a2203280204222320032802006a22032005201341037422246a22042802002214490d062003201c4b0d072017201441286c6a220e2004280204221141286c22046a2108200341286c210502400240024002400240200320146b220920116b220320114f0d00201f2008200341286c2204101e220b20046a210120114101480d0120034101480d01202020056a21052008210303402005200341586a2208200141586a22092009290300200829030054220a1b2204290300370300200541206a200441206a290300370300200541186a200441186a290300370300200541106a200441106a290300370300200541086a200441086a29030037030020012009200a1b2101200e20082003200a1b22034f0d04200541586a2105200b2104200b2001490d000c050b0b201f200e2004101e220320046a210120114101480d01200920114c0d01201720056a210a20032104200e21030340200320082004200829030020042903005422091b2205290300370300200341206a200541206a290300370300200341186a200541186a290300370300200341106a200541106a290300370300200341086a200541086a2903003703002004200441286a20091b2104200341286a2103200841286a200820091b2208200a4f0d04200120044b0d000c040b0b200821030c010b200e21030b201f21040b20032004200120046b220520054128706b101e1a2015280200220320124d0d082002280268220520226a2204202320116a36020420042014360200200320134d0d09200520246a2204200441086a200320136b41037441786a10391a20152003417f6a2204360200200441014b0d000b0b20160d000b0240200228026c450d00200228026810020b201e450d00201f10020b2002201d36027c200220173602782002201c36028001200241f8006a10b7010240201d450d00201710020b02402019450d00201a10020b2018a70d3b0c3c0b41acc10020132004103c000b41acc10020122004103c000b201420031055000b2003201c1029000b41bcc10020122003103c000b41b4c300103b000b105f000b105e000b418439103b000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41d437103b000b41ce114123102d000b41ec38103b000b41cc3641004100103c000b41c1214133102d000b4196114131102d000b41d438103b000b41f4214122102d000b41c1214133102d000b41b436103b000b41f4214122102d000b419c36103b000b41da0f412c102d000b418436103b000b41ec35103b000b418438103b000b41f4214122102d000b41ec37103b000b41f4214122102d000b41c1214133102d000b41a437103b000b418c37103b000b1063000b1062000b41f4214122102d000b41d410412d102d000b41c4381054000b41c435103b000b2009201c1055000b41f436103b000b41bc37103b000b41dcc10020042008103c000b41ccc100200441016a2008103c000b41dc36103b000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b419410412b102d000b41c1214133102d000b41ac35103b000b41c1214133102d000b41c1214133102d000b41c1214133102d000b200228027c450d00201010020b41c1214133102d000b201010020b200f450d09200d10020c090b201710020b0240200228024c450d00200510020b2002201536027c2002201336027820022014360280012001200241286a20031b2012201120031b200241f8006a10b001200241e8006a41086a220442003703002002420037036841be0f4107200241e8006a1003200241d8006a41086a2004290300370300200220022903683703580240200241d8006a411041d02d410041001000417f460d00200242003703780240200241d8006a4110200241f8006a41084100100041016a41084d0d002002290378210602402003450d0020012001104422072006200720072006561b7d10b1010c0a0b200241286a200241286a104422072006200720072006561b22067d10b101200110432107410810012203450d0d200220033602782002420837027c200241f8006a410041081027200228027820022802800122036a42f3e885d3a3ac98b63a3700002002200341086a36028001200241e8006a41086a20022802800136020020022002290378370368412010012203450d0d200720067c2106200220033602782002422037027c200241f8006a4100412010272002280278220420022802800122056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a220336028001200228027c2108200241e8006a20022802702003102720022802682205200228027022016a20042003101e1a2002200120036a220336027002402008450d00200410020b200228026c210420022006370378200241e8006a41086a220842003703002002420037036820052003200241e8006a1003200241d8006a41086a200829030037030020022002290368370358200241d8006a4110200241f8006a410810042004450d09200510020c090b41c1214133102d000b41f4214122102d000b20042003460d010b200420034d0d0120024190016a420037030020024188016a420037030020024180016a420037030020024200370378200820034105746a220a200241f8006a460d00200a200241f8006a412010060d010b2002200936024c20022008360248200220043602500240024020042003470d00200241f8006a41186a2204200141186a290000370300200241f8006a41106a220b200141106a290000370300200241f8006a41086a220e200141086a290000370300200220012900003703782003210a20032009460d010c040b200241f8006a41186a2209200141186a290000370300200241f8006a41106a220a200141106a290000370300200241f8006a41086a220b200141086a29000037030020022001290000370378200420034d0d02200820034105746a22042002290378370000200441186a2009290300370000200441106a200a290300370000200441086a200b2903003700000c040b200241c8006a107c200241c8006a41086a280200210a200228024821080c020b419c38103b000b41b43820032004103c000b200e2903002106200b29030021072004290300211b2008200a4105746a22042002290378370000200441186a201b370000200441106a2007370000200441086a2006370000200241c8006a41086a200a41016a3602000b200241286a41086a200241c8006a41086a28020036020020022002290348370328200241f8006a200241286a10a201200228028001210820022802782104200241e8006a41086a2209420037030020024200370368418d104107200241e8006a1003200241d8006a41086a200929030037030020022002290368370358200241d8006a41102004200810040240200228027c450d00200410020b0240200228022c450d00200228022810020b2002200541016a360278200241e8006a41086a220442003703002002420037036841cd104107200241e8006a1003200241d8006a41086a2205200429030037030020022002290368370358200241d8006a4110200241f8006a41041004200442003703002002420037036841b70f4107200241e8006a10032005200429030037030020022002290368370358410021050240200241d8006a411041d02d410041001000417f460d0020024100360278200241d8006a4110200241f8006a41044100100041016a41044d0d02200228027821050b410710012204450d04200220043602782002420737027c200241f8006a410041071027200228027820022802800122086a220441002800bf10360000200241286a41086a200841076a2208360200200441046a41002f00c3103b0000200441066a41002d00c5103a0000200220022903783703282002200836028001412010012204450d04200220043602782002422037027c200241f8006a4100412010272002280278220820022802800122096a22042001290000370000200441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a2900003700002002200941206a220436028001200228027c2109200241286a200228023020041027200228022822012002280230220a6a20082004101e1a2002200a20046a220a36023002402009450d00200810020b200228022c2108200241003602800120024201370378200241f8006a410041041027200228027820022802800122046a20053600002002200441046a220436028001200241f8006a2004410410272002280278220420022802800122056a20033600002002200541046a220336028001200241e8006a41086a22054200370300200242003703682001200a200241e8006a1003200241d8006a41086a200529030037030020022002290368370358200241d8006a41102004200310040240200228027c450d00200410020b2008450d00200110020b410121040c020b41c1214133102d000b0240200110af010d00200241e8006a41086a220342003703002002420037036841be0f4107200241e8006a1003200241d8006a41086a2003290300370300200220022903683703580240024002400240200241d8006a411041d02d410041001000417f460d00200242003703780240200241d8006a4110200241f8006a41084100100041016a41084d0d00200229037821062001104322072006540d02410810012203450d07200220033602782002420837027c200241f8006a410041081027200228027820022802800122036a42f3e885d3a3ac98b63a3700002002200341086a36028001200241286a41086a20022802800136020020022002290378370328412010012203450d07200720067d2107200220033602782002422037027c200241f8006a4100412010272002280278220520022802800122086a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200841206a220336028001200228027c2109200241286a200228023020031027200228022822082002280230220a6a20052003101e1a2002200a20036a220336023002402009450d00200510020b200228022c210520022007370378200241e8006a41086a220942003703002002420037036820082003200241e8006a1003200241d8006a41086a200929030037030020022002290368370358200241d8006a4110200241f8006a4108100402402005450d00200810020b20012001104420067c10b101200241e8006a41086a220342003703002002420037036841c50f4107200241e8006a1003200241d8006a41086a20032903003703002002200229036837035802400240200241d8006a411041d02d410041001000417f460d002002421037022c2002200241d8006a360228200241f8006a200241286a103a20022802782208450d052002200229027c220637022c20022008360228200241f8006a41186a200141186a290000370300200241f8006a41106a200141106a290000370300200241f8006a41086a200141086a29000037030020022001290000370378200241f8006a21032006422088a722052006a7460d010c060b2002410036023020024201370328200241f8006a41186a200141186a290000370300200241f8006a41106a200141106a290000370300200241f8006a41086a200141086a29000037030020022001290000370378200241f8006a21030b200241286a107c200241306a2802002105200228022821080c040b41c1214133102d000b41f4214122102d000b41ec3d103b000b41c1214133102d000b20032900002106200241286a41086a2209200541016a360200200820054105746a22052006370000200541186a200341186a290000370000200541106a200341106a290000370000200541086a200341086a290000370000200241c8006a41086a200928020036020020022002290328370348200241f8006a200241c8006a10a201200228028001210520022802782103200241e8006a41086a220842003703002002420037036841c50f4107200241e8006a1003200241d8006a41086a200829030037030020022002290368370358200241d8006a41102003200510040240200228027c450d00200310020b200228024c450d00200228024810020b200241f8006a41186a200141186a290000370300200241f8006a41106a200141106a290000370300200241f8006a41086a200141086a29000037030020022001290000370378200241c8006a41086a200241186a41086a28020036020020022002290318370348410710012203450d01200220033602282002420737022c200241286a4100410710272002280228200228023022056a220341002800cc0f360000200241e8006a41086a200541076a2205360200200341046a41002f00d00f3b0000200341066a41002d00d20f3a00002002200229032837036820022005360230412010012203450d01200220033602282002422037022c200241286a41004120102720022802282205200228023022086a22032002290378370000200341086a200241f8006a41086a290300370000200341106a200241f8006a41106a290300370000200341186a200241f8006a41186a2903003700002002200841206a2203360230200228022c2109200241e8006a200228027020031027200228026822082002280270220a6a20052003101e1a2002200a20036a220a36027002402009450d00200510020b200228026c2105200241286a200241c8006a10b8012002280230210920022802282103200241e8006a41086a220b4200370300200242003703682008200a200241e8006a1003200241d8006a41086a200b29030037030020022002290368370358200241d8006a41102003200910040240200228022c450d00200310020b02402005450d00200810020b0240200228024c450d00200228024810020b410710012203450d01200220033602782002420737027c200241f8006a410041071027200228027820022802800122056a220341002800d30f360000200241286a41086a200541076a2205360200200341046a41002f00d70f3b0000200341066a41002d00d90f3a0000200220022903783703282002200536028001412010012203450d01200220033602782002422037027c200241f8006a4100412010272002280278220520022802800122086a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200841206a220336028001200228027c2101200241286a20022802302003102720022802282208200228023022096a20052003101e1a2002200920036a220336023002402001450d00200510020b200228022c210520022004360278200241e8006a41086a220442003703002002420037036820082003200241e8006a1003200241d8006a41086a200429030037030020022002290368370358200241d8006a4110200241f8006a4104100402402005450d00200810020b410021040b0240024020002d000022034107714101460d0020034105460d0120034102460d0120034101470d01200041086a280200450d01200041046a2802001002200241a0016a24000f0b2004450d00200041086a280200450d00200041046a28020010020b200241a0016a24000f0b101c000ba90301057f230041206b220124000240410710012202450d002001200236021020014207370214200141106a4100410710272001280210200128021822036a220241002800d30f360000200141086a200341076a2203360200200241046a41002f00d70f3b0000200241066a41002d00d90f3a00002001200129031037030020012003360218412010012202450d002001200236021020014220370214200141106a41004120102720012802102203200128021822046a22022000290000370000200241086a200041086a290000370000200241106a200041106a290000370000200241186a200041186a2900003700002001200441206a220036021820012802142104200120012802082000102720012802002202200128020822056a20032000101e1a2001200520006a220036020802402004450d00200310020b20012802042103200141106a41086a220442003703002001420037031020022000200141106a1003200141086a20042903003703002001200129031037030020014110200141106a410041001000210002402003450d00200210020b200141206a24002000417f470f0b101c000bc70908057f017e017f027e017f017e017f017e230041d0006b220324000240200241086a2204280200220520014d0d002002280200220620014105746a220141186a2207290000210820062005417f6a22094105746a2205290000210a200541086a2206290000210b200541106a220c290000210d2007200541186a220e290000370000200141106a2207290000210f2007200d370000200141086a2207290000210d2007200b3700002001290000210b2001200a370000200341106a41186a2008370300200341106a41106a200f370300200341106a41086a2201200d370300200e2008370000200c200f3700002006200d3700002005200b3700002003200b37031020042009360200200341086a200936020020032002290200370300200341c0006a200310a2012003280248210220032802402105200142003703002003420037031041c50f4107200341106a1003200341306a41086a200129030037030020032003290310370330200341306a411020052002100402402003280244450d00200510020b02402003280204450d00200328020010020b0240410710012201450d002003200136021020034207370214200341106a4100410710272003280210200328021822056a220141002800cc0f360000200341306a41086a200541076a2205360200200141046a41002f00d00f3b0000200141066a41002d00d20f3a00002003200329031037033020032005360218412010012201450d002003200136021020034220370214200341106a41004120102720032802102205200328021822026a22012000290000370000200141086a200041086a290000370000200141106a200041106a290000370000200141186a200041186a2900003700002003200241206a220136021820032802142109200341306a20032802382001102720032802302202200328023822046a20052001101e1a2003200420016a220136023802402009450d00200510020b20032802342105200341106a41086a220942003703002003420037031020022001200341106a1003200341306a41086a200929030037030020032003290310370330200341306a4110100502402005450d00200210020b410710012201450d002003200136021020034207370214200341106a4100410710272003280210200328021822056a220141002800d30f360000200341306a41086a200541076a2205360200200141046a41002f00d70f3b0000200141066a41002d00d90f3a00002003200329031037033020032005360218412010012201450d002003200136021020034220370214200341106a41004120102720032802102205200328021822026a22012000290000370000200141086a200041086a290000370000200141106a200041106a290000370000200141186a200041186a2900003700002003200241206a220036021820032802142102200341306a20032802382000102720032802302201200328023822096a20052000101e1a2003200920006a220036023802402002450d00200510020b20032802342105200341106a41086a220242003703002003420037031020012000200341106a1003200341306a41086a200229030037030020032003290310370330200341306a4110100502402005450d00200110020b200341d0006a24000f0b101c000b419c3920012005103c000b9a0301057f230041306b220224000240410810012203450d002002200336022020024208370224200241206a4100410810272002280220200228022822036a42f3e885d3c3cdd8b73a3700002002200341086a360228200241106a41086a200228022836020020022002290320370310412010012203450d002002200336022020024220370224200241206a41004120102720022802202204200228022822056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002002200541206a220036022820022802242105200241106a20022802182000102720022802102203200228021822066a20042000101e1a2002200620006a220036021802402005450d00200410020b2002280214210420022001370308200241206a41086a220542003703002002420037032020032000200241206a1003200241106a41086a200529030037030020022002290320370310200241106a4110200241086a4108100402402004450d00200310020b200241306a24000f0b101c000bfd0602067f017e230041306b220224000240410810012203450d00200220033602182002420837021c200241186a4100410810272002280218200228022022036a42f3e885d3a3ec9bb73a3700002002200341086a360220200241086a41086a200228022036020020022002290318370308412010012203450d00200220033602182002422037021c200241186a41004120102720022802182204200228022022056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002002200541206a2203360220200228021c2106200241086a20022802102003102720022802082205200228021022076a20042003101e1a2002200720036a220336021002402006450d00200410020b200228020c210442002108200241186a41086a220642003703002002420037031820052003200241186a1003200241086a41086a20062903003703002002200229031837030802400240200241086a411041d02d410041001000417f460d0020024200370318200241086a4110200241186a41084100100041016a41084d0d01200229031821080b02402004450d00200510020b4100210302402008427f510d002008102e560d002000104322082001540d00410810012203450d02200220033602182002420837021c200241186a4100410810272002280218200228022022036a42f3e885d3a3ac98b63a3700002002200341086a360220200241086a41086a200228022036020020022002290318370308412010012203450d02200820017d2108200220033602182002422037021c200241186a41004120102720022802182204200228022022056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002002200541206a2200360220200228021c2103200241086a20022802102000102720022802082205200228021022066a20042000101e1a2002200620006a220036021002402003450d00200410020b200228020c210420022008370328200241186a41086a220342003703002002420037031820052000200241186a1003200241086a41086a200329030037030020022002290318370308200241086a4110200241286a41081004410121032004450d00200510020b200241306a240020030f0b41c1214133102d000b101c000bf80301057f230041206b22022400024002400240410710012203450d002002200336021020024207370214200241106a4100410710272002280210200228021822046a220341002800d30f360000200241086a200441076a2204360200200341046a41002f00d70f3b0000200341066a41002d00d90f3a00002002200229031037030020022004360218412010012203450d002002200336021020024220370214200241106a41004120102720022802102204200228021822056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a220136021820022802142105200220022802082001102720022802002203200228020822066a20042001101e1a2002200620016a220136020802402005450d00200410020b20022802042104200241106a41086a220542003703002002420037031020032001200241106a1003200241086a20052903003703002002200229031037030041002101024002402002411041d02d410041001000417f460d00200241003602104101210120024110200241106a41044100100041016a41044d0d01200228021021052004450d040c030b20040d020c030b41c1214133102d000b101c000b200310020b2000200136020020002005360204200241206a24000b8806010a7f230041306b22022400024002400240024002400240024002400240410710012203450d00200220033602182002420737021c200241186a4100410710272002280218200228022022046a220341002800cc0f360000200241086a41086a200441076a2204360200200341046a41002f00d00f3b0000200341066a41002d00d20f3a00002002200229031837030820022004360220412010012203450d00200220033602182002422037021c200241186a41004120102720022802182204200228022022056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a2201360220200228021c2103200241086a20022802102001102720022802082206200228021022056a20042001101e1a2002200520016a220136021002402003450d00200410020b200228020c2107200241186a41086a220342003703002002420037031820062001200241186a1003200241086a41086a200329030037030020022002290318370308200241086a411041d02d410041001000417f460d01200241003602184100200241086a4110200241186a41044100100022012001417f461b220141034d0d0720022802182208417f4c0d082008450d022008100122090d030b101c000b200041003602082000420137020020070d020c030b410121090b2002200836021c200220093602182002410036022002402008450d002001410420014104491b2103200241206a210a41002101410021040340200241003a002f200241086a41102002412f6a41012003100041016a41014b220b450d04200441016a210420022d002f210502402001200228021c470d00200241186a1023200a2802002101200228021821090b2003200b6a2103200920016a20053a0000200a200141016a220136020020042008490d000b200228021821090b2009450d032000200229021c370204200020093602002007450d010b200610020b200241306a24000f0b200228021c450d00200910020b41c1214133102d000b1024000b990401057f230041206b220224000240410710012203450d002002200336021020024207370214200241106a4100410710272002280210200228021822046a220341002800bf10360000200241086a200441076a2204360200200341046a41002f00c3103b0000200341066a41002d00c5103a00002002200229031037030020022004360218412010012203450d002002200336021020024220370214200241106a41004120102720022802102204200228021822056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a220136021820022802142105200220022802082001102720022802002203200228020822066a20042001101e1a2002200620016a220136020802402005450d00200410020b20022802042104200241106a41086a220542003703002002420037031020032001200241106a1003200241086a20052903003703002002200229031037030041002101024002402002411041d02d410041001000417f460d002002410036021020024110200241106a41044100100041016a41044d0d01200228021021012002410036021020024110200241106a41044104100041016a41044d0d01200041086a200228021036020020002001360204410121010b2000200136020002402004450d00200310020b200241206a24000f0b41c1214133102d000b101c000b930503067f017e097f230041d0006b220224002002410036023020012001280208220341002001280200220420012802042205200241306a41042003100022032003417f461b2203410420034104491b6a220636020802400240024002400240200341034d0d0020022802302207ad42287e2208422088a70d042008a72203417f4c0d032003450d012003100122090d02101c000b20004100360200200241d0006a24000f0b410821090b20022007360204200220093602002002410036020802402007450d00200241306a41186a210a200241306a41106a210b4100210c4100210d034020024200370330200141086a220e410020042005200241306a41082006100022032003417f461b2203410820034108491b20066a220636020002400240200341074d0d0020022903302108200a4200370300200b4200370300200241306a41086a220f420037030020024200370330200e410020042005200241306a41202006100022032003417f461b2203412020034120491b20066a22063602002003411f4d0d00200d41016a210d200241106a41186a220e200a290300370300200241106a41106a2210200b290300370300200241106a41086a2211200f29030037030020022002290330370310200c2002280204470d0120021068200241086a280200210c200228020021090c010b2000410036020002402002280204450d00200910020b200241d0006a24000f0b2009200c41286c6a2203200837030020032002290310370308200341206a200e290300370300200341186a2010290300370300200341106a2011290300370300200241086a200c41016a220c360200200d2007490d000b0b20002002290300370200200041086a200241086a280200360200200241d0006a24000f0b105f000b105e000bf40403057f017e037f230041306b22012400200041086a28020021022001410036022820014201370320200141206a4100410410272001280220200128022822036a20023600002001200341046a360228200141086a220420012802283602002001200129032037030002400240024002402002450d0020002802002200200241286c6a21050340200141106a41086a220341003602002001420137031020002903002106200141106a41004108102720032003280200220241086a2207360200200220012802106a2006370000200141106a20074120102720032003280200220741206a22023602002007200128021022086a220341086a200041106a290000370000200341106a200041186a290000370000200341186a200041206a2900003700002003200041086a2900003700002002417f4c0d03024002402002450d002002100122030d010c060b410121030b200141206a41086a220741003602002001200236022420012003360220200141206a41002002102720072007280200220920026a22033602002009200128022022076a20082002101e1a2001280224210202402001280214450d00200810020b200120042802002003102720012802002209200428020022086a20072003101e1a2004200820036a220336020002402002450d00200710020b200041286a22002005470d000c020b0b20012802082103200128020021090b20012802042102200141206a41086a2200420037030020014200370320418f114107200141206a1003200141106a41086a200029030037030020012001290320370310200141106a411020092003100402402002450d00200910020b200141306a24000f0b1019000b101c000bb50201077f230041206b22022400200141086a28020021032002410036021820024201370310200241106a4100410410272002280210200228021822046a20033600002002200441046a360218200241086a2204200228021836020020022002290310370300024002402003450d00200128020021050340410110012201450d022002200136021020024201370214200241106a410041011027200241106a41086a22012001280200220641016a22013602002006200228021022076a20052d00003a00002002280214210620022004280200200110272002280200200428020022086a20072001101e1a2004200820016a36020002402006450d00200710020b200541016a21052003417f6a22030d000b0b20002002290300370200200041086a2004280200360200200241206a24000f0b101c000bd60c03047f047e017f230041f0006b210202400240024002400240024002400240024002400240024002400240024020012d002822034103714101460d0020034102470d01200141206a22032802002204450d0e20032004417f6a3602002001411c6a2d0000450d050c0e0b20012802102204450d01200141106a4100360200024020012802082203200128020c2205460d002004417f7321040340200241c8006a41206a200341206a290300370300200241c8006a41186a200341186a290300370300200241c8006a41106a200341106a290300370300200241c8006a41086a200341086a29030037030020022003290300370348200441016a2204450d072005200341286a2203470d000b200141086a20053602000b200042003703000f0b20012802102204450d01200141106a410036020020012802082203200128020c2205460d022004417f7321040340200241c8006a41206a200341206a290300370300200241c8006a41186a200341186a290300370300200241c8006a41106a200341106a290300370300200241c8006a41086a200341086a29030037030020022003290300370348200441016a2204450d062005200341286a2203470d000b200141086a20053602000c020b20012802082202200128020c460d06200141086a200241286a360200200041286a200241206a290300370300200041206a200241186a290300370300200041186a200241106a290300370300200041106a200241086a29030037030020002002290300370308200042013703000f0b20012802082203200128020c460d00200141086a200341286a360200200241206a200341206a290300370300200241186a200341186a290300370300200241106a200341106a290300370300200241086a200341086a290300370300200220032903003703000c040b200141286a41023a0000200141206a22032802002204450d0820032004417f6a3602002001411c6a2d0000450d050c080b200141186a22042802002203200141146a280200460d082004200341586a220336020020032903004200510d05200241c8006a41206a200341206a2903002206370300200241c8006a41186a200341186a2903002207370300200241c8006a41106a200341106a2903002208370300200241c8006a41086a200341086a2903002209370300200241086a22042008370300200241106a22052007370300200241186a220a20063703002002200329030037034820022009370300200041286a200141246a280200290300370300200041206a200a290300370300200041186a2005290300370300200041106a200429030037030020002002290300370308200042013703000f0b2000200229034837030820004201370300200141086a200341286a360200200041106a200241c8006a41086a290300370300200041186a200241c8006a41106a290300370300200041206a200241c8006a41186a290300370300200041286a200241c8006a41206a2903003703000f0b200141086a200341286a360200200241086a200241c8006a41086a290300370300200241106a200241c8006a41106a290300370300200241186a200241c8006a41186a290300370300200241206a200241c8006a41206a290300370300200220022903483703000b2000200229030037030820004201370300200041106a200241086a290300370300200041186a200241106a290300370300200041206a200241186a290300370300200041286a200241206a2903003703000f0b200042003703000f0b200141186a22042802002203200141146a280200460d022004200341586a220336020020032903004200510d01200241c8006a41206a200341206a2903002206370300200241c8006a41186a200341186a2903002207370300200241c8006a41106a200341106a2903002208370300200241c8006a41086a200341086a2903002209370300200241286a41086a22042008370300200241286a41106a22052007370300200241286a41186a220a20063703002002200329030037034820022009370328200041286a200141246a280200290300370300200041206a200a290300370300200041186a2005290300370300200041106a200429030037030020002002290328370308200042013703000f0b2001411c6a41013a0000200042003703000f0b2001411c6a41013a0000200042003703000f0b200042003703000f0b200042003703000b8c0204017f017e017f017e230041c0006b22022400102e2103200241086a220442003703002002420037030041f726410720021003200241306a41086a2004290300370300200220022903003703300240200241306a411041d02d410041001000417f460d00200242003703000240200241306a4110200241084100100041016a41084d0d0020022903002105200241286a200041286a290300370300200241206a200041206a290300370300200241186a200041186a290300370300200241106a200041106a290300370300200241086a200041086a29030037030020022000290300370300200520037c20022001103f200241c0006a24000f0b41c1214133102d000b41f4214122102d000bba0503047f017e087f230041e0006b22012400200141c0006a41086a220242003703002001420037034041f2224107200141c0006a1003200141086a2002290300370300200120012903403703000240024002402001411041d02d410041001000417f460d00200141003602400240410020014110200141c0006a41044100100022022002417f461b220341034d0d0020012802402204ad42287e2205422088a70d022005a72202417f4c0d03024002402002450d002002100122060d01101c000b410821060b200120043602142001200636021020014100360218024002402004450d002003410420034104491b2107200141c0006a41186a21084100210341002109034020014200370340410020014110200141c0006a41082007100022022002417f461b220241074d0d022001290340210520084200370300200141c0006a41106a220a4200370300200141c0006a41086a220b420037030020014200370340410020014110200141c0006a41202002410820024108491b20076a2207100022022002417f461b2202411f4d0d02200941016a21092002412020024120491b2102200141206a41186a220c2008290300370300200141206a41106a220d200a290300370300200141206a41086a220a200b29030037030020012001290340370320024020032001280214470d00200141106a106f200141106a41086a2802002103200128021021060b200220076a21072006200341286c6a2202200537030020022001290320370308200241206a200c290300370300200241186a200d290300370300200241106a200a290300370300200141106a41086a200341016a220336020020092004490d000b200128021021060b2006450d012000200129021437020420002006360200200141e0006a24000f0b2001280214450d00200610020b41c1214133102d000b41f4214122102d000b1064000b1065000bf40403057f017e037f230041306b22012400200041086a28020021022001410036022820014201370320200141206a4100410410272001280220200128022822036a20023600002001200341046a360228200141086a220420012802283602002001200129032037030002400240024002402002450d0020002802002200200241286c6a21050340200141106a41086a220341003602002001420137031020002903002106200141106a41004108102720032003280200220241086a2207360200200220012802106a2006370000200141106a20074120102720032003280200220741206a22023602002007200128021022086a220341086a200041106a290000370000200341106a200041186a290000370000200341186a200041206a2900003700002003200041086a2900003700002002417f4c0d03024002402002450d002002100122030d010c060b410121030b200141206a41086a220741003602002001200236022420012003360220200141206a41002002102720072007280200220920026a22033602002009200128022022076a20082002101e1a2001280224210202402001280214450d00200810020b200120042802002003102720012802002209200428020022086a20072003101e1a2004200820036a220336020002402002450d00200710020b200041286a22002005470d000c020b0b20012802082103200128020021090b20012802042102200141206a41086a220042003703002001420037032041f2224107200141206a1003200141106a41086a200029030037030020012001290320370310200141106a411020092003100402402002450d00200910020b200141306a24000f0b1019000b101c000b922305077f017e027f017e037f230041b0016b22022400200241003a005020012001280208220320012802002001280204200241d0006a41012003100041016a220341014b6a220436020802400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020034102490d0020022d0050220341074b0d03024020030e080005020404060703000b200241003a0050200141086a20042001280200200141046a280200200241d0006a41012004100041016a220341014b6a220436020020034102490d1e20022d00502203450d0a20034101470d1e200141046a280200210520024100360250200141086a4100200128020022062005200241d0006a41042004100022032003417f461b2207410420074104491b20046a2203360200200741034d0d1e20022802502208ad42187e2209422088a70d202009a72204417f4c0d1f2004450d1b20041001220a0d1c0c210b20004106360200200241b0016a24000f0b200241003a005041042107200141086a200420012802002205200141046a280200220b200241d0006a41012004100041016a220341014b6a220436020020034102490d1020022d0050220341034b0d10024020030e04000e0f10000b20024200370350200141086a41002005200b200241d0006a41082004100022012001417f461b2201410820014108491b20046a360200200141074d0d1020022903502109410121070c0f0b200241003a0050200141086a200420012802002207200141046a2802002205200241d0006a41012004100041016a220341014b6a220436020020034102490d0620022d00502203450d0420034101470d0620024200370350200141086a410020072005200241d0006a41082004100022012001417f461b2201410820014108491b20046a360200200141074d0d06200229035021094202210c0c050b20004106360200200241b0016a24000f0b200241003a0050200141086a200420012802002207200141046a2802002205200241d0006a41012004100041016a220341014b6a220436020020034102490d0820022d00502203450d0620034101470d08420221090c070b200241003a0050200141086a200420012802002207200141046a2802002205200241d0006a41012004100041016a220341014b6a220436020020034102490d1120022d00502203450d0820034101470d1120024100360250200141086a410020072005200241d0006a41042004100022012001417f461b2201410420014104491b20046a360200200141034d0d1120022802502103420221090c200b200241003a0050200141086a200420012802002207200141046a2802002205200241d0006a41012004100041016a220341014b6a2204360200024020034102490d004105210320022d0050220b41034b0d1d0240200b0e0400100e0f000b20024100360250200141086a410020072005200241d0006a41042004100022012001417f461b2201410420014104491b20046a360200200141034d0d1d20022802502101410121030c1f0b410521030c1c0b20024200370350200141086a410020072005200241d0006a41082004100022012001417f461b2201410820014108491b20046a360200200141074d0d01200229035021094201210c0b20004105360200200041086a200c370300200041106a2009370300200041186a2002290350370300200041206a200241d0006a41086a290300370300200041286a200241d0006a41106a290300370300200241b0016a24000f0b20004106360200200241b0016a24000f0b200141046a280200210320024100360250200141086a410020012802002003200241d0006a41042004100022032003417f461b2203410420034104491b20046a2204360200200341034d0d1320022802502203417f4c0d172003450d0e20031001220a450d16200a4100200310171a200141086a28020021040c0f0b20024200370350200141086a410020072005200241d0006a41082004100022012001417f461b22014108200141084922011b20046a36020020010d012002290350210c420121090b20004101360200200041086a2009370300200041106a200c370300200041186a2002290350370300200041206a200241d0006a41086a290300370300200041286a200241d0006a41106a290300370300200241b0016a24000f0b20004106360200200241b0016a24000f0b200241d0006a200110bd0120024180016a41086a2203200241dc006a29020037030020024180016a41106a2204200241e4006a29020037030020024180016a41186a2207200241ec006a29020037030020024180016a41206a2205200241f4006a29020037030020024180016a41286a220b200241fc006a2802003602002002200229025437038001200228025022064106460d08200241206a41286a220a200b280200360200200241206a41206a220b2005290300370300200241206a41186a22052007290300370300200241206a41106a22072004290300370300200241206a41086a220420032903003703002002200229038001370320200241d0006a41286a200a280200360200200241d0006a41206a200b290300370300200241d0006a41186a2005290300370300200241d0006a41106a2007290300370300200241d0006a41086a200429030037030020022002290320370350413010012203450d1220032002290350370204200320063602002003410c6a200241d0006a41086a290300370200200341146a200241e0006a2903003702002003411c6a200241e8006a290300370200200341246a200241f0006a2903003702002003412c6a200241f8006a28020036020020022003360208200241003a0050200141086a2204200428020022042001280200200141046a280200200241d0006a41012004100041016a41014b22016a3602002001450d0720022d0050220141034f0d07420121090c170b20024200370350200141086a41002005200b200241d0006a41082004100022012001417f461b2201410820014108491b20046a360200200141074d0d0220022903502109410221070c010b20024100360250200141086a41002005200b200241d0006a41042004100022012001417f461b2201410420014104491b20046a36020041032107200141034d0d01200228025021060b20004102360200200041086a20073602002000410c6a2006360200200041106a2009370200200041186a2002290350370300200041206a200241d0006a41086a290300370300200041286a200241d0006a41106a290300370300200241b0016a24000f0b20004106360200200241b0016a24000f0b20024200370350200141086a410020072005200241d0006a41082004100022012001417f461b2201410820014108491b20046a360200200141074d0d0f20022903502109410321030c100b20024200370350200141086a410020072005200241d0006a41082004100022012001417f461b2201410820014108491b20046a360200200141074d0d0e20022903502109410421030c0f0b200241d0006a41186a220b4200370300200241d0006a41106a22064200370300200241d0006a41086a220a420037030020024200370350200141086a410020072005200241d0006a41202004100022012001417f461b2201412020014120491b20046a3602002001411f4d0d0220024180016a41186a2201200b29030037030020024180016a41106a2203200629030037030020024180016a41086a2204200a2903003703002002200229035037038001200b200129030037030020062003290300370300200a20042903003703002002200229038001370350410221032002411c6a41026a220420022d00523a0000200241086a41086a2207200241e7006a290000370300200241086a41106a2205200241d0006a411f6a2d00003a0000200220022f01503b011c2002200229005f3703082002280053210120022900572109200241046a41026a20042d00003a0000200241206a41086a2007290300370300200241206a41106a20052d00003a0000200220022f011c3b0104200220022903083703200c0f0b200241086a10220b20004106360200200241b0016a24000f0b200b20024180016a41186a290000370300200620024180016a41106a290000370300200a20024180016a41086a29000037030020022002290080013703500c0a0b4101210a0b200141086a200341002001280200200141046a280200200a20032004100022012001417f461b2201200120034b1b20046a3602000240200320014d0d00200a10020c040b200a450d032003ad22094220862009842109410121010c020b4104210a0b200220083602542002200a3602502002410036025802402008450d00200141086a21044101210d4100210b03402002410036028001200441002006200520024180016a41042003100022072007417f461b2207410420074104491b20036a220f36020002400240200741034d0d002002280280012203417f4c0d09024002402003450d00200310012207450d0a20074100200310171a0c010b410121070b2004200341002006200520072003200f100022052005417f461b2205200520034b1b200f6a3602000240200320054b0d002007450d012003ad22094220862009842109200141046a220e28020021052004280200210320024100360280012004200341002001280200200520024180016a41042003100022052005417f461b2205410420054104491b6a22063602000240200541034d0d002002280280012203417f4c0d0b024002402003450d00200310012205450d0c20054100200310171a200428020021060c010b410121050b2004200341002001280200200e2802002005200320061000220f200f417f461b220f200f20034b1b20066a36020002402003200f4b0d002005450d012003ad220c422086200c84210c200b2002280254470d04200241d0006a1076200241d0006a41086a280200210b2002280250210a0c040b200510020b2009a7450d010b200710020b200228025021040240200b450d00200b41186c21032004210103400240200141046a280200450d00200128020010020b0240200141106a280200450d002001410c6a28020010020b200141186a2101200341686a22030d000b0b2002280254450d04200410020c040b0240200a200b41186c6a22032009370204200320073602002003410c6a2005360200200341106a200c370200200241d0006a41086a200b41016a220b360200200d20084f0d00200d41016a210d20042802002103200e2802002105200128020021060c010b0b2002280250210a0b200a450d0120022902542109410221010b2000200136020420004100360200200041086a200a3602002000410c6a2009370200200041146a20022902503702002000411c6a200241d0006a41086a290200370200200041246a200241e0006a2902003702002000412c6a200241e8006a280200360200200241b0016a24000f0b20004106360200200241b0016a24000f0b1061000b1060000b101c000b1019000b0b0b200241086a41026a2204200241046a41026a2d00003a0000200241d0006a41086a2207200241206a41086a290300370300200241d0006a41106a2205200241206a41106a290300370300200220022f01043b010820022002290320370350024020034105470d0020004106360200200241b0016a24000f0b2002411c6a41026a220b20042d00003a000020024180016a41086a2204200729030037030020024180016a41106a22072005290300370300200220022f01083b011c2002200229035037038001200041086a20033a0000200041043602002000410c6a2001360000200041106a2009370000200020022f011c3b00092000410b6a200b2d00003a0000200041186a200229038001370000200041206a2004290300370000200041286a2007290300370000200241b0016a24000f0b200041033602002000410c6a2002290250370200200041146a200241d8006a2902003702002000411c6a200241e0006a290200370200200041246a200241e8006a2902003702002000412c6a200241f0006a28020036020020002003ad422086200141ff0171ad42088684200984370204200241b0016a24000be60201047f230041206b22022400200241003602082002420137030020024100412010272002280200200228020822036a22042001290000370000200441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a2900003700002002200341206a2204360208200220044120102720022802002203200228020822056a22042001290020370000200441086a200141286a290000370000200441106a200141306a290000370000200441186a200141386a2900003700002002200541206a220136020802402001417f4c0d00024002402001450d002001100122040d01101c000b410121040b200220013602142002200436021020024100360218200241106a41002001102720022002280218220420016a360218200420022802106a20032001101e1a200041086a20022802183602002000200229031037020002402002280204450d00200310020b200241206a24000f0b1019000be70101037f0240024002402000280200220128020022024103460d0020020d0220012802042202450d0220024101470d012001410c6a280200450d02200141086a2802001002200028020010020f0b20012d00044101470d01200141086a10bf01200028020010020f0b0240200141106a2802002203450d00200141086a2802002102200341186c210303400240200241046a280200450d00200228020010020b0240200241106a280200450d002002410c6a28020010020b200241186a2102200341686a22030d000b0b2001410c6a280200450d00200141086a28020010020b200028020010020be00302057f017e230041206b220124000240410710012202450d002001200236021020014207370214200141106a4100410710272001280210200128021822036a220241002800d92e360000200141086a200341076a2203360200200241046a41002f00dd2e3b0000200241066a41002d00df2e3a00002001200129031037030020012003360218412010012202450d002001200236021020014220370214200141106a41004120102720012802102203200128021822046a22022000290000370000200241086a200041086a290000370000200241106a200041106a290000370000200241186a200041186a2900003700002001200441206a220036021820012802142104200120012802082000102720012802002202200128020822056a20032000101e1a2001200520006a220036020802402004450d00200310020b2001280204210342002106200141106a41086a220442003703002001420037031020022000200141106a1003200141086a200429030037030020012001290310370300024002402001411041d02d410041001000417f460d002001420037031020014110200141106a41084100100041016a41084d0d01200129031021060b02402003450d00200210020b200141206a240020060f0b41c1214133102d000b101c000bd14b05067f017e057f047e047f230041a0076b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d00002203417f6a220441054b0d0002400240024002400240024020040e06000402030105000b200241f8006a41086a22042000410a6a290000370300200241f8006a41106a2205200041126a290000370300200241f8006a41186a22062000411a6a2900003703002002200041026a29000037037820002d0001450d21200241d8036a41186a2006290300370300200241d8036a41106a2005290300370300200241d8036a41086a2004290300370300200220022903783703d803410810012204450d43200220043602582002420837025c200241d8006a4100410810272002280258200228026022046a42f3cacdd3e38d9eba3a3700002002200441086a360260200241206a41086a200228026036020020022002290358370320412010012204450d43200220043602582002422037025c200241d8006a41004120102720022802582205200228026022066a22042001290000370000200441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a2900003700002002200641206a2201360260200228025c2106200241206a20022802282001102720022802202204200228022822076a20052001101e1a2002200720016a220136022802402006450d00200510020b20022802242105200241d8006a41086a220642003703002002420037035820042001200241d8006a1003200241c0006a41086a200629030037030020022002290358370340200241c0006a4110200241d8036a412010042005450d38200410020c380b200241d8036a41286a200041306a290300370300200241d8036a41206a200041286a290300370300200241d8036a41186a200041206a290300370300200241d8036a41106a200041186a290300370300200241d8036a41086a200041106a2903003703002002200041086a2903003703d803200241d8036a200110ae0141002101410121040c400b200041086a2903004200510d20200041106a2903002108200241f0036a4200370300200241d8036a41106a4200370300200241d8036a41086a4200370300200242003703d8030240200241d8036a2001460d002001200241d8036a412010060d270b200241d8006a41086a220142003703002002420037035841ad0b4107200241d8006a1003200241c0006a41086a2204200129030037030020022002290358370340200241c0006a411020024190076a410041001000417f470d21200142003703002002420037035841ed2d4107200241d8006a10032004200129030037030020022002290358370340200241c0006a411041d02d410041001000417f460d22200241003602d803200241c0006a4110200241d8036a41044100100041016a41044d0d1a20022802d8030d23200220083703d803200241d8006a41086a220142003703002002420037035841a90c4107200241d8006a1003200241c0006a41086a2205200129030037030020022002290358370340200241c0006a4110200241d8036a4108100441012104200241013a00d803200142003703002002420037035841ad0b4107200241d8006a10032005200129030037030020022002290358370340200241c0006a4110200241d8036a410110040c370b200241086a2205200041106a2903003703002002200041086a29030037030020022d000022044103714101460d0520044102460d0320044103470d2320022d0001210920022802042105410810012206450d40200220063602d803200242083702dc03200241d8036a41004108102720022802d80320022802e00322066a42e4cab5d383cedcb73a3700002002200641086a3602e003200241f8006a41086a20022802e003360200200220022903d803370378410410012206450d40200220063602d803200242043702dc03200241d8036a41004104102720022802d803220720022802e00322066a20053600002002200641046a22063602e00320022802dc03210a200241f8006a200228028001200610272002280278220b200228028001220c6a20072006101e1a2002200c20066a2206360280010240200a450d00200710020b200228027c2107200241d8006a41086a220a420037030020024200370358200b2006200241d8006a1003200241c0006a41086a200a29030037030020022002290358370340200241c0006a411020024190076a410041001000210602402007450d00200b10020b2006417f460d2620011043210820011044420020087d510d27200241e4036a200141086a290000370200200241ec036a200141106a290000370200200241f4036a200141186a290000370200200220053602d803200220012900003702dc03410810012206450d40200220063602782002420837027c200241f8006a410041081027200228027820022802800122066a42e4cab5d3e3ee9bba3a3700002002200641086a36028001200241d8006a41086a220620022802800136020020022002290378370358200241f8006a200241d8036a1045200228027c210c2002280278210b200241d8006a2006280200200228028001220710272002280258220a2006280200220d6a200b2007101e1a2006200d20076a22073602000240200c450d00200b10020b200228025c2106200241d8006a41086a220b420037030020024200370358200a2007200241d8006a1003200241c0006a41086a200b29030037030020022002290358370340200241c0006a411020024190076a410041001000210702402006450d00200a10020b2007417f470d3a20024190076a20051042200241d8036a41186a2207200141186a290000370300200241d8036a41106a220b200141106a290000370300200241d8036a41086a220a200141086a290000370300200220012900003703d8032002280298072206200228029407460d170c390b200241086a2204200041116a290000370300200241106a2205200041196a290000370300200241186a2206200041216a2900003703002002200041096a290000370300200041086a2d000041037122034101460d0520034103460d0320034102470d23200241d8006a41086a220342003703002002420037035841d61d4108200241d8006a1003200241c0006a41086a200329030037030020022002290358370340200241c0006a411041d02d410041001000417f460d122002421037027c2002200241c0006a360278200241d8036a200241f8006a103a20022802d8032206450d27200220022902dc0322083702242002200636022020062008422088a7220741057422036a210520034105754104490d06200621040340200120042203460d182003200141201006450d18200341206a22042001460d182004200141201006450d18200441206a22042001460d182004200141201006450d18200441206a22042001460d182004200141201006450d182005200441206a22046b41057541034b0d000b20034180016a22032005470d070c080b200241f8036a200041246a280200360200200241f0036a2000411c6a290200370300200241e8036a200041146a290200370300200241e0036a2000410c6a2902003703002002200041046a2902003703d803200241d8036a200110db014100210541012104410121010c3d0b200041106a2d00004102470d32419cc200103b000b200241d8036a20022802042205103720022802e003450d25200241d8006a41106a2206200241d8036a41106a290300370300200241d8006a41086a200241d8036a41086a290300370300200220022903d8033703582001200229035810b201450d26200241f8006a41186a2207200141186a290000370300200241f8006a41106a200141106a290000370300200241f8006a41086a200141086a2900003703002002200129000037037820062802002201200241e4006a280200460d110c340b200241d8006a41086a220342003703002002420037035841d61d4108200241d8006a1003200241c0006a41086a2003290300370300200220022903583703404100210b200241c0006a411041d02d410041001000417f460d052002421037027c2002200241c0006a360278200241d8036a200241f8006a103a20022802d8032205450d2c2005200241e0036a280200220941057422036a210720022802dc03210b20034105754104490d0620052106410021030340200120062204460d0a2003200420014120100622064100476a21032006450d0a200441206a22062001460d0a20032006200141201006220a4100476a2103200a450d0a200641206a22062001460d0a20032006200141201006220a4100476a2103200a450d0a200641206a22062001460d0a20032006200141201006220a4100476a2103200a450d0a2007200641206a22066b41057541034b0d000b20044180016a22042007470d070c080b20052903002108200220022802042206360220200241d8006a41086a220442003703002002420037035841a2294107200241d8006a1003200241c0006a41086a200429030037030020022002290358370340200241c0006a411041d02d410041001000417f460d25200242003703d803200241c0006a4110200241d8036a41084100100041016a41084d0d1420022903d8032008560d262001200810b201450d27200241d8006a41086a220442003703002002420037035841a9294107200241d8006a1003200241c0006a41086a200429030037030020022002290358370340410021050240200241c0006a411041d02d410041001000417f460d00200241003602d803200241c0006a4110200241d8036a41044100100041016a41044d0d1820022802d80321050b2002200541016a3602d803200241d8006a41086a220442003703002002420037035841a9294107200241d8006a1003200241c0006a41086a200429030037030020022002290358370340200241c0006a4110200241d8036a41041004412010012204450d3a200241e4036a428180808010370200200141086a2207290000210e200141106a220b290000210f20012900002110200441186a200141186a220a290000370000200441106a200f370000200441086a200e37000020042010370000200220083703d803200220043602e0032005200241d8036a10df01200241d8006a1036200241d8036a200610e001200241f8006a41186a2206200a290000370300200241f8006a41106a200b290000370300200241f8006a41086a20072900003703002002200129000037037820022802602204200228025c460d100c310b200041306a2903002108200241206a41186a2006290300370300200241206a41106a2005290300370300200241206a41086a20042903003703002002200229030037032041d02d200110c60122112008540d2741d02d200241206a10c601210e410810012203450d39200220033602d803200242083702dc03200241d8036a41004108102720022802d80320022802e00322036a42f3e885d3a3ec9bb73a3700002002200341086a3602e003200241f8006a41086a20022802e003360200200220022903d803370378412010012203450d39200220033602d803200242203702dc03200241d8036a41004120102720022802d803220420022802e00322056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a22033602e00320022802dc032106200241f8006a200228028001200310272002280278220520022802800122076a20042003101e1a2002200720036a22033602800102402006450d00200410020b200228027c21044200210f200241d8006a41086a220642003703002002420037035820052003200241d8006a1003200241c0006a41086a2006290300370300200220022903583703400240200241c0006a411041d02d410041001000417f460d00200242003703d803200241c0006a4110200241d8036a41084100100041016a41084d0d1520022903d803210f0b02402004450d00200510020b410810012203450d39200220033602d803200242083702dc03200241d8036a41004108102720022802d80320022802e00322036a42f3e885d3a3ec9bb73a3700002002200341086a3602e003200241f8006a41086a20022802e003360200200220022903d803370378412010012203450d39200220033602d803200242203702dc03200241d8036a41004120102720022802d803220420022802e00322056a22032002290320370000200341086a200241206a41086a290300370000200341106a200241206a41106a290300370000200341186a200241206a41186a2903003700002002200541206a22033602e00320022802dc032106200241f8006a200228028001200310272002280278220520022802800122076a20042003101e1a2002200720036a22033602800102402006450d00200410020b200228027c210442002110200241d8006a41086a220642003703002002420037035820052003200241d8006a1003200241c0006a41086a2006290300370300200220022903583703400240200241c0006a411041d02d410041001000417f460d00200242003703d803200241c0006a4110200241d8036a41084100100041016a41084d0d1620022903d80321100b02402004450d00200510020b200f2010560d28200e20087c220f200e580d2941a00610012203450d392003200241d8036a41b803101e220341003b01be03200341003602b803200341c0036a200241f8006a41e002101e1a200241c8006a4200370300200241d4006a41d43c3602002002200336024420024100360240200241d02d360250200241206a2001460d0b2001200241206a41201006450d0b2002417f360240200241d8036a41186a2207200141186a290000370300200241d8036a41106a220b200141106a290000370300200241d8036a41086a220a200141086a290000370300200220012900003703d8032002200241c0006a41047222043602602002200241c0006a41086a2802003602582002200228024436025c200241f8006a200241d8006a200241d8036a10970141012103200241f8006a41106a2802002105200241f8006a410c6a2802002109200241f8006a41086a2802002106200228027c210c024020022802784101470d00200241d8006a41186a2007290300370300200241d8006a41106a200b290300370300200241d8006a41086a200a290300370300200220022903d803370358410021030b41900210012201450d39201120087d21082001200241d8036a418802101e220141003b018e0220014100360288022003450d09200220013602782002420037027c2006200541286c6a2101200241d8036a200241f8006a109801200241d8036a1099010c0a0b200622032005460d010b200620074105746a2104034020012003460d102003200141201006450d102004200341206a2203470d000b0b200241d8036a41186a200141186a290000370300200241d8036a41106a200141106a290000370300200241d8036a41086a200141086a290000370300200220012900003703d803200241d8036a210320072008a7460d0a0c290b41012105410021094100210341000d270c040b41002103200522042007460d010b034020012004460d022003200420014120100622064100476a21032006450d022007200441206a2204470d000b0b4100450d010c240b41010d230b41dc3b103b000b200241f4036a200241e0006a290300370200200241fc036a200241e8006a29030037020020024184046a200241f0006a290300370200200220063602dc032002200c3602d803200220093602e003200220053602e4032002200241c0006a410c6a3602e803200220022903583702ec0320024198016a42003703002002410036028801200242003703782002200136029401200241d8036a200241f8006a109a0121010b20014201370300200120083703082002417f360240200241d8036a41186a2201200241206a41186a290300370300200241d8036a41106a2206200241206a41106a290300370300200241d8036a41086a2207200241206a41086a290300370300200220022903203703d803200220043602602002200241c0006a41086a2802003602582002200228024436025c200241f8006a200241d8006a200241d8036a10970141012103200241f8006a41106a2802002104200241f8006a410c6a280200210b200241f8006a41086a2802002105200228027c210a024020022802784101470d00200241d8006a41186a2001290300370300200241d8006a41106a2006290300370300200241d8006a41086a2007290300370300200220022903d803370358410021030b41900210012201450d2e2001200241d8036a418802101e220141003b018e022001410036028802024002402003450d00200220013602782002420037027c2005200441286c6a2101200241d8036a200241f8006a109801200241d8036a1099010c010b200241f4036a200241e0006a290300370200200241fc036a200241e8006a29030037020020024184046a200241f0006a290300370200200220053602dc032002200a3602d8032002200b3602e003200220043602e4032002200241c0006a410c6a3602e803200220022903583702ec0320024198016a42003703002002410036028801200242003703782002200136029401200241d8036a200241f8006a109a0121010b200142013703002001200f370308200241003602400b200241d8036a200241c0006a200241206a109b010240024020022802e0032201450d0020022802d80322032001200241206a200241c0006a108e01450d010b200241c8006a290300210820022802442101024020022802dc03450d0020022802d80310020b2001450d22200220083702dc03200220013602d80320024190076a200241d8036a10c7010c220b200241c0006a4104722101024020022802dc03450d00200310020b200241f8006a41086a200141086a28020036020020022001290200370378200241d8036a200241f8006a109d01200241d8036a109e010c210b2002410036022820024201370320200241d8036a41186a200141186a290000370300200241d8036a41106a200141106a290000370300200241d8036a41086a200141086a290000370300200220012900003703d803200241d8036a21030b200241206a107c200241286a2802002107200228022021060c1e0b200241e0006a107c200241e8006a28020021010c220b200241d8006a1074200241e0006a28020021040c200b20024190076a107c20024190076a41086a28020021060c210b41c43b103b000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b41c1214133102d000b418431103b000b41dc32103b000b418c33103b000b41f4214122102d000b41a433103b000b419cc000103b000b41f43b103b000b41f432103b000b41fcc000103b000b4194c100103b000b41c1214133102d000b41b0294124102d000b41e4c000103b000b41f4214122102d000b41b4c000103b000b41ccc000103b000b418c3c103b000b41a43c103b000b41bc3c103b000b41c1214133102d000b200241d8036a41186a2206200520034105746a220341186a2207290000370300200241d8036a41106a220a200341106a220c290000370300200241d8036a41086a220d200341086a2212290000370300200220032900003703d80320052009417f6a22094105746a22042900002108200441086a2213290000210e200441106a2214290000210f2007200441186a2215290000370000200c200f3700002012200e37000020032008370000200420022903d8033700002013200d2903003700002014200a290300370000201520062903003700002002200b36027c200220053602782002200936028001200241d8036a200241f8006a10a20120022802e003210420022802d8032103200241d8006a41086a220642003703002002420037035841d61d4108200241d8006a1003200241c0006a41086a200629030037030020022002290358370340200241c0006a4110200320041004024020022802dc03450d00200310020b0240200b450d00200510020b200241d8006a41086a220342003703002002420037035841c81d4107200241d8006a1003200241c0006a41086a20032903003703002002200229035837034002400240200241c0006a411041d02d410041001000417f460d00200242003703d80302400240200241c0006a4110200241d8036a41084100100041016a41084d0d0020022903d8032108200241d8006a41086a220342003703002002420037035841d21e4107200241d8006a1003200241c0006a41086a200329030037030020022002290358370340200241c0006a411041d02d410041001000417f460d03200242003703d803200241c0006a4110200241d8036a41084100100041016a41084d0d01200120022903d80320087c10c5010c050b41c1214133102d000b41c1214133102d000b41f4214122102d000b41f4214122102d000b200341086a2900002108200341106a290000210e200341186a290000210f200620074105746a22042003290000370000200441186a200f370000200441106a200e370000200441086a2008370000200241206a41086a2203200741016a360200200241f8006a41086a200328020036020020022002290320370378200241d8036a200241f8006a10a20120022802e003210420022802d8032103200241d8006a41086a220542003703002002420037035841d61d4108200241d8006a1003200241c0006a41086a200529030037030020022002290358370340200241c0006a4110200320041004024020022802dc03450d00200310020b0240200228027c450d00200228027810020b2001427f10c5010b20002d000021030b410121040b410121010c070b2002280258200441d8006c6a220120022903d8033703002001200536023020012002290378370234200141086a200241d8036a41086a2205290300370300200141106a200241d8036a41106a290300370300200141186a200241d8036a41186a290300370300200141206a200241d8036a41206a290300370300200141286a200241d8036a41286a2903003703002001413c6a200241f8006a41086a290300370200200141c4006a200241f8006a41106a290300370200200141cc006a2006290300370200200241d8006a41086a2201200441016a36020020052001280200360200200220022903583703d803200241d8036a103e20022802d8032106024020052802002201450d00200141d8006c210420062101034020011038200141d8006a2101200441a87f6a22040d000b0b024020022802dc03450d00200610020b200241206a10220c050b200241d8006a41106a2206200141016a360200200241d8006a41086a220b28020020014105746a22012002290378370000200141086a200241f8006a41086a290300370000200141106a200241f8006a41106a290300370000200141186a2007290300370000200241d8036a41106a2006290300370300200241d8036a41086a200b290300370300200220022903583703d8032005200241d8036a10df010c020b20024190076a41086a220c200641016a360200200a2903002108200b290300210e2007290300210f20022802900720064105746a220620022903d803370000200641186a200f370000200641106a200e370000200641086a2008370000200241206a41086a200c2802003602002002200229039007370320410810012206450d06200220063602d803200242083702dc03200241d8036a41004108102720022802d80320022802e00322066a42e4cab5d3e38e9db93a3700002002200641086a3602e003200241f8006a41086a20022802e003360200200220022903d803370378410410012206450d06200220063602d803200242043702dc03200241d8036a41004104102720022802d803220720022802e00322066a20053600002002200641046a22063602e00320022802dc03210a200241f8006a200228028001200610272002280278220b200228028001220c6a20072006101e1a2002200c20066a220c360280010240200a450d00200710020b200228027c2107200241d8036a200241206a10a20120022802e003210a20022802d8032106200241d8006a41086a220d420037030020024200370358200b200c200241d8006a1003200241c0006a41086a200d29030037030020022002290358370340200241c0006a41102006200a1004024020022802dc03450d00200610020b02402007450d00200b10020b2002280224450d00200228022010020b200241e4036a200141086a290000370200200241ec036a200141106a290000370200200241f4036a200141186a290000370200200220053602d803200220012900003702dc03200220093a0020410810012201450d05200220013602782002420837027c200241f8006a410041081027200228027820022802800122016a42e4cab5d3e3ee9bba3a3700002002200141086a36028001200241d8006a41086a220120022802800136020020022002290378370358200241f8006a200241d8036a1045200228027c210b20022802782106200241d8006a200128020020022802800122051027200228025822072001280200220a6a20062005101e1a2001200a20056a22053602000240200b450d00200610020b200228025c2101200241d8006a41086a220642003703002002420037035820072005200241d8006a1003200241c0006a41086a200629030037030020022002290358370340200241c0006a4110200241206a410110042001450d002007100220044101460d010c020b20044101470d010b200241047210220b41012101410021040b410121050b2003411d74411d75417f4a0d0102400240200341077122034104460d0020034105470d012001450d03200041086a2d00004101470d03200041106a280200450d032000410c6a2802001002200241a0076a24000f0b2004450d02200041086a2d00004101470d022000410c6a104b200241a0076a24000f0b2005450d01200041046a2d00004101470d01200041086a104b200241a0076a24000f0b101c000b200241a0076a24000b080041ec3a1054000b080041ec3a1054000bfe2507097f027e0a7f027e067f017e0d7f230041d0026b220424000240024020014115490d0041012105410121060240024002400340200620057121070340024002402003450d0020054101710d012000200110e1012003417f6a21030c010b2000200110e201200441d0026a24000f0b2001410276220641036c2108200641017421094100210a024020014132490d0020082008417f6a220b2000200841286c6a220c41586a290300220d200c290300220e54220a1b220f200841016a200b2008200a1b200d200e200a1b220d200c41286a290300220e5422101b2000200f41286c6a290300200e200d20101b5422111b210820092009417f6a220c2000200941286c6a220b41586a290300220d200b290300220e54220b1b22122009410172220f200c2009200b1b200d200e200b1b220d2000200f41286c6a290300220e54220f1b2000201241286c6a290300200e200d200f1b5422131b210920062006417f6a22142000200641286c6a221241586a290300220d2012290300220e54220c1b2215200641016a20142006200c1b200d200e200c1b220d201241286a290300220e5422121b2000201541286c6a290300200e200d20121b5422141b210641024101200c1b200c20121b20146a200b6a200f6a20136a200a6a20106a20116a210a0b200a2000200641286c6a290300220d2000200941286c6a290300220e54220c6a200d200e200c1b220d2000200841286c6a290300220e54220b6a210a0240024002400240200020092006200c1b221641286c6a290300200e200d200b1b5a0d00200a41016a220a410b4b0d012007200a45714101470d030c020b200820062009200c1b200b1b21162007200a45714101470d020c010b2001417f6a2117024020014101762208450d002000200141286c6a41586a2106200021090340200441a8016a41206a220c200941206a220a290300370300200441a8016a41186a220b200941186a2210290300370300200441a8016a41106a220f200941106a2212290300370300200441a8016a41086a2211200941086a2213290300370300200420092903003703a801200641086a2214290300210d200641106a2215290300210e200641186a221829030021192006290300211a200a200641206a221b290300370300201020193703002012200e3703002013200d3703002009201a370300201b200c2903003703002018200b2903003703002015200f29030037030020142011290300370300200620042903a801370300200941286a2109200641586a21062008417f6a22080d000b0b201720166b211620074101714101470d010b2000200110e3010d070b024002400240024002402002450d00201620014f0d092000201641286c6a22062903002002290300540d00200441a8016a41206a220a200041206a2212290300370300200441a8016a41186a220b200041186a2211290300370300200441a8016a41106a2210200041106a2213290300370300200441a8016a41086a220f200041086a2209290300370300200420002903003703a801200641086a2208290300210d200641106a220c290300210e200641186a221429030021192006290300211a2012200641206a2215290300370300201120193703002013200e3703002009200d3703002000201a3703002015200a2903003703002014200b290300370300200c20102903003703002008200f290300370300200620042903a8013703002000290300210d200441086a41186a221c2012290300370300200441086a41106a221d2011290300370300200441086a41086a221e201329030037030020042009290300370308200041286a21144100210841002001417f6a22094f0d010c020b201620014f0d07200441a8016a41206a2224200041206a2205290300370300200441a8016a41186a2225200041186a2226290300370300200441a8016a41106a2227200041106a2228290300370300200441a8016a41086a2229200041086a222a290300370300200420002903003703a8012000201641286c6a2206290300210d200641086a2209290300210e200641106a22082903002119200641186a220c290300211a2005200641206a220a2903003703002026201a37030020282019370300202a200e3703002000200d370300200a2024290300370300200c20252903003703002008202729030037030020092029290300370300200620042903a8013703002000290300210d200441086a41186a222b2005290300370300200441086a41106a222c2026290300370300200441086a41086a222d20282903003703002004202a2903003703082001417f6a210941002120200041286a2208210602400340200d20062903005a0d01200641286a2106202041016a22202009490d000b0b200921070240200920204d0d002000200141286c6a41586a2106200921070340200d2006290300540d01200641586a21062007417f6a220720204b0d000b0b20072020490d0620092007490d032008200741286c6a210b41800121164100210a410021154100210c4100211441800121172008202041286c6a222e21180340200b20186b220641286e21090240024002400240024002400240200641a7d0004b221f0d00200941807f6a20092015200a492014200c4922087222101b21062010450d012017200620081b21172006201620081b21160b2014200c470d020c010b2006200641017622176b21162014200c470d010b2017450d0141002106200441286a2214210c201821090340200c20063a0000200c200d20092903005a6a210c200941286a2109200641016a22062017490d000b0b2015200a470d020c010b200441286a220c21142015200a470d010b02402016450d00200b41586a210641002109200441a8016a2215210a0340200a20093a0000200a200d2006290300546a210a200641586a2106200941016a22092016490d000c020b0b200441a8016a220a21150b0240200a20156b2206200c20146b2209200920064b1b221b450d00200441a8026a41206a2222201820142d000041286c6a220641206a290300370300200441a8026a41186a221c200641186a290300370300200441a8026a41106a221d200641106a290300370300200441a8026a41086a221e200641086a290300370300200420062903003703a802201820142d000041286c6a2206200b20152d00002210417f7341286c6a2209290300370300200641206a200941206a290300370300200641186a200941186a290300370300200641106a200941106a290300370300200641086a200941086a2903003703000240201b4101460d00410021080340200b2010417f7341807e7241286c6a22092018201420086a41016a2d000041286c6a2206290300370300200941206a200641206a220f290300370300200941186a200641186a2212290300370300200941106a200641106a2211290300370300200941086a200641086a22132903003703002006200b201520086a41016a2d00002210417f7341286c6a2209290300370300200f200941206a2903003703002012200941186a2903003703002011200941106a2903003703002013200941086a290300370300200841026a2106200841016a220f21082006201b490d000b2015200f6a21152014200f6a21140b200920042903a802370300200941206a2022290300370300200941186a201c290300370300200941106a201d290300370300200941086a201e290300370300201541016a2115201441016a21140b2018201741286c6a20182014200c461b2118200b410020166b41286c6a200b2015200a461b210b201f0d000b024002402014200c4f0d00200b41586a2106200c21080340200441a8026a41206a220a20182008417f6a22082d000041286c6a220941206a2210290300370300200441a8026a41186a220f200941186a2212290300370300200441a8026a41106a2211200941106a2213290300370300200441a8026a41086a2215200941086a221b290300370300200420092903003703a802200641086a2216290300210e200641106a22172903002119200641186a221f290300211a200629030021212010200641206a22222903003703002012201a37030020132019370300201b200e370300200920213703002022200a290300370300201f200f2903003703002017201129030037030020162015290300370300200620042903a802370300200641586a210620142008490d000b200b2014200c6b41286c6a21180c010b20182106200a21082015200a4f0d0003402008417f6a22082d00002109200441a8026a41206a220c200641206a2210290300370300200441a8026a41186a220f200641186a2212290300370300200441a8026a41106a2211200641106a2213290300370300200441a8026a41086a2214200641086a221b290300370300200420062903003703a802200b2009417f7341286c6a2209290300210e200941086a22162903002119200941106a2217290300211a200941186a221f29030021212010200941206a2222290300370300201220213703002013201a370300201b20193703002006200e3703002022200c290300370300201f200f2903003703002017201129030037030020162014290300370300200920042903a802370300200641286a210620152008490d000b2018200a20156b41286c6a21180b2000200d3703002005202b2903003703002026202c2903003703002028202d290300370300200020042903083703080240024020012018202e6b41286e20206a22094d0d002024200529030037030020252026290300370300202720282903003703002029202a290300370300200420002903003703a8012000200941286c6a2206290300210d200641086a2208290300210e200641106a220c2903002119200641186a220a290300211a2005200641206a220b2903003703002026201a37030020282019370300202a200e3703002000200d370300200b2024290300370300200a2025290300370300200c202729030037030020082029290300370300200620042903a801370300200120096b2208450d0120082009200920084b1b210c2001410376210a200641286a210b0240024020092008417f6a22014f0d00200020092002200310c40120062102200b21000c010b200b20012006200310c401200921010b200c200a4f2105200720204d2106200141154f0d070c0b0b41b4c20020092001103c000b41c4c200103b000b410021230c010b410621230b03400240024002400240024002400240024002400240024002400240024002400240024020230e0a04080905060001020307070b200a2014200841286c6a220c41206a2215290300370300200b200c41186a22182903003703002010200c41106a221b290300370300200f200c41086a22162903003703002004200c2903003703a801200641086a2217290300210e200641106a221f2903002119200641186a2220290300211a200629030021212015200641206a22222903003703002018201a370300201b20193703002016200e370300200c20213703002022200a2903003703002020200b290300370300201f20102903003703002017200f290300370300200620042903a801370300200841016a22082009417f6a22094f0d0d410621230c100b2014200841286c6a2106410721230c0f0b2006290300200d540d0a410821230c0e0b200641286a2106200841016a22082009490d08410021230c0d0b200820094f0d06410321230c0c0b2000200941286c6a2106410421230c0b0b2006290300200d5a0d09410921230c0a0b200641586a210620082009417f6a2209490d07410121230c090b2000200d3703002012201c2903003703002011201d2903003703002013201e290300370300200020042903083703082001200841016a2206490d01410221230c080b2000200641286c6a2100200120066b220141154f0d090c0e0b200620011055000b410121230c050b410721230c040b410021230c030b410021230c020b410421230c010b410521230c000b0b0b0b200720091029000b202020071055000b41b4c20020162001103c000b41dcc20020162001103c000b20014102490d002000210a410121090340200941016a210c02402000200941286c6a220641586a22082903002006290300220d5a0d00200441086a41186a2210200641206a220b290300370300200441086a41106a220f200641186a2212290300370300200441086a41086a2211200641106a22132903003703002004200629030837030820062008290300370300200641086a200841086a2903003703002013200841106a2903003703002012200841186a290300370300200b200841206a2903003703004100210b0240024002402009417f6a2208450d00200a21060340200641586a2209290300200d5a0d02200641206a200641786a290300370300200641186a200641706a290300370300200641106a200641686a290300370300200641086a200641606a29030037030020062009290300370300200921062008417f6a22080d000b200921060c020b2000200841286c6a21060c010b2008210b0b2006200d3703002000200b41286c6a22062004290308370308200641206a2010290300370300200641186a200f290300370300200641106a20112903003703000b200a41286a210a200c2109200c2001490d000b0b200441d0026a24000b9a0301057f230041306b220224000240410810012203450d002002200336022020024208370224200241206a4100410810272002280220200228022822036a42f3e885d3a3ec9bb73a3700002002200341086a360228200241106a41086a200228022836020020022002290320370310412010012203450d002002200336022020024220370224200241206a41004120102720022802202204200228022822056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002002200541206a220036022820022802242105200241106a20022802182000102720022802102203200228021822066a20042000101e1a2002200620006a220036021802402005450d00200410020b2002280214210420022001370308200241206a41086a220542003703002002420037032020032000200241206a1003200241106a41086a200529030037030020022002290320370310200241106a4110200241086a4108100402402004450d00200310020b200241306a24000f0b101c000bc70302057f017e230041206b220224000240410810012203450d002002200336021020024208370214200241106a4100410810272002280210200228021822036a42f3e885d3a3ac98b63a3700002002200341086a360218200241086a200228021836020020022002290310370300412010012203450d002002200336021020024220370214200241106a41004120102720022802102204200228021822056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a220136021820022802142105200220022802082001102720022802002203200228020822066a20042001101e1a2002200620016a220136020802402005450d00200410020b2002280204210442002107200241106a41086a220542003703002002420037031020032001200241106a1003200241086a200529030037030020022002290310370300024002402002411041d02d410041001000417f460d002002420037031020024110200241106a41084100100041016a41084d0d01200229031021070b02402004450d00200310020b200241206a240020070f0b41c1214133102d000b101c000ba11105027f017e0e7f017e0b7f230041b0036b2202240020024188016a41086a2203200141086a2802003602002002200129020037038801200241086a20024188016a109d01200241306a41206a200241086a41206a280200360200200241306a41186a200241086a41186a290300370300200241306a41106a200241086a41106a290300370300200241306a41086a200241086a41086a2903003703002002200229030837033020024188016a200241306a10c8010240024020022903a80122044202510d00200241f0016a4104722105200241c0016a210620024188016a41206a2107200241b0016a2108200241b8016a2109200241bc016a210a20024194016a210b2002419c016a210c200241ac016a210d0340200241e8006a41186a220120024188016a41186a220e290300370300200241e8006a41106a220f20024188016a41106a2210290300370300200241e8006a41086a22112003290300370300200241d8006a41086a2212200641086a2903003703002002200229038801370368200220062903003703582008290300211320092802002114200a2802002115200241d0016a41186a22162001290300370300200241d0016a41106a2217200f290300370300200241d0016a41086a22182011290300370300200220022903683703d001200241f0016a41086a2012290300370300200220022903583703f001024020044201520d00410810012201450d0320022001360288012002420837028c0120024188016a41004108102720032003280200220141086a36020020012002280288016a42f3e885d3a3ac98b63a370000200241a8026a41086a2201200328020036020020022002290388013703a80241201001220f450d032002200f360288012002422037028c0120024188016a41004120102720032003280200221141206a220f360200201120022802880122126a221120022903d001370000201141086a2018290300370000201141106a2017290300370000201141186a2016290300370000200228028c012119200241a8026a2001280200200f102720022802a80222112001280200221a6a2012200f101e1a2001201a200f6a220f36020002402019450d00201210020b20022802ac022101200220133703880120024190036a41086a2212420037030020024200370390032011200f20024190036a100320024180036a41086a201229030037030020022002290390033703800320024180036a411020024188016a410810042001450d00201110020b024002402014450d00200320022802f0013602002002201536028c012002201436028801200241d0016a20024188016a10c9014101211b2015450d01201410020c010b4100211b0b2003200541086a280200360200200220052902003703880120024180026a20024188016a109801200241a8026a41206a20024180026a41206a280200360200200241a8026a41186a20024180026a41186a290300370300200241a8026a41106a20024180026a41106a290300370300200241a8026a41086a20024180026a41086a29030037030020022002290380023703a80220024188016a200241a8026a10ca010240200228028801450d000340200241d0026a41086a2201200328020036020020022002290388013703d002200b280200211120102802002112200c2802002119200241e0026a41086a220f2001280200360200200220022903d0023703e002024002402011450d00200241f0026a41086a2019360200200220123602f402200220113602f002200e20162903003703002010201729030037030020032018290300370300200720022903e002370200200741086a200f280200360200200220022903d00137038801410810012201450d062002200136029003200242083702940320024190036a41004108102720024190036a41086a22012001280200220f41086a360200200f2002280290036a42f3e885d3b38eddb73a37000020024180036a41086a220f200128020036020020022002290390033703800320024190036a20024188016a10cb01200228029403211c200228029003211a20024180036a200f280200200128020022191027200228028003221d200f280200221e6a201a2019101e1a200f201e20196a221e3602000240201c450d00201a10020b200228028403211a200241a0036a200241f0026a1051200241a0036a41086a280200211c20022802a0032119200142003703002002420037039003201d201e20024190036a1003200f200129030037030020022002290390033703800320024180036a41102019201c1004024020022802a403450d00201910020b0240201a450d00201d10020b0240200d280200450d00200728020010020b2012450d01201110020c010b200720022903e002370200200e20162903003703002010201729030037030020032018290300370300200741086a200f280200360200200220022903d00137038801410810012201450d052002200136029003200242083702940320024190036a41004108102720024190036a41086a22012001280200220f41086a360200200f2002280290036a42f3e885d3b38eddb73a37000020024180036a41086a220f200128020036020020022002290390033703800320024190036a20024188016a10cb01200228029403211a200228029003211220024180036a200f2802002001280200221110272002280280032219200f280200221d6a20122011101e1a200f201d20116a22113602000240201a450d00201210020b20022802840321122001420037030020024200370390032019201120024190036a1003200f200129030037030020022002290390033703800320024180036a4110100502402012450d00201910020b200d280200450d00200728020010020b20024188016a200241a8026a10ca012002280288010d000b0b200241a8026a1099010240201b201445720d002015450d00201410020b20024188016a200241306a10c801200729030022044202520d000b0b200241306a109e01200241b0036a24000f0b101c000bc10b03087f017e027f230041d0016b220224000240024020012802202203450d00200141206a2003417f6a36020020012802082104200128020c2203200128020422052f01be034f0d01200241306a41186a2206200520034105746a220741d8036a290000370300200241306a41106a2208200741d0036a290000370300200241306a41086a2209200741c8036a2900003703002002200741c0036a290000370330200141046a2005360200200141086a20043602002001410c6a200341016a360200200241d0006a41206a22072005200341286c6a220341206a290300370300200241d0006a41186a2205200341186a290300370300200241d0006a41106a2204200341106a290300370300200241d0006a41086a2201200341086a29030037030020022003290300370350200241f8006a41186a2006290300370300200241f8006a41106a2008290300370300200241f8006a41086a2009290300370300200241f8006a41286a2001290300370300200241a8016a2004290300370300200241b0016a2005290300370300200241b8016a20072903003703002002200229033037037820022002290350370398012000200241f8006a41c800101e1a200241d0016a24000f0b20004202370320200241d0016a24000f0b200128020021070240024020052802b8032203450d0020053201bc03210a2002200336027c2002200741016a22073602782002200a4220862004ad84220a370380010c010b2004ad210a410021030b20051002200241106a220820033602002002200736020c02400240200a422088a7220520032f01be034f0d00200241186a2005360200200241146a200a3e020020024100360208200241086a410472210b200241206a21070c010b200241146a2209200a37020020024101360208200aa72104200241086a410472210b200241186a210c2003210503400240024020032802b8032206450d00200741016a210720033201bc034220862004ad84210a200621030c010b2004ad210a410021030b024020051002200820033602002002200736020c0240200a422088a7220520032f01be034f0d00200c20053602002009200aa72204360200200241003602082003210541000d020c010b2009200a370200200aa72104200241013602082003210541010d010b0b200241206a21070b2007200b290200370200200741086a200b41086a290200370200200241306a41086a20022802242206200228022c22084105746a220341c8036a290000370300200241306a41106a200341d0036a290000370300200241306a41186a200341d8036a2900003703002002200341c0036a290000370330200241d0006a41206a2006200841286c6a220341206a290300370300200241d0006a41186a200341186a290300370300200241d0006a41106a200341106a290300370300200241d0006a41086a200341086a290300370300200220032903003703502007280200210920022802282105200241f8006a41086a2204200620084102746a41a4066a280200220736020020024184016a2206200536020020022009417f6a220336027c20022003410047360278024002402003450d002009417e6a2103200241f8006a41047221080340200420072802a0062207360200200620053602002002200336027c200220034100473602782003417f6a2203417f470d000c020b0b200241f8006a41047221080b200120082902003702002001410c6a4100360200200141086a200841086a280200360200200241f8006a41186a200241306a41186a290300370300200241f8006a41106a200241306a41106a290300370300200241f8006a41086a200241306a41086a290300370300200241a0016a200241d0006a41086a290300370300200241a8016a200241d0006a41106a290300370300200241b0016a200241d0006a41186a290300370300200241b8016a200241f0006a2903003703002002200229033037037820022002290350370398012000200241f8006a41c800101e1a200241d0016a24000bb30301057f230041306b220224000240410810012203450d002002200336022020024208370224200241206a4100410810272002280220200228022822036a42f3e885d3b3ec9bb23a3700002002200341086a360228200241106a41086a200228022836020020022002290320370310412010012203450d002002200336022020024220370224200241206a41004120102720022802202204200228022822056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002002200541206a220036022820022802242105200241106a20022802182000102720022802102203200228021822066a20042000101e1a2002200620006a220636021802402005450d00200410020b200228021421042002200110512002280208210120022802002100200241206a41086a220542003703002002420037032020032006200241206a1003200241106a41086a200529030037030020022002290320370310200241106a411020002001100402402002280204450d00200010020b02402004450d00200310020b200241306a24000f0b101c000bba0803057f017e057f230041f0006b220224000240024020012802202203450d00200141206a2003417f6a36020020012802082104200128020c2203200128020422052f018e024f0d01200141046a2005360200200141086a20043602002001410c6a200341016a360200200241086a220620052003410c6c6a220341086a28020036020020022003290200370300200241c8006a41086a22052006280200360200200241dc006a2003418c016a280200360200200020022903002207370200200220034184016a290200370254200041086a2005290300370200200041106a200241c8006a41106a29030037020020022007370348200241f0006a24000f0b20004100360200200241f0006a24000f0b20012802002106024002402005280288022203450d00200532018c0221072002200336024c2002200641016a2206360248200220074220862004ad8422073703500c010b2004ad2107410021030b20051002200241086a2208200336020020022006360204024002402007422088a7220520032f018e024f0d00200241106a20053602002002410c6a20073e02002002410036020020024104722109200241186a21060c010b2002410c6a220a2007370200200241013602002007a7210420024104722109200241106a210b20032105034002400240200328028802220c450d00200641016a2106200332018c024220862004ad842107200c21030c010b2004ad2107410021030b024020051002200820033602002002200636020402402007422088a7220520032f018e024f0d00200b2005360200200a2007a72204360200200241003602002003210541000d020c010b200a20073702002007a72104200241013602002003210541010d010b0b200241186a21060b20062009290200370200200641086a200941086a290200370200200241286a41086a200228021c220c2002280224220a410c6c6a220341086a28020036020020022003290200370328200241386a41086a2003418c016a280200360200200220034184016a2902003703382006280200210820022802202105200241c8006a41086a2204200c200a4102746a4194026a2802002206360200200241c8006a410c6a220c200536020020022008417f6a220336024c20022003410047360248024002402003450d002008417e6a2103200241c8006a4104722108034020042006280290022206360200200c20053602002002200336024c200220034100473602482003417f6a2203417f470d000c020b0b200241c8006a41047221080b200120082902003702002001410c6a4100360200200141086a200841086a280200360200200241c8006a41086a2203200241286a41086a280200360200200241dc006a200241386a41086a28020036020020002002290328220737020020022002290338370254200041086a2003290300370200200041106a200241c8006a41106a29030037020020022007370348200241f0006a24000bda0201057f230041206b22022400200241003602082002420137030020024100412010272002280200200228020822036a22042001290000370000200441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a2900003700002002200341206a2205360208200241106a200141206a1051200228021021032002200520022802182204102720022004200228020822066a22013602082006200228020022056a20032004101e1a02402002280214450d00200310020b02402001417f4c0d00024002402001450d002001100122040d01101c000b410121040b200220013602142002200436021020024100360218200241106a41002001102720022002280218220420016a360218200420022802106a20052001101e1a200041086a20022802183602002000200229031037020002402002280204450d00200510020b200241206a24000f0b1019000b02000be90502047f017e230041d0006b220524000240024002402004417f4c0d000240024002402004450d002004100122060d010c020b410121060b200520043602042005200636020020054100360208200541002004102720052005280208220620046a360208200620052802006a20032004101e1a200541c0006a41086a2204200528020836020020052005290300370340200541186a200241186a290000370300200541106a200241106a290000370300200541086a200241086a290000370300200541286a20042802003602002005200229000037030020052005290340370320410810012204450d002005200436024020054208370244200541c0006a4100410810272005280240200528024822046a42f3e885d3b38eddb73a3700002005200441086a360248200541306a41086a2204200528024836020020052005290340370330200541c0006a200510cb012005280244210720052802402103200541306a200428020020052802482202102720052802302206200428020022086a20032002101e1a2004200820026a220236020002402007450d00200310020b20052802342103200541c0006a41086a220442003703002005420037034020062002200541c0006a1003200541306a41086a20042903003703002005200529034037033002400240024002400240200541306a411041d02d410041001000417f460d00200541003602404100200541306a4110200541c0006a41044100100022042004417f461b220741034d0d0820052802402204417f4c0d062004450d01200410012202450d0520024100200410171a0c020b2000410036020020030d020c030b410121020b20044100200541306a4110200220042007410420074104491b100022072007417f461b4b0d042002450d0520002004ad2209422086200984370204200020023602002003450d010b200610020b0240200541246a280200450d00200541206a28020010020b200541d0006a24000f0b101c000b1019000b200210020b41c1214133102d000bd50402057f017e230041206b220324000240024002400240410810012204450d002003200436021020034208370214200341106a4100410810272003280210200328021822046a42f3e885d3b3ec9bb23a3700002003200441086a360218200341086a200328021836020020032003290310370300412010012204450d002003200436021020034220370214200341106a41004120102720032802102205200328021822066a22042002290000370000200441086a200241086a290000370000200441106a200241106a290000370000200441186a200241186a2900003700002003200641206a220236021820032802142104200320032802082002102720032802002206200328020822076a20052002101e1a2003200720026a220236020802402004450d00200510020b20032802042105200341106a41086a220442003703002003420037031020062002200341106a1003200341086a200429030037030020032003290310370300024002400240024002402003411041d02d410041001000417f460d0020034100360210410020034110200341106a41044100100022022002417f461b220741034d0d0820032802102202417f4c0d062002450d01200210012204450d0520044100200210171a0c020b200041003602082000420137020020050d020c030b410121040b2002410020034110200420022007410420074104491b100022072007417f461b4b0d042004450d0520002002ad2208422086200884370204200020043602002005450d010b200610020b200341206a24000f0b101c000b1019000b200410020b41c1214133102d000ba90701047f230041f0006b220424000240024002402003280200450d00200441086a200341086a28020036020020042003290200370300200441106a41186a200141186a290000370300200441106a41106a200141106a290000370300200441106a41086a200141086a290000370300200441386a200241086a2802003602002004200129000037031020042002290200370330410810012201450d022004200136025020044208370254200441d0006a4100410810272004280250200428025822016a42f3e885d3b38eddb73a3700002004200141086a360258200441c0006a41086a2201200428025836020020042004290350370340200441d0006a200441106a10cb012004280254210520042802502102200441c0006a200128020020042802582203102720042802402206200128020022076a20022003101e1a2001200720036a220336020002402005450d00200210020b20042802442102200441e0006a200410512004280268210520042802602101200441d0006a41086a220742003703002004420037035020062003200441d0006a1003200441c0006a41086a200729030037030020042004290350370340200441c0006a411020012005100402402004280264450d00200110020b02402002450d00200610020b0240200441346a280200450d00200441306a28020010020b2004280204450d0120042802001002200441f0006a24000f0b200441106a41186a200141186a290000370300200441106a41106a200141106a290000370300200441106a41086a200141086a290000370300200441386a200241086a2802003602002004200129000037031020042002290200370330410810012201450d012004200136025020044208370254200441d0006a4100410810272004280250200428025822016a42f3e885d3b38eddb73a3700002004200141086a360258200441c0006a41086a2201200428025836020020042004290350370340200441d0006a200441106a10cb012004280254210520042802502102200441c0006a200128020020042802582203102720042802402206200128020022076a20022003101e1a2001200720036a220336020002402005450d00200210020b20042802442101200441d0006a41086a220242003703002004420037035020062003200441d0006a1003200441c0006a41086a200229030037030020042004290350370340200441c0006a4110100502402001450d00200610020b200441346a280200450d00200441306a28020010020b200441f0006a24000f0b101c000b1e002001200210c9010240200241046a280200450d00200228020010020b0b9a0301057f230041306b220324000240410810012204450d002003200436022020034208370224200341206a4100410810272003280220200328022822046a42f3e885d3a3ac98b63a3700002003200441086a360228200341106a41086a200328022836020020032003290320370310412010012204450d002003200436022020034220370224200341206a41004120102720032802202205200328022822066a22042001290000370000200441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a2900003700002003200641206a220136022820032802242106200341106a20032802182001102720032802102204200328021822076a20052001101e1a2003200720016a220136021802402006450d00200510020b2003280214210520032002370308200341206a41086a220642003703002003420037032020042001200341206a1003200341106a41086a200629030037030020032003290320370310200341106a4110200341086a4108100402402005450d00200410020b200341306a24000f0b101c000bf90f020b7f017e230041a0036b220424002001280204210520022802082106200228020421072002280200210802400240200128020022092f018e02220a450d004107210b0c010b4101210b0b03400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200b0e1b0a090b0c0d0708000102030406050e1a0f10141617151819121113130b2009200a410c6c6a210c4100210a200921024108210b0c300b20082002280200200241086a280200220d20062006200d4b1b1006220e450d1b4109210b0c2f0b200e411e76417f73410271417f6a220d450d24410a210b0c2e0b200d4101470d1d410b210b0c2d0b200a41016a210a2002410c6a2202200c470d1b0c1a0b4100417f41012006200d491b2006200d461b220d0d20410c210b0c2b0b200441013a00980120042d0098014101710d154105210b0c2a0b2005450d1d4106210b0c290b2005417f6a21052009200a4102746a4190026a28020022092f018e02220a0d124101210b0c280b200441003a00980120042d009801410171450d180c190b2009418e026a2f0100210a0c130b200141086a2102200aad4220862001ad84210f2007450d184103210b0c250b200810024104210b0c240b20042005360268200420023602782004200936026c2004200f370370200441086a41086a2202200341086a2802003602002004200329020037030820044198016a41086a220a2009200f422088a7410c6c6a2206418c016a220d280000220536020020064184016a2206290000210f20062004290308370000200d2002280200360000200220053602002004200f370398012004200f370308200a20022802003602002004200429030837039801200041013602002000410c6a200a2802003602002000200429039801370204200441a0036a24000f0b200441086a41106a20093602002001200128020841016a3602082004411c6a200aad4220862001ad84220f3702002004200736020c2004200836020820042006ad3703102004200936026c200441003602682004200f3703702004200736024c2004200836024820042006360250200441d8006a41086a200341086a2802003602002004200329020037035820044198016a200441e8006a200441c8006a200441d8006a1089012004280298014101470d1a4110210b0c220b200441286a41086a200441b0016a280200360200200441386a41086a200441bc016a280200360200200420044198016a41106a2903003703282004200441b4016a290200370338200441a4016a2802002102200441c4016a2802002109200441c0016a280200210a200428029c01210520044198016a41086a280200220d280288022206450d1a4111210b0c210b200d2f018c02210d2004200636026c2004200541016a2205360268200420023602702004200d3602744100450d1b4119210b0c200b2005210241c002100122060d1e4118210b0c1f0b101c000b2004200d36026c20042005360268200420023602702002210541010d174112210b0c1d0b200441b4016a210e200441a8016a2108200441e8006a410c6a210c200441c4016a2103200441c0016a21010c180b20032802002109200428029c0141016a2105200d2f018c02210d4113210b0c1b0b200441e8006a41086a2002360200200c200d3602002004200636026c20042005360268200441c8006a41086a200441286a41086a220228020036020020042004290328370348200441d8006a41086a200441386a41086a22062802003602002004200429033837035820044198016a200441e8006a200441c8006a200441d8006a200a2009108a012004280298014101470d114114210b0c1a0b2002200841086a2802003602002006200e41086a280200360200200420082902003703282004200e29020037033820044198016a410c6a28020021022001280200210a20044198016a41086a280200220d2802880222060d164116210b0c190b41c00210012206450d164117210b0c180b200620044198016a418802101e220641003b018e022006410036028802200620042902683702900220064198026a200441e8006a41086a290200370200200641a0026a200441f8006a290200370200200641a8026a20044180016a290200370200200641b0026a20044188016a290200370200200641b8026a20044190016a2902003702002006200228020036029002200220063602002002200228020441016a360204200628029002220241003b018c022002200636028802200620062f018e02220d410c6c6a220220042903283702002002418c016a200441386a41086a280200220536020020024184016a2004290338220f370200200241086a200441286a41086a28020036020020064190026a200d41016a22024102746a200a360200200620062f018e0241016a3b018e0220044198016a41086a2005360200200a20023b018c02200a2006360288022004200f37039801410f210b0c170b20004100360200200441a0036a24000f0b4107210b0c150b4102210b0c140b410d210b0c130b4101210b0c120b4100210b0c110b4108210b0c100b4101210b0c0f0b4105210b0c0e0b4102210b0c0d0b4104210b0c0c0b410e210b0c0b0b410a210b0c0a0b410c210b0c090b410f210b0c080b410f210b0c070b411a210b0c060b4119210b0c050b4112210b0c040b4113210b0c030b4115210b0c020b4118210b0c010b4117210b0c000b0b4501017f230041c0006b22012400200141386a2000410c6a28020036020020012000290204370330200141086a200141306a109d01200141086a109e01200141c0006a24000b7302017f017e024020002802002202417f460d002000200241016a36000002400240200041046a20011096012202450d002002280200450d00200241086a29030021030c010b20002802102001200041146a28020028021411140021030b20002000280200417f6a36000020030f0b109f01000b960501077f230041e0026b22032400200341086a200241086a28020036020020032002290200370300024002400240024020002802000d002000417f360000200341306a41186a2204200141186a290000370300200341306a41106a2205200141106a290000370300200341306a41086a200141086a290000370300200320012900003703302003200041046a3602182003200041086a28020036021020032000280204360214200341b8026a200341106a200341306a10970141012102200341b8026a41106a2802002106200341c4026a2802002107200341b8026a41086a280200210820032802bc022109024020032802b8024101470d00200341106a41186a2004290300370300200341106a41106a2005290300370300200341106a41086a200341306a41086a29030037030020032003290330370310410021020b41900210012201450d012001200341306a418802101e220141003b018e02200141003602880202402002450d00200320013602b802200342003702bc02200341306a200341b8026a109801200341306a1099012008200641286c6a220241106a210120022802102206450d040c030b200341cc006a200341186a290300370200200341d4006a200341206a290300370200200341dc006a200341286a2903003702002003200836023420032009360230200320073602382003200636023c20032000410c6a36024020032003290310370244200341d8026a4200370300200341003602c802200342003703b802200320013602d402200341306a200341b8026a109a01220241106a2101200228021022060d020c030b10c301000b101c000b200241146a280200450d00200610020b20012003290300370200200141086a200341086a28020036020020004100360000200341e0026a24000bab0401097f230041d0026b220324000240024020002802000d002000417f360000200341c8006a41186a2204200141186a290000370300200341c8006a41106a2205200141106a290000370300200341c8006a41086a2206200141086a290000370300200320012900003703482003200041046a3602082003200041086a28020036020020032000280204360204200341206a2003200341c8006a10970141012107200341206a41106a28020021082003412c6a2802002109200341206a41086a280200210a2003280224210b024020032802204101470d00200341186a2004290300370300200341106a2005290300370300200341086a200629030037030020032003290348370300410021070b41900210012201450d012001200341c8006a418802101e220141003b018e022001410036028802024002402007450d002003200136022020034200370224200a200841286c6a2101200341c8006a200341206a109801200341c8006a1099010c010b200341e4006a200341086a290300370200200341ec006a200341106a290300370200200341f4006a200341186a2903003702002003200a36024c2003200b360248200320093602502003200836025420032000410c6a3602582003200329030037025c200341c0006a420037030020034100360230200342003703202003200136023c200341c8006a200341206a109a0121010b200142013703002001200237030820004100360000200341d0026a24000f0b10c301000b101c000bfc0103017f017e047f230041306b2203240020034100360208200342013703002002290300210420034100410810272003280200200328020822056a20043700002003200541086a2206360208200341206a200241086a10a201200328022021052003200620032802282202102720032002200328020822076a22083602082007200328020022066a20052002101e1a02402003280224450d00200510020b200341206a41086a220242003703002003420037032020002001200341206a1003200341106a41086a200229030037030020032003290320370310200341106a411020062008100402402003280204450d00200610020b200341306a24000bfb1903047f017e077f230041d0006b22022400200241003602082002420137030002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001280200417f6a220341044b0d000240024002400240024020030e050004020301000b2002107e2002280200200241086a22032802006a41013a00002003200328020041016a22043602002002410036024820024201370340200141086a28020022054101460d0920054102470d1a200241c0006a107e20022802402205200241c8006a220328020022016a41013a00002003200141016a22013602000c0a0b2002107e2002280200200241086a22032802006a41073a00002003200328020041016a3602002002410036024820024201370340200141086a28020022034101460d0420034102470d1a200241c0006a107e2002280240200241c0006a41086a220328020022056a41013a00002003200541016a2205360200200141106a2903002106200241c0006a20054108102720032003280200220441086a22013602002004200228024022056a20063700000c050b2002107e2002280200200241086a22032802006a41053a00002003200328020041016a360200200241003602382002420137033020012d000422034103714101460d0520034102470d1a200241306a107e2002280230200241306a41086a220328020022056a41013a00002003200541016a2205360200200141086a2802002104200241306a20054104102720032003280200220741046a22013602002007200228023022056a20043600000c060b2002107e2002280200200241086a22032802006a41063a00002003200328020041016a3602002002410036024820024201370340200141086a22042d0000417f6a220341034b0d1a024020030e04000d0a0c000b200241c0006a107e2002280240200241c8006a220328020022056a41003a00002003200541016a22053602002001410c6a2802002104200241c0006a20054104102720032003280200220741046a22013602002007200228024022056a20043600000c0d0b2002107e2002280200200241086a22032802006a41023a00002003200328020041016a3602002002410036024820024201370340200141086a280200417f6a220341034b0d1a024020030e04000f0a0e000b200241c0006a107e2002280240200241c0006a41086a220328020022056a41003a00002003200541016a2205360200200141106a2903002106200241c0006a20054108102720032003280200220441086a22013602002004200228024022056a20063700000c0f0b2002107e2002280200200241086a22032802006a41003a00002003200328020041016a3602002002410036021820024201370310200128020422034101460d0620034102470d1a200241106a107e2002280210200241106a41086a220328020022056a41013a00002003200541016a2208360200200141106a220328020021052002410036024820024201370340200241c0006a4100410410272002280240200228024822046a20053600002002200441046a360248200241206a41086a220420022802483602002002200229034037032020032802002203450d0f200141086a2802002201200341186c6a21090340200241306a41086a2203410036020020024201370330200241c0006a200110512002280240210a200241306a4100200241c0006a41086a220528020022071027200320072003280200220b6a220c360200200b20022802306a200a2007101e1a02402002280244450d00200a10020b200241c0006a2001410c6a220d10512002280240210a200241306a200c200528020022071027200320072003280200220c6a2201360200200c2002280230220b6a200a2007101e1a02402002280244450d00200a10020b2001417f4c0d14024002402001450d002001100122030d010c170b410121030b200541003602002002200136024420022003360240200241c0006a41002001102720052005280200220720016a22033602002007200228024022056a200b2001101e1a2002280244210102402002280234450d00200b10020b200241206a2004280200200310272002280220220a200428020022076a20052003101e1a2004200720036a220336020002402001450d00200510020b200d410c6a22012009470d000c110b0b200241c0006a107e2002280240200241c0006a41086a220328020022056a41003a00002003200541016a2205360200200141106a2903002106200241c0006a20054108102720032003280200220441086a22013602002004200228024022056a20063700000b200228024421042002200241086a22032802002001102720032003280200220720016a360200200720022802006a20052001101e1a2004450d10200510020c100b200241306a107e2002280230200241306a41086a220328020022056a41003a00002003200541016a2207360200200241c0006a200141086a28020010d80120022802402104200241306a200720022802482205102720032005200328020022076a220a360200200720022802306a20042005101e1a02402002280244450d00200410020b410221030240200141056a2d000022014103714102460d004100210320014101470d00410121030b200241306a200a41011027200241386a22012001280200220441016a22013602002004200228023022056a20033a00000b200228023421042002200241086a22032802002001102720032003280200220720016a360200200720022802006a20052001101e1a2004450d0e200510020c0e0b200241c0006a107e2002280240200241c0006a41086a220428020022056a41003a00002004200541016a2205360200200141106a2903002106200241c0006a20054108102720022802402205200428020022016a20063700002004200141086a2201360200200328020021040b200228024421032002200420011027200241086a22042004280200220420016a360200200420022802006a20052001101e1a2003450d0c200510020c0c0b200241106a107e2002280210200241106a41086a220328020022056a41003a00002003200541016a2205360200200241c0006a200141086a105120022802402107200241106a2005200228024822041027200320042003280200220a6a2201360200200a200228021022056a20072004101e1a2002280244450d0a200710020c0a0b200241c0006a107e2002280240200241c0006a41086a220328020022056a41023a00002003200541016a2205360200200141106a2903002106200241c0006a20054108102720032003280200220441086a22013602002004200228024022056a20063700000c030b200241c0006a107e2002280240200241c8006a220328020022056a41023a00002003200541016a22053602002001410c6a2802002104200241c0006a20054104102720032003280200220741046a22013602002007200228024022056a20043600000c050b200241c0006a107e2002280240200241c0006a41086a220328020022056a41033a00002003200541016a2205360200200141106a2903002106200241c0006a20054108102720032003280200220441086a22013602002004200228024022056a20063700000c010b200241c0006a107e2002280240200241c0006a41086a220328020022016a41013a00002003200141016a2201360200200241c0006a20014120102720032003280200220741206a22013602002007200228024022056a220341086a200441096a290000370000200341106a200441116a290000370000200341186a200441196a290000370000200320042900013700000b200228024421042002200241086a22032802002001102720032003280200220720016a360200200720022802006a20052001101e1a2004450d06200510020c060b200241c0006a107e20022802402205200241c8006a220328020022016a41033a00002003200141016a22013602000c010b200241c0006a107e2002280240200241c0006a41086a220328020022056a41013a00002003200541016a2205360200200141106a2903002106200241c0006a20054108102720032003280200220441086a22013602002004200228024022056a20063700000b200228024421042002200241086a22032802002001102720032003280200220720016a360200200720022802006a20052001101e1a2004450d03200510020c030b200228022821032002280220210a0b20022802242104200241106a20082003102720022002280218220720036a22013602182007200228021022056a200a2003101e1a2004450d00200a10020b200228021421042002200241086a22032802002001102720032003280200220720016a360200200720022802006a20052001101e1a2004450d00200510020b20002002290300370200200041086a200241086a280200360200200241d0006a24000f0b1019000b101c000b41ec30103b000b41843e103b000b41ac3f103b000b419435103b000b41943b103b000b41ecc100103b000bc20201027f230041c0006b22022400200241106a41086a220342003703002002420037031020014107200241106a1003200241086a20032903003703002002200229031037030002402002411041d02d410041001000417f460d00200241386a4200370300200241206a41106a4200370300200241206a41086a420037030020024200370320024020024110200241206a4120410010002203417f460d002003411f4d0d0020002002290320370000200041186a200241206a41186a290300370000200041106a200241206a41106a290300370000200041086a200241206a41086a2200290300370000200241106a41086a220342003703002002420037031020014107200241106a10032000200329030037030020022002290310370320200241206a41101005200241c0006a24000f0b41c1214133102d000b41f4214122102d000bb80101027f230041306b22032400200341206a41086a220442003703002003420037032020012002200341206a1003200341086a200429030037030020032003290320370300024002402003411041d02d410041001000417f460d002003421037021420032003360210200341206a200341106a103a20032802202201450d012000200329022437020420002001360200200341306a24000f0b2000410036020820004201370200200341306a24000f0b41c1214133102d000b8d5b05087f037e137f017e017f230041e0016b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d000022034103714101460d00024020034102460d0020034103470d0d200241206a200041196a290000370300200241186a200041116a290000370300200241106a200041096a29000037030020022000290001370308200241386a1047200228023822042002280240220541286c22066a2107200421030240200641286d4104490d00200421060340200120062203460d062003200141201006450d06200341286a22062001460d0a2006200141201006450d0a200641286a22062001460d0b2006200141201006450d0b200641286a22062001460d0c2006200141201006450d0c2007200641286a22066b41286d41034b0d000b200341a0016a21030b024020032007460d002004200541286c6a2106034020012003460d042003200141201006450d042006200341286a2203470d000b0b2004200228023c10870141fc3e103b000b200041216a2d0000210520024198016a41186a200041196a220329000037030020024198016a41106a200041116a220629000037030020024198016a41086a200041096a22042900003703002002200029000137039801200241386a41186a2003290000370300200241386a41106a2006290000370300200241386a41086a2004290000370300200241e0006a200141086a290000370300200241e8006a200141106a290000370300200241f0006a200141186a2900003703002002200029000137033820022001290000370358410910012203450d17200220033602c001200242093702c401200241c0016a41004109102720022802c00120022802c80122066a220441002900f922370000200241086a41086a2203200641096a2206360200200441086a41002d0081233a0000200220022903c001370308200220063602c801200241c0016a200241386a10be0120022802c401210820022802c0012104200241086a200328020020022802c8012206102720022802082207200328020022096a20042006101e1a2003200920066a220636020002402008450d00200410020b200228020c210320024188016a41086a2204420037030020024200370388012007200620024188016a1003200241f8006a41086a20042903003703002002200229038801370378200241f8006a411041d02d410041001000417f460d02200241003a00c001200241f8006a4110200241c0016a41014100100041016a41014d0d1020022d00c00121062003450d160c150b200041046a280200210d102e210a20024188016a41086a22034200370300200242003703880141e122410a20024188016a1003200241f8006a41086a20032903003703002002200229038801370378200241f8006a411041d02d410041001000417f460d0c20024200370338200241f8006a4110200241386a41084100100041016a41084d0d0a2002290338200a7c210a200241386a1047200228023822072002280240220841286c22066a2105200721030240200641286d4104490d00200721030340200120032206460d052006200141201006450d05200641286a2103200641286a22042001460d062004200141201006450d06200641d0006a2103200441286a22042001460d062004200141201006450d06200641f8006a2103200441286a22042001460d062004200141201006450d062005200441286a22036b41286d41034b0d000b200641a0016a21030b4102210420032005460d052007200841286c6a2106034020012003460d052003200141201006450d052006200341286a2203470d000c060b0b200228023c450d120c110b4102210620030d120c130b200228023c0d0f0c100b200621030b200341206a290300200a5621040b200441024720047121030240200228023c450d00200710020b2003450d0720024198016a200d10d80120022802a00121052002280298012107200241386a41186a22034200370300200241386a41106a22064200370300200241386a41086a220442003703002002420037033820072005200241386a1012200241c0016a41186a22052003290300370300200241c0016a41106a22082006290300370300200241c0016a41086a22092004290300370300200220022903383703c0010240200228029c01450d00200710020b200320052903003703002006200829030037030020042009290300370300200220022903c001370338410710012203450d1020022003360298012002420737029c0120024198016a41004107102720022802980120022802a00122066a220341002800eb22360000200241086a41086a200641076a2206360200200341046a41002f00ef223b0000200341066a41002d00f1223a00002002200229039801370308200220063602a001412010012203450d1020022003360298012002422037029c0120024198016a410041201027200228029801220620022802a00122046a22032002290338370000200341086a200241386a41086a290300370000200341106a200241386a41106a290300370000200341186a200241386a41186a2903003700002002200441206a22033602a001200228029c012107200241086a20022802102003102720022802082204200228021022056a20062003101e1a2002200520036a220336021002402007450d00200610020b200228020c210620024188016a41086a2207420037030020024200370388012004200320024188016a1003200241f8006a41086a20072903003703002002200229038801370378200241f8006a411020024198016a410041001000210302402006450d00200410020b2003417f470d08200241386a200241c0016a10dc01024020022802402203450d002002290338210b20022802442106102e210c02402006450d00200310020b200c200b540d0b0b200241286a10bb01200241386a41186a2206200241c0016a41186a290300370300200241386a41106a2204200241c0016a41106a290300370300200241386a41086a2207200241c0016a41086a290300370300200220022903c00137033820022802302205200228022c460d030c0b0b200228023c0d0b0c0c0b200228023c0d0a0c0b0b200228023c0d090c0a0b200241286a106f200241286a41086a28020021050c070b41c1214133102d000b419c3e103b000b41f4214122102d000b41b43e103b000b41cc3e103b000b41c1214133102d000b41e43e103b000b200241286a41086a200541016a22153602002002280228220f200541286c6a2203200a37030020032002290338370308200341106a2007290300370300200341186a2004290300370300200341206a2006290300370300024002400240024002400240024002400240024002400240024002400240024002400240201541144b0d00201541014d0d01200f200541286c6a21110340201520052203417f6a2205490d100240201520056b22074102490d00200f200341286c6a2204290300200f200541286c6a220e290300220a5a0d00200e2004290300370300200e290308210b200e41086a200441086a290300370300200241386a41186a2200200e41206a2203290300370300200241386a41106a2212200e41186a2206290300370300200241386a41086a2213200e41106a22082903003703002008200441106a2903003703002006200441186a2903003703002003200441206a2903003703002002200b37033841012108024020074103490d0041012106201121030340200641016a220820074f0d150240200341286a2204290300200a5a0d00200620074f0d15200341206a200341c8006a290300370300200341186a200341c0006a290300370300200341106a200341386a290300370300200341086a200341306a29030037030020032004290300370300200641026a2109200821062004210320092007490d010c020b0b20062108200321040b2004200a370300200e200841286c6a22032002290338370308200341206a2000290300370300200341186a2012290300370300200341106a20132903003703000b201141586a211120050d000c020b0b20154101762216ad42287e220a422088a70d0d200aa72203417f4c0d0c4108211702402003450d00200310012217450d160b41002106200241003602a0012002420437039801200f41586a2118200f41887f6a21194104210420024198016a41086a211a2015211003402010211141002110410121070240024002402011417f6a2203450d000240024002400240024002400240200f200341286c6a290300200f2011417e6a220741286c6a290300220a5a0d00410021082007450d022019201141286c6a21030340200a2003290300220b5a0d02200341586a2103200b210a2007417f6a22070d000c030b0b02402007450d002019201141286c6a2103410221070340200a2003290300220b540d04200341586a2103200b210a2011200741016a2207470d000b41002110201121072006200228029c01470d090c080b41022107410021102006200228029c01470d080c070b200721080b024020112008490d00201120154b0d140240201120086b22074101762209450d002018201141286c6a2103200f200841286c6a21050340200241386a41206a220e200541206a2200290300370300200241386a41186a2212200541186a2213290300370300200241386a41106a2214200541106a2210290300370300200241386a41086a221b200541086a221c29030037030020022005290300370338200341086a221d290300210a200341106a221e290300210b200341186a221f290300210c200329030021202000200341206a22212903003703002013200c3703002010200b370300201c200a370300200520203703002021200e290300370300201f2012290300370300201e2014290300370300201d201b29030037030020032002290338370300200341586a2103200541286a21052009417f6a22090d000b0b2008450d030c020b200820111055000b201120076b2208450d010b200741094d0d010b200821102006200228029c01470d030c020b201120154b0d0d200f200841286c6a2112034020112008417f6a2210490d0f0240201120106b22074102490d00200f200841286c6a2208290300200f201041286c6a2200290300220a5a0d00200020082903003703002000290308210b200041086a200841086a290300370300200241386a41186a2213200041206a2203290300370300200241386a41106a2214200041186a2205290300370300200241386a41086a221b200041106a22092903003703002009200841106a2903003703002005200841186a2903003703002003200841206a2903003703002002200b37033841012109024020074103490d0041012105201221030340200541016a220920074f0d090240200341286a2208290300200a5a0d00200520074f0d0b200341206a200341c8006a290300370300200341186a200341c0006a290300370300200341106a200341386a290300370300200341086a200341306a29030037030020032008290300370300200541026a210e2009210520082103200e2007490d010c020b0b20052109200321080b2008200a3703002000200941286c6a22032002290338370308200341206a2013290300370300200341186a2014290300370300200341106a201b2903003703000b2010450d01201241586a2112201021082007410a490d000b0b2006200228029c01470d010b20024198016a107a201a280200210620022802980121040b200420064103746a2203200736020420032010360200201a200641016a2206360200024020064102490d0020022802980121040340024002400240024020042006417f6a4103746a2203280200450d00200420064103746a220841746a2802002205200328020422074d0d00200641024d0d0520042006417d6a22124103746a2802042203200720056a4d0d01200641034d0d05200841646a280200200320056a4d0d010c050b20064103490d012003280204210720042006417d6a22124103746a28020421030b20032007490d010b2006417e6a21120b2006201241016a22134d0d06200620124d0d0720042012410374221b6a2203280204221c20032802006a220320042013410374221d6a22062802002214490d08200320154b0d09200f201441286c6a22112006280204220041286c22066a2107200341286c210402400240024002400240200320146b220820006b220320004f0d0020172007200341286c2206101e220e20066a210520004101480d0120034101480d01201820046a21042007210303402004200341586a2207200541586a2208200829030020072903005422091b2206290300370300200441206a200641206a290300370300200441186a200641186a290300370300200441106a200641106a290300370300200441086a200641086a2903003703002005200820091b210520112007200320091b22034f0d04200441586a2104200e2106200e2005490d000c050b0b201720112006101e220320066a210520004101480d01200820004c0d01200f20046a210920032106201121030340200320072006200729030020062903005422081b2204290300370300200341206a200441206a290300370300200341186a200441186a290300370300200341106a200441106a290300370300200341086a200441086a2903003703002006200641286a20081b2106200341286a2103200741286a200720081b220720094f0d04200520064b0d000c040b0b200721030c010b201121030b201721060b20032006200520066b220420044128706b101e1a201a280200220320124d0d0a2002280298012204201b6a2206201c20006a36020420062014360200200320134d0d0b2004201d6a2206200641086a200320136b41037441786a10391a201a2003417f6a2206360200200641014b0d000b0b20100d000b0240200228029c01450d0020022802980110020b2016450d00201710020b200241286a10bc0120024198016a41186a200241c0016a41186a29030037030020024198016a41106a200241c0016a41106a29030037030020024198016a41086a200241c0016a41086a290300370300200220022903c00137039801200241386a41286a200d41286a290300370300200241386a41206a200d41206a290300370300200241386a41186a200d41186a290300370300200241386a41106a200d41106a290300370300200241386a41086a200d41086a2903003703002002200d290300370338410710012203450d14200220033602082002420737020c200241086a4100410710272002280208200228021022066a220341002800eb2236000020024188016a41086a200641076a2206360200200341046a41002f00ef223b0000200341066a41002d00f1223a0000200220022903083703880120022006360210412010012203450d14200220033602082002422037020c200241086a41004120102720022802082206200228021022046a2203200229039801370000200341086a20024198016a41086a290300370000200341106a20024198016a41106a290300370000200341186a20024198016a41186a2903003700002002200441206a2203360210200228020c210720024188016a20022802900120031027200228028801220420022802900122056a20062003101e1a2002200520036a22053602900102402007450d00200610020b200228028c012106200241086a200241386a10d801200228021021072002280208210320024188016a41086a2208420037030020024200370388012004200520024188016a1003200241f8006a41086a20082903003703002002200229038801370378200241f8006a41102003200710040240200228020c450d00200310020b02402006450d00200410020b024002400240200228023822034103460d0020030d02200228023c2203450d0220034101470d01200241c4006a280200450d02200241c0006a28020010020c020b20022d003c4101470d01200241c0006a10bf010c010b0240200241386a41106a2802002206450d00200241c0006a2802002103200641186c210603400240200341046a280200450d00200328020010020b0240200341106a280200450d002003410c6a28020010020b200341186a2103200641686a22060d000b0b200241c4006a280200450d00200241c0006a28020010020b200241386a41186a2206200241c0016a41186a2204290300370300200241386a41106a2207200241c0016a41106a2205290300370300200241386a41086a2208200241c0016a41086a2209290300370300200220022903c001370338412010012203450d14200141086a220e290000210a200141106a2211290000210b2001290000210c200341186a200141186a2200290000370000200341106a200b370000200341086a200a3700002003200c3700002002200336029801200242818080801037029c01200241386a20024198016a10dd01200620042903003703002007200529030037030020082009290300370300200241e0006a200e290000370300200241e8006a2011290000370300200241f0006a2000290000370300200220022903c00137033820022001290000370358200241386a410110de010240200228022c450d00200228022810020b200d1002200241e0016a24000f0b41ccc100200541016a2007103c000b41dcc10020052007103c000b41acc10020132006103c000b41acc10020122006103c000b201420031055000b200320151029000b41bcc10020122003103c000b41b4c300103b000b20112008417f6a22104f0d010b201020111055000b201120151029000b1065000b1064000b200520151055000b41dcc10020062007103c000b41ccc100200641016a2007103c000b200410020b410b10012203450d02200220033602382002420b37023c200241386a4100410b10272002280238200228024022066a220341002900822337000020024198016a41086a2006410b6a2206360200200341086a41002f008a233b00002003410a6a41002d008c233a0000200220022903383703980120022006360240412010012203450d02200220033602382002422037023c200241386a41004120102720022802382206200228024022046a22032002290308370000200341086a200241086a41086a290300370000200341106a200241086a41106a290300370000200341186a200241086a41186a2903003700002002200441206a2203360240200228023c210720024198016a20022802a00120031027200228029801220420022802a00122056a20062003101e1a2002200520036a22033602a00102402007450d00200610020b200228029c01210620024188016a41086a2207420037030020024200370388012004200320024188016a1003200241f8006a41086a20072903003703002002200229038801370378200241f8006a411020024198016a410041001000210302402006450d00200410020b02400240024002402003417f460d00200241386a200241086a10dc010240024002400240024020022802402208450d0020022002290244220a37022c20022008360228200aa7210e200a422088a72209450d0120094101470d02410021030c030b410021092002410036023020024201370328410121084100210e0b410021060c020b4100210320092106034020032006410176220720036a2204200820044105746a2001412010062205417f4a1b200420051b2103200620076b220641014b0d000b0b200820034105746a2001412010062206450d032006411f7620036a21060b200241386a41186a200141186a290000370300200241386a41106a200141106a290000370300200241386a41086a200141086a2900003703002002200129000037033820092006490d012009200e470d03200241286a107c200228022821080c030b41943f103b000b419cc300103b000b200310c201000b200820064105746a220341206a2003200920066b41057410391a20032002290338370000200341186a200241386a41186a290300370000200341106a200241386a41106a290300370000200341086a200241386a41086a290300370000200241286a41086a200941016a360200102e210a20024188016a41086a220342003703002002420037038801418d23410b20024188016a1003200241f8006a41086a200329030037030020022002290388013703780240200241f8006a411041d02d410041001000417f460d00200242003703380240200241f8006a4110200241386a41084100100041016a41084d0d002002290338210b200241c8006a200241286a41086a2802003602002002200b200a7c37033820022002290328370340410910012203450d0420022003360298012002420937029c0120024198016a41004109102720022802980120022802a00122036a2206410029009823370000200241c0016a41086a200341096a2203360200200641086a41002d00a0233a000020022002290398013703c001200220033602a001412010012203450d0420022003360298012002422037029c0120024198016a410041201027200228029801220620022802a00122046a22032002290308370000200341086a200241086a41086a290300370000200341106a200241086a41106a290300370000200341186a200241086a41186a2903003700002002200441206a22033602a001200228029c012107200241c0016a20022802c8012003102720022802c001220420022802c80122056a20062003101e1a2002200520036a22033602c80102402007450d00200610020b20022802c401210620042003200241386a10d70102402006450d00200410020b0240200241c4006a280200450d00200241c0006a28020010020b200241386a10bb01200228023c210f20022802382110024002400240024020022802402203450d00200341286c41b07f6a2104200241386a41086a2106201021030340200241386a41206a200341206a290300370300200241386a41186a200341186a290300370300200241386a41106a200341106a2903003703002006200341086a29030037030020022003290300370338200241c0016a41186a200641186a290000370300200241c0016a41106a200641106a290000370300200241c0016a41086a200641086a290000370300200220062900003703c001200241c0016a200241086a412010060d02200341286a2103200441586a220441b07f470d000b0b2002410036024020024208370338200f450d0120101002200241386a10bc010c020b20024198016a41206a2206200241386a41206a29030037030020024198016a41186a2207200241386a41186a29030037030020024198016a41106a2205200241386a41106a29030037030020024198016a41086a2208200241386a41086a2903003703002002200229033837039801412810012211450d062011200229039801370300201141206a2006290300370300201141186a2007290300370300201141106a2005290300370300201141086a20082903003703002002201136028801200242818080801037028c01024020044158460d00200341286a2103200241386a41086a21064101210e0340200241386a41206a2205200341206a290300370300200241386a41186a2208200341186a290300370300200241386a41106a2209200341106a2903003703002006200341086a29030037030020022003290300370338200241c0016a41186a200641186a290000370300200241c0016a41106a200641106a290000370300200241c0016a41086a200641086a290000370300200220062900003703c0010240200241c0016a200241086a41201006450d0020024198016a41206a2207200529030037030020024198016a41186a2212200829030037030020024198016a41106a2213200929030037030020024198016a41086a2214200629030037030020022002290338370398012005200729030037030020082012290300370300200920132903003703002006201429030037030020022002290398013703380240200e200228028c01470d0020024188016a200e410110820120022802880121110b2011200e41286c6a22072002290338370300200741206a2005290300370300200741186a2008290300370300200741106a2009290300370300200741086a200629030037030020024188016a41086a200e41016a220e3602000b2004450d01200341286a2103200441586a21040c000b0b0240200f450d00201010020b200241386a41086a20024188016a41086a2802003602002002200229038801370338200228023c2103200241386a10bc012003450d01200228023810020c010b200241386a10bc010b200241386a41186a200241086a41186a290300370300200241386a41106a200241086a41106a290300370300200241386a41086a200241086a41086a29030037030020022002290308370338410b10012203450d0420022003360298012002420b37029c0120024198016a4100410b102720022802980120022802a00122066a2203410029008223370000200241c0016a41086a2006410b6a2206360200200341086a41002f008a233b00002003410a6a41002d008c233a000020022002290398013703c001200220063602a001412010012203450d0420022003360298012002422037029c0120024198016a410041201027200228029801220620022802a00122046a22032002290338370000200341086a200241386a41086a290300370000200341106a200241386a41106a290300370000200341186a200241386a41186a2903003700002002200441206a22033602a001200228029c012107200241c0016a20022802c8012003102720022802c001220420022802c80122056a20062003101e1a2002200520036a22033602c80102402007450d00200610020b20022802c401210620024188016a41086a2207420037030020024200370388012004200320024188016a1003200241f8006a41086a20072903003703002002200229038801370378200241f8006a4110100502402006450d00200410020b200241386a41186a200241086a41186a290300370300200241386a41106a200241086a41106a290300370300200241386a41086a200241086a41086a29030037030020022002290308370338410710012203450d0420022003360298012002420737029c0120024198016a41004107102720022802980120022802a00122066a220341002800eb22360000200241c0016a41086a200641076a2206360200200341046a41002f00ef223b0000200341066a41002d00f1223a000020022002290398013703c001200220063602a001412010012203450d0420022003360298012002422037029c0120024198016a410041201027200228029801220620022802a00122046a22032002290338370000200341086a200241386a41086a290300370000200341106a200241386a41106a290300370000200341186a200241386a41186a2903003700002002200441206a22033602a001200228029c012107200241c0016a20022802c8012003102720022802c001220420022802c80122056a20062003101e1a2002200520036a22033602c80102402007450d00200610020b20022802c401210620024188016a41086a2207420037030020024200370388012004200320024188016a1003200241f8006a41086a20072903003703002002200229038801370378200241f8006a4110100502402006450d00200410020b200241386a1047200228023c211320022802382112024020022802402203450d00200341286c2109200241d8006a210620122103034020062003290000370000200241386a41186a200241086a41186a290300370300200241386a41106a200241086a41106a290300370300200241386a41086a200241086a41086a290300370300200641086a200341086a290000370000200641106a200341106a290000370000200641186a200341186a29000037000020022002290308370338410910012204450d0620022004360298012002420937029c0120024198016a41004109102720024198016a41086a22072007280200220441096a220536020020042002280298016a220841002900f922370000200241c0016a41086a22042005360200200841086a41002d0081233a000020022002290398013703c00120024198016a200241386a10be01200228029c01210e2002280298012105200241c0016a200428020020072802002207102720022802c0012208200428020022116a20052007101e1a2004201120076a22073602000240200e450d00200510020b20022802c401210420024188016a41086a2205420037030020024200370388012008200720024188016a1003200241f8006a41086a20052903003703002002200229038801370378200241f8006a4110100502402004450d00200810020b200341286a2103200941586a22090d000b0b02402013450d00201210020b20002d00004101470d0a0c090b41c1214133102d000b41f4214122102d000b200710020b200641ff01714102470d04410b10012203450d00200220033602382002420b37023c200241386a4100410b10272002280238200228024022066a2203410029008223370000200241c0016a41086a2006410b6a2206360200200341086a41002f008a233b00002003410a6a41002d008c233a0000200220022903383703c00120022006360240412010012203450d00200220033602382002422037023c200241386a41004120102720022802382206200228024022046a2203200229039801370000200341086a20024198016a41086a290300370000200341106a20024198016a41106a290300370000200341186a20024198016a41186a2903003700002002200441206a2203360240200228023c2107200241c0016a20022802c8012003102720022802c001220420022802c80122086a20062003101e1a2002200820036a22033602c80102402007450d00200610020b20022802c401210720024188016a41086a2206420037030020024200370388012004200320024188016a1003200241f8006a41086a20062903003703002002200229038801370378410021030240200241f8006a411041d02d410041001000417f460d00200242103702c4012002200241f8006a3602c001200241386a200241c0016a103a20022802382206450d022002200229023c220a37020c20022006360208200a422088a72103200aa721092007450d040c030b2002410036021020024201370308410121064100210920070d020c030b101c000b41c1214133102d000b200410020b200241386a41186a2204200141186a290000370300200241386a41106a2207200141106a290000370300200241386a41086a2208200141086a29000037030020022001290000370338024020032009470d00200241086a107c200241086a41086a2802002103200228020821060b2008290300210a2007290300210b2004290300210c200620034105746a22062002290338370000200641186a200c370000200641106a200b370000200641086a200a370000200241086a41086a2206200341016a360200200420024198016a41186a290300370300200720024198016a41106a290300370300200820024198016a41086a2903003703002002200229039801370338200241c0016a41086a2006280200360200200220022903083703c001200241386a200241c0016a10dd010b200241386a41186a20024198016a41186a290300370300200241386a41106a20024198016a41106a290300370300200241386a41086a20024198016a41086a290300370300200241e0006a200141086a290000370300200241e8006a200141106a290000370300200241f0006a200141186a290000370300200220022903980137033820022001290000370358200241386a200541ff017141004710de0120002d00004101470d010b200041046a10bf010b200241e0016a24000bcd0402057f017e230041c0006b220224000240024002400240410910012203450d002002200336023020024209370234200241306a4100410910272002280230200228023822036a2204410029009823370000200241086a200341096a2203360200200441086a41002d00a0233a00002002200229033037030020022003360238412010012203450d002002200336023020024220370234200241306a41004120102720022802302204200228023822056a22032001290000370000200341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002002200541206a220136023820022802342105200220022802082001102720022802002203200228020822066a20042001101e1a2002200620016a220136020802402005450d00200410020b20022802042104200241306a41086a220542003703002002420037033020032001200241306a1003200241086a20052903003703002002200229033037030002402002411041d02d410041001000417f460d002002200236021020024110360214200242003703302002410020024110200241306a41084100100022012001417f461b2201410820014108491b360218200141074d0d0220022903302107200241306a200241106a103a20022802302201450d022002200229023437032020002001360208200020073703002000200229032037020c200041146a200241286a2802003602002004450d040c030b2000410036020820040d020c030b101c000b41c1214133102d000b200310020b200241c0006a24000be20301067f230041306b220224000240410b10012203450d00200220033602202002420b370224200241206a4100410b10272002280220200228022822046a2203410029008223370000200241106a41086a2004410b6a2204360200200341086a41002f008a233b00002003410a6a41002d008c233a00002002200229032037031020022004360228412010012203450d002002200336022020024220370224200241206a41004120102720022802202204200228022822056a22032000290000370000200341086a200041086a290000370000200341106a200041106a290000370000200341186a200041186a2900003700002002200541206a220036022820022802242105200241106a20022802182000102720022802102203200228021822066a20042000101e1a2002200620006a220636021802402005450d00200410020b200228021421042002200110a2012002280208210520022802002100200241206a41086a220742003703002002420037032020032006200241206a1003200241106a41086a200729030037030020022002290320370310200241106a411020002005100402402002280204450d00200010020b02402004450d00200310020b0240200141046a280200450d00200128020010020b200241306a24000f0b101c000bc00201057f230041306b22022400200220013a000f0240410910012201450d002002200136022020024209370224200241206a4100410910272002280220200228022822036a220441002900f922370000200241106a41086a2201200341096a2203360200200441086a41002d0081233a00002002200229032037031020022003360228200241206a200010be012002280224210520022802202103200241106a200128020020022802282200102720022802102204200128020022066a20032000101e1a2001200620006a220036020002402005450d00200310020b20022802142103200241206a41086a220542003703002002420037032020042000200241206a10032001200529030037030020022002290320370310200241106a41102002410f6a4101100402402003450d00200410020b200241306a24000f0b101c000bab0201057f230041206b220224000240410810012203450d002002200336021020024208370214200241106a4100410810272002280210200228021822036a42e4cab5d3c3ac99b83a3700002002200341086a360218200241086a200228021836020020022002290310370300410410012203450d002002200336021020024204370214200241106a41004104102720022802102203200228021822046a20003600002002200441046a220036021820022802142105200220022802082000102720022802002204200228020822066a20032000101e1a2002200620006a220036020802402005450d00200310020b2002280204210320042000200110d70102402003450d00200410020b02402001410c6a280200450d00200128020810020b200241206a24000f0b101c000b9c0b04027f017e027f017e230041d0006b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001280200417f6a220341044b0d000240024002400240024020030e050004020301000b200141086a28020022034101460d0720034102470d16420221040c080b420121040240200141086a28020022034101460d0020034102470d17420221040b20004105360200200041086a2004370300200041106a200141106a290300370300200241d0006a24000f0b20012d000422034103714101460d034102210520034102470d16200141086a28020021030c040b200141086a22052d0000417f6a220341034b0d16024020030e04000c080a000b2001410c6a2802002101410121030c0c0b200141086a280200417f6a220641034b0d1641042103024020060e0400080d0e000b200141106a2903002104410121030c0d0b200128020422034101460d0420034102470d16200141106a2802002205ad42187e2204422088a70d172004a72203417f4c0d18200141086a28020021012003450d0d2003100122060d0e0c100b413010012203450d0f2003200141086a28020010e001200141056a2d00002101410121050b20004103360200200041086a20033602002000200141ff0171410874200572360204200241d0006a24000f0b200141106a2903002107420121040b20004101360200200041106a2007370300200041086a2004370300200241d0006a24000f0b200141106a2802002203417f4c0d14200141086a2802002106410121014101210502402003450d00200310012205450d0c0b2002200336023c2002200536023820024100360240200241386a41002003102720022002280240220520036a360240200520022802386a20062003101e1a200241286a2002280240360200200220022903383703200c0a0b200141106a2903002104410321030c020b200141106a2903002104410221030c050b200141106a2903002104410421030b0c010b41022103200241206a41026a200541036a2d00003a0000200241c0006a200141206a290000370300200241386a41106a200141286a2d00003a0000200220052f00013b01202002200141186a290000370338200141106a29000021042001410c6a28000021010b200020022f01203b000920004104360200200041086a20033a00002000410c6a2001360200200041106a2004370300200041186a20022903383703002000410b6a200241226a2d00003a0000200041206a200241386a41086a290300370300200041286a200241386a41106a290300370300200241d0006a24000f0b2001410c6a2802002105410321030b200041023602002000410c6a2005360200200041086a2003360200200041106a2004370300200241d0006a24000f0b410421060b20022006360208200241003602102002200536020c200241086a4100200341186d10830120022802102103200228020821062002200136021820022001200541186c6a36021c200241386a200241186a103302402002280238450d002006200341186c6a21010340200241206a41106a2205200241386a41106a290300370300200241206a41086a2206200241386a41086a29030037030020022002290338370320200141106a2005290300370200200141086a200629030037020020012002290320370200200341016a2103200141186a2101200241386a200241186a103320022802380d000b0b200241086a41086a2003360200200241206a41086a200336020020022002290308370320410221010b2000200136020420004100360200200041086a2002290320370200200041106a200241206a41086a280200360200200241d0006a24000f0b101c000b41ec30103b000b41843e103b000b41ac3f103b000b419435103b000b41943b103b000b41ecc100103b000b1060000b1061000b1019000b9d08090e7f017e017f017e017f017e017f017e017f230041306b22022400024002400240024020014108490d00200141017641feffffff07712203417f6a220420014f0d032001410d74200173220541117620057322054105742005732206417f2001417f6a677622077122054100200120052001491b6b220520014f0d01200241086a41206a22082000200441286c6a220441206a2209290300370300200241086a41186a220a200441186a220b290300370300200241086a41106a220c200441106a220d290300370300200241086a41086a220e200441086a220f2903003703002000200541286c6a22052903002110200541086a22112903002112200541106a22132903002114200541186a221529030021162009200541206a2217290300370300200b2016370300200d2014370300200f2012370300200429030021122004201037030020022012370308201720082903003703002015200a2903003703002013200c2903003703002011200e29030037030020052002290308370300200320014f0d022006410d7420067322054111762005732205410574200573220620077122054100200120052001491b6b220520014f0d01200241086a41206a22082000200341286c6a220441206a2209290300370300200241086a41186a220a200441186a220b290300370300200241086a41106a220c200441106a220d290300370300200241086a41086a220e200441086a220f2903003703002000200541286c6a22052903002110200541086a22112903002112200541106a22132903002114200541186a221529030021162009200541206a2217290300370300200b2016370300200d2014370300200f2012370300200429030021122004201037030020022012370308201720082903003703002015200a2903003703002013200c2903003703002011200e290300370300200520022903083703002003410172220420014f0d032006410d742006732205411176200573220541057420057320077122054100200120052001491b6b220520014f0d01200241086a41206a22032000200441286c6a220141206a2204290300370300200241086a41186a2206200141186a2207290300370300200241086a41106a2208200141106a2209290300370300200241086a41086a220a200141086a220b2903003703002000200541286c6a22002903002110200041086a22052903002112200041106a220c2903002114200041186a220d29030021162004200041206a220e2903003703002007201637030020092014370300200b2012370300200129030021122001201037030020022012370308200e2003290300370300200d2006290300370300200c20082903003703002005200a290300370300200020022903083703000b200241306a24000f0b41b4c20020052001103c000b200321040b41ecc20020042001103c000bd808070d7f017e017f017e017f027e027f230041306b2202240002400240024002400240024020014101762203450d0003402003417f6a2203210403402004410174220d41017221160240200d41026a220d20014f0d00201620014f0d06200d20162000200d41286c6a2903002000201641286c6a290300541b21160b0240201620014f0d00200420014f0d042000201641286c6a220d2903002000200441286c6a22042903005a0d00200241086a41206a2205200441206a2206290300370300200241086a41186a2207200441186a2208290300370300200241086a41106a2209200441106a220a290300370300200241086a41086a220b200441086a220c290300370300200d41086a220e290300210f200d41106a22102903002111200d41186a22122903002113200d29030021142006200d41206a221529030037030020082013370300200a2011370300200c200f3703002004290300210f200420143703002002200f370308201520052903003703002012200729030037030020102009290300370300200e200b290300370300200d2002290308370300201621040c010b0b20030d000b0b024020014102490d002001210503402005417f6a220520014f0d06200241086a41206a2206200041206a220d290300370300200241086a41186a2207200041186a2216290300370300200241086a41106a2208200041106a220a290300370300200241086a41086a2209200041086a220b2903003703002000200541286c6a2204290300210f200441086a220c2903002111200441106a220e2903002113200441186a22102903002114200d200441206a221229030037030020162014370300200a2013370300200b2011370300200029030021112000200f370300200220113703082012200629030037030020102007290300370300200e2008290300370300200c2009290300370300200420022903083703004100210403402004410174220d41017221160240200d41026a220d20054f0d00201620054f0d07200d20162000200d41286c6a2903002000201641286c6a290300541b21160b0240201620054f0d00200420054f0d052000201641286c6a220d2903002000200441286c6a22042903005a0d002006200441206a220a2903003703002007200441186a220b2903003703002008200441106a220c2903003703002009200441086a220e290300370300200d41086a2210290300210f200d41106a22122903002111200d41186a22152903002113200d2903002114200a200d41206a2203290300370300200b2013370300200c2011370300200e200f3703002004290300210f200420143703002002200f37030820032006290300370300201520072903003703002012200829030037030020102009290300370300200d2002290308370300201621040c010b0b200541014b0d000b0b200241306a24000f0b418cc30020042001103c000b418cc30020042005103c000b41fcc20020162001103c000b41fcc20020162005103c000b41b4c20020052001103c000bac0904097f017e0e7f017e230041306b22022400200041286a2103200041887f6a2104200041586a21054100210620014132492107410121080240024002400340024002400240200820014f0d002005200841286c6a210903402009290300200941286a2209290300540d0220092109200841016a22082001490d000b0b410021092008200146220a0d030c010b410121092008200146220a0d020b20070d012008417f6a220a20014f0d022009450d032000200a41286c6a2209290300210b20092000200841286c220c6a220a290300370300200241086a41206a220d200941206a220e290300370300200241086a41186a220f200941186a2210290300370300200241086a41106a2211200941106a2212290300370300200241086a41086a2213200941086a22142903003703002014200a41086a22152903003703002012200a41106a22162903003703002010200a41186a2217290300370300200e200a41206a22182903003703002002200b3703082018200d2903003703002017200f2903003703002016201129030037030020152013290300370300200a2002290308370300024020084102490d0020002008417e6a220d41286c6a22192903002009290300220b5a0d00200920192903003703002009290308211a2014201941086a290300370300200f200e29030037030020112010290300370300201320122903003703002012201941106a2903003703002010201941186a290300370300200e201941206a2903003703002002201a3703084100210e0240200d450d002004200c6a2109024003402009290300200b5a0d01200941286a2009290300370300200941c8006a200941206a290300370300200941c0006a200941186a290300370300200941386a200941106a290300370300200941306a200941086a290300370300200941586a2109200d417f6a220d0d000b200941286a21190c010b200941286a2119200d210e0b2019200b3703002000200e41286c6a22092002290308370308200941206a200f290300370300200941186a2011290300370300200941106a20132903003703000b200641016a21060240200120086b22124102490d00200a290300220b200a2903285a0d00200a200a41286a220d290300370300200a290308211a2015200d41086a290300370300200f201829030037030020112017290300370300201320162903003703002016200d41106a2903003703002017200d41186a2903003703002018200d41206a2903003703002002201a37030841012116024020124103490d002003200c6a21094101210e02400340200b200941286a220d2903005a0d01200941206a200941c8006a290300370300200941186a200941c0006a290300370300200941106a200941386a290300370300200941086a200941306a2903003703002009200d290300370300200e41026a2110200e41016a2216210e200d210920102012490d000c020b0b200e21162009210d0b200d200b370300200a201641286c6a22092002290308370308200941206a200f290300370300200941186a2011290300370300200941106a20132903003703000b20064105490d000b4100210a0b200241306a2400200a0f0b41ecc200200a2001103c000b41b4c20020082001103c000b0bdb3b02004180080bec282f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f73657373696f6e2f7372632f6c69622e72737365733a696e647365733a6c656e7365733a6c6c637365733a6e6c6e7365733a76616c00000000002f636865636b6f75742f7372632f6c6962636f72652f6f70732f61726974682e72730000000000000000000000000000617474656d707420746f20646976696465206279207a65726f00000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f616c6c206974656d7320636f6d652066726f6d2060766f74657273603b20666f7220616e206974656d20746f20626520696e2060766f7465727360207468657265206d757374206265206120766f746520726567697374657265643b2071656448617368206e6f7420657175616c52756e74696d65206d656d6f7279206578686175737465642e2041626f7274696e676c6962616c6c6f632f7261775f7665632e72736361706163697479206f766572666c6f7774696d3a64696454696d657374616d70206d7573742062652075706461746564206f6e636520696e2074686520626c6f636b2f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f74696d657374616d702f7372632f6c69622e727374696d3a76616c54696d657374616d70206d7573742062652066697273742065787472696e73696320696e2074686520626c6f636b54696d657374616d70206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b617373657274696f6e206661696c65643a206175782e69735f656d7074792829656e766578745f7365745f73746f726167656578745f6765745f73746f726167656578745f7472616e736665726578745f6372656174656d656d6f727963616c6c002f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f7374616b696e672f7372632f636f6e74726163742e72730000000000000000000000000000000000000000000000000000000000000000007372632f6c69622e72732f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f636f756e63696c2f7372632f6c69622e7273636f753a6e7874636f753a76636f636f753a76626f636f753a767273636f753a617072636f753a6c616374617267657420666f7220696e616374697669747920636c65616e7570206d75737420626520616374697665636f753a766770636f753a63616e616c6c206974656d7320696e2063616e64696461746573206c697374206172652072656769737465726564636f753a726567636f753a63626f636f753a636e6363616e6e6f742070726573656e74206f757473696465206f662070726573656e746174696f6e20706572696f64636f753a737373636f753a707373636f753a77696e6c6561646572626f617264206d757374206578697374207768696c652070726573656e7420706861736520616374697665636f753a61637470726573656e7465642063616e646964617465206d7573742062652063757272656e7463616e646964617465206d757374206e6f7420666f726d2061206475706c696361746564206d656d62657220696620656c656374656463616e646964617465206e6f7420776f72746879206f66206c6561646572626f61726470726573656e746572206d75737420686176652073756666696369656e7420736c61736861626c652066756e647300000000000000002f636865636b6f75742f7372632f6c6962636f72652f736c6963652f6d6f642e7273696e76616c69642063616e64696461746520736c6f7463616e64696461746520686173206e6f7420656e6f7567682066756e64736475706c69636174652063616e646964617465207375626d697373696f6e72657472616374696f6e20696e646578206d69736d6174636872657472616374696f6e20696e64657820696e76616c696463616e6e6f742072657472616374206e6f6e2d766f74657263616e6e6f742072657472616374207768656e2070726573656e74696e676261642074617267657420696e646578626164207265706f7274657220696e64657863616e6e6f74207265617020647572696e67206772616365207065726964766f746520696e646578206e6f742063757272656e74726561706572206d757374206265206120766f74657263616e6e6f74207265617020647572696e672070726573656e746174696f6e20706572696f64617373657274696f6e206661696c65643a202153656c663a3a70726573656e746174696f6e5f6163746976652829636f753a737473636f753a706475636f753a74726d636f753a706572636f753a63636f66696e616c6973652063616e206f6e6c792062652063616c6c656420616674657220612074616c6c7920697320737461727465642e72756e6e6572207570206d757374206265207265676973746572656400617474656d707420746f20646976696465206279207a65726f000000000000002f636865636b6f75742f7372632f6c6962636f72652f6f70732f61726974682e72730000000000000000000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f53746f7261676520726f6f74206d757374206d6174636820746861742063616c63756c617465642e2f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f6578656375746976652f7372632f6c69622e7273617373657274696f6e206661696c65643a206865616465722e6469676573742829203d3d20263c73797374656d3a3a4d6f64756c653c53797374656d3e3e3a3a6469676573742829416c6c207472616e73616374696f6e732073686f756c6420686176652074686520636f7272656374206e6f6e6365416c6c207472616e73616374696f6e732073686f756c642062652070726f7065726c79207369676e65645472616e73616374696f6e207472696520726f6f74206d7573742062652076616c69642e506172656e7420686173682073686f756c642062652076616c69642e7374726f616765206973206e6f74206e756c6c2c207468657265666f7265206d75737420626520612076616c696420747970656c6962636f72652f726573756c742e727373657269616c697a656420617267732073686f756c642062652070726f7669646564206279207468652072756e74696d653b0a090909636f72726563746c792073657269616c697a656420646174612073686f756c6420626520646573657269616c697a61626c653b0a0909097165642f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652d73616e64626f782f7372632f2e2e2f776974686f75745f7374642e72732f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f7374616b696e672f7372632f6c69622e72737374613a6c65637374613a7370657374613a6572617374613a6e73657374613a77696c3a7374613a7661630000000000000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f000000000000002f636865636b6f75742f7372632f6c6962636f72652f6f70732f61726974682e72737374613a6c6f63617373657274696f6e206661696c65643a20746f5f62616c616e6365202b2076616c7565203e20746f5f62616c616e6365617373657274696f6e206661696c65643a203c426f6e646167653c543e3e3a3a676574287472616e736163746f7229203c3d203c426f6e646167653c543e3e3a3a676574286465737429617373657274696f6e206661696c65643a2066726f6d5f62616c616e6365203e3d2076616c756543616e6e6f7420756e7374616b65206966206e6f7420616c7265616479207374616b65642e43616e6e6f74207374616b6520696620616c7265616479207374616b65642e7374613a666565617474656d707420746f207472616e7361637420776974686f757420656e6f7567682066756e647320746f20706179206665657374613a746f74617373657274696f6e206661696c65643a20266465737420213d207472616e736163746f72617373657274696f6e206661696c65643a2062203e3d2076616c756573746f72616765206973206e6f74206e756c6c2c207468657265666f7265206d75737420626520612076616c6964207479706552657175697265642076616c756573206d75737420626520696e2073746f726167652f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f636f756e63696c2f7372632f766f74696e672e7273636f763a706572696f64636f763a70726f636f763a707273636f763a766f74653a636f763a766f746572733a636f763a636f6f6c6f6666636f763a7665746f3a70726f706f73616c206d75737420657869737420746f206265207665746f65646f6e6c7920636f756e63696c6c6f7273206d6179207665746f20636f756e63696c2070726f706f73616c73617373657274696f6e206661696c65643a202153656c663a3a69735f7665746f6564282670726f706f73616c5f68617368294e6f206475706c69636174652070726f706f73616c7320616c6c6f776564617373657274696f6e206661696c65643a2053656c663a3a77696c6c5f7374696c6c5f62655f636f756e63696c6c6f725f6174286175782e7265665f696e746f28292c2065787069727929616c6c207175657565642070726f706f73616c20686173686573206d7573742068617665206173736f6369617465642070726f706f73616c732f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f64656d6f63726163792f7372632f6c69622e727364656d3a6c617564656d3a707562416c6c2063757272656e74207075626c69632070726f706f73616c73206861766520616e20616d6f756e74206c6f636b65646465706f7369746f727320616c7761797320657869737420666f722063757272656e742070726f706f73616c7364656d3a70657264656d3a6e787464656d3a72636f43616e6e6f7420696e6a6563742061207265666572656e64756d207468617420656e6473206561726c696572207468616e2070726563656564696e67207265666572656e64756d63616c6c656420604f7074696f6e3a3a756e77726170282960206f6e206120604e6f6e65602076616c75656c6962636f72652f6f7074696f6e2e7273002f636865636b6f75742f7372632f6c6962636f72652f736c6963652f6d6f642e72730000000000000000000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f000000000000002f636865636b6f75742f7372632f6c6962636f72652f6f70732f61726974682e727364656d3a6d696e64656d3a70706363616e206f6e6c79207365636f6e6420616e206578697374696e672070726f706f73616c7472616e736163746f72206d75737420686176652062616c616e636520746f207369676e616c20617070726f76616c2e766f746520676976656e20666f7220696e76616c6964207265666572656e64756d2e617373657274696f6e206661696c65643a203c7374616b696e673a3a4d6f64756c653c543e3e3a3a6465647563745f756e626f6e646564286175782e7265665f696e746f28292c206465706f7369742e3029617373657274696f6e206661696c65643a203c7374616b696e673a3a4d6f64756c653c543e3e3a3a6465647563745f756e626f6e646564286175782e7265665f696e746f28292c2076616c756529617373657274696f6e206661696c65643a2076616c7565203e3d2053656c663a3a6d696e696d756d5f6465706f736974282900000000000000002f636865636b6f75742f7372632f6c6962636f72652f736c6963652f6d6f642e727300000000000000000000000000002f636865636b6f75742f7372632f6c6962616c6c6f632f736c6963652e7273696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f64652f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f636f6e73656e7375732f7372632f6c69622e72733a617574683a7379733a6f6c640000007379733a6e756d7379733a7068617379733a7478727379733a726e647379733a787469426c6f636b206e756d626572206d6179206e65766572206265207a65726f2f55736572732f726f626572742f70726f6a656374732f6574682f706f6c6b61646f742f7375627374726174652f72756e74696d652f73797374656d2f7372632f6c69622e72737379733a6e6f6e7379733a7874647379733a6469676c656e5f5f5068616e746f6d4974656d2073686f756c64206e6576657220626520757365642e3a636f6465000000000000002f636865636b6f75742f7372632f6c6962636f72652f736c6963652f736f72742e7273617373657274696f6e206661696c65643a206d6964203c3d206c656e6c6962636f72652f736c6963652f6d6f642e7273000000000000000000000000002f636865636b6f75742f7372632f6c6962636f72652f736c6963652f6d6f642e7273617373657274696f6e206661696c65643a20696e646578203c3d206c656e6c6962616c6c6f632f7665632e7273617373657274696f6e206661696c65643a20696e646578203c206c656e0041ec300be0124f1600002800000000040000480000003300000001000000711700002300000000040000480000003300000001000000a0040000190000007004000022000000c50100002d000000c00400003900000070040000220000001a0200002d0000004f160000280000001f0e0000530000006f000000090000004f160000280000001f0e00005300000078000000090000009c050000110000008905000013000000e502000005000000df17000014000000d008000005000000df17000014000000d608000005000000fe130000110000009203000005000000b40500002b000000df0500004a0000004b000000030000007117000023000000df0500004a0000002b000000010000008e06000020000000df0500004a00000041000000030000005e06000030000000df0500004a0000004200000003000000300600002e000000df0500004a0000004300000003000000f00600004d0000008700000012000000f00600004d0000008800000012000000f00600004d000000890000000f000000f00600004d0000007000000019000000f00600004d0000007100000019000000f00600004d000000720000000f000000f00600004d0000005e00000016000000f00600004d0000005f00000012000000f00600004d0000003d00000016000000f00600004d0000003e00000018000000f00600004d0000003f000000130000004f16000028000000df0500004a0000002b000000010000005e0700000a000000a8000000020000004f1600002800000068070000480000006500000001000000711700002300000068070000480000006500000001000000ed0a00002e0000006807000048000000e3000000030000006807000048000000e400000003000000c70a0000260000006807000048000000f800000003000000b10a0000160000006807000048000000f9000000030000009b0a0000160000006807000048000000fb000000030000007d0a00001e0000006807000048000000fc000000030000008009000022000000200900000a0000006b0a000012000000680700004800000000010000030000005b0a000010000000680700004800000001010000030000003d0a00001e00000068070000480000001b01000003000000250a00001800000068070000480000001c010000030000000d0a00001800000068070000480000001f01000003000000f40900001900000068070000480000002001000003000000d60900001e00000068070000480000002901000003000000b80900001e00000068070000480000002a01000003000000a20900001600000068070000480000002f010000030000008009000022000000260900000e000000680700004800000044010000030000004a0900002e00000068070000480000004a01000003000000270900002300000068070000480000004d01000003000000f1080000360000006807000048000000500100000400000080090000220000003c02000023000000e00b000039000000b00b0000220000001a0200002d000000900b000019000000b00b000022000000c50100002d0000004f0d00001c000000410c00004a00000050000000030000002b0d000024000000410c00004a00000058000000030000008b0c000048000000410c00004a0000009c00000003000000190c000028000000410c00004a000000a400000003000000010d00002a000000410c00004a000000850000000e000000d30c00002e000000410c00004a0000008b000000040000009e0d000011000000b1030000050000004f160000280000001f0e00005300000008010000090000004f16000028000000720e0000480000005b00000001000000f00e000039000000300f0000220000001a0200002d000000201000001f000000720e000048000000c800000003000000fb0f000025000000720e000048000000d6000000040000007117000023000000720e0000480000005b00000001000000d40f000027000000720e00004800000030020000030000008a0f00004a000000720e0000480000003302000003000000590f000031000000720e00004800000034020000030000000600000000000000010000000700000008000000090000000a0000000b0000000c0000000d0000004610000033000000720e0000480000005702000003000000d40f000027000000720e00004800000016020000030000008010000025000000720e00004800000022020000030000000e00000018000000040000000f000000100000001100000012000000130000001400000015000000a51000001c000000720e00004800000015010000030000004f16000028000000161100004b0000001b000000010000007117000023000000161100004b0000001b000000010000003c1200004b000000161100004b0000004e000000030000001e1200001e000000161100004b0000005200000003000000ec11000032000000161100004b0000005300000003000000c11100002b000000161100004b0000006900000003000000a111000020000000161100004b0000006a000000030000004f16000028000000c01200004a0000003900000001000000401400003900000080140000220000001a0200002d00000010140000220000003c02000023000000d31300002b000000fe130000110000004f010000150000008c13000047000000c01200004a000000d9000000040000007117000023000000c01200004a0000003900000001000000c615000032000000c01200004a0000009300000003000000781500004e000000c01200004a00000094000000030000002615000052000000c01200004a000000a2000000030000000415000022000000c01200004a000000ac00000004000000d414000030000000c01200004a000000af000000040000000016000022000000200900000a0000000016000022000000260900000e000000301600001f000000b20200001e000000301600001f000000b5020000360000004f16000028000000771600004a0000003b00000001000000f41600001e00000012170000470000007d000000030000007117000023000000771600004a0000003b0000000100000000180000220000003d02000023000000c31700001c000000df17000014000000cc0100000d000000a017000023000000910200001d00000000180000220000003c02000023000000a017000023000000a70000003a000000a017000023000000ae00000030000000221800001e000000401800000f00000047030000090000004f1800001d000000401800000f0000006f03000009000000000c076c696e6b696e670302cc3b00ff8401046e616d6501f68401e40100146578745f6765745f73746f726167655f696e746f010a6578745f6d616c6c6f6302086578745f66726565030c6578745f74776f785f313238040f6578745f7365745f73746f7261676505116578745f636c6561725f73746f72616765060a6578745f6d656d636d7007186578745f656e756d6572617465645f747269655f726f6f74080e6578745f7072696e745f75746638090d6578745f7072696e745f6e756d0a0a6578745f6d656d6370790b0b6578745f6d656d6d6f76650c0a6578745f6d656d7365740d166578745f73616e64626f785f6d656d6f72795f6e65770e176578745f73616e64626f785f696e7374616e74696174650f126578745f73616e64626f785f696e766f6b6510166578745f73616e64626f785f6d656d6f72795f67657411166578745f73616e64626f785f6d656d6f72795f736574120e6578745f626c616b65325f323536130d6578745f7072696e745f68657814106578745f73746f726167655f726f6f7415126578745f656432353531395f76657269667916773c7375627374726174655f72756e74696d655f7072696d6974697665733a3a67656e657269633a3a4469676573743c4974656d3e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a686366613333306530633737643531613517066d656d73657418393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a6838313936363666396265663463633931194b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68646339636565313232303362623835621a4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68353632363038323130343238623465631b4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68653335663962326562366332393066621c24616c6c6f633a3a616c6c6f633a3a6f6f6d3a3a68613732396634666436376436376633391d8b013c7375627374726174655f72756e74696d655f7072696d6974697665733a3a67656e657269633a3a4865616465723c4e756d6265722c20486173682c204469676573744974656d3e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a68306561356233376164373865313636341e066d656d6370791f573c616c6c6f633a3a7665633a3a5665633c75383e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a683135633166653139313338396266313020a0013c7375627374726174655f72756e74696d655f7072696d6974697665733a3a67656e657269633a3a556e636865636b656445787472696e7369633c4163636f756e7449642c20496e6465782c2043616c6c2c205369676e61747572653e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a686666343637646332363738333264373321583c616c6c6f633a3a626f7865643a3a426f783c543e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a683733356130396161356431326165663322345f5a4e34636f726533707472313364726f705f696e5f706c61636531376834616536316365303665356638316331452e3138363723393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a6835646661343736643064326634353464244b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6831623238376135353263616531393734252b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a683461653631636530366535663831633126a0013c7375627374726174655f72756e74696d655f7072696d6974697665733a3a67656e657269633a3a556e636865636b656445787472696e7369633c4163636f756e7449642c20496e6465782c2043616c6c2c205369676e61747572653e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a656e636f64653a3a6862346461326637656565363934383334273a3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a726573657276653a3a6861623665336266623631626431356231285a3c706f6c6b61646f745f72756e74696d653a3a43616c6c206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a656e636f64653a3a68393931323239363862316130396334322934636f72653a3a736c6963653a3a736c6963655f696e6465785f6c656e5f6661696c3a3a68363938393263393438396363616162622a363c5420617320636f72653a3a636f6e766572743a3a496e746f3c553e3e3a3a696e746f3a3a68353666353936643634373237343833632b8d015f5a4e34395f244c5424616c6c6f632e2e7261775f7665632e2e526177566563244c54245424432424753230244124475424244754243131616c6c6f636174655f696e32385f24753762242475376224636c6f737572652475376424247537642431376838343739373131363565646633646537452e6c6c766d2e3632303339333138363734383337373033382c493c7375627374726174655f72756e74696d655f73657373696f6e3a3a4d6f64756c653c543e3e3a3a726f746174655f73657373696f6e3a3a68663938353764613535613230616562632d2e636f72653a3a6f7074696f6e3a3a6578706563745f6661696c65643a3a68653163323536643932353565393632662e463c7375627374726174655f72756e74696d655f73797374656d3a3a4d6f64756c653c543e3e3a3a626c6f636b5f6e756d6265723a3a68313635316433343866326134346235372f527375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653a3a726571756972653a3a6861313164373161613165393864646363304b3c54206173207375627374726174655f636f6465633a3a6b657965647665633a3a4b657965645665633e3a3a746f5f6b657965645f7665633a3a6866346339626432626430633262303964314f7375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765745f6f725f64656661756c743a3a6837623835343430353965333637333638324b3c54206173207375627374726174655f636f6465633a3a6b657965647665633a3a4b657965645665633e3a3a746f5f6b657965645f7665633a3a686466633130663239626637643964313133523c636f72653a3a697465723a3a436c6f6e65643c493e20617320636f72653a3a697465723a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a683032316562386262636530636661323334583c28412c204229206173207375627374726174655f72756e74696d655f7072696d6974697665733a3a7472616974733a3a45786563757461626c653e3a3a657865637574653a3a6863373034616135306561623165643139359f017375627374726174655f72756e74696d655f636f756e63696c3a3a766f74696e673a3a3c696d706c207375627374726174655f72756e74696d655f7072696d6974697665733a3a7472616974733a3a45786563757461626c6520666f72207375627374726174655f72756e74696d655f636f756e63696c3a3a4d6f64756c653c543e3e3a3a657865637574653a3a683730353563353930613161356165386336597375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653a3a6765745f6f725f64656661756c743a3a686432656434346461383333643033393337473c7375627374726174655f72756e74696d655f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a6465706f7369745f6f663a3a6864356630353863656136333834623032382b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a683436373662323538363033663731396439076d656d6d6f76653a563c616c6c6f633a3a7665633a3a5665633c543e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a68653630626561346331643730393736643b29636f72653a3a70616e69636b696e673a3a70616e69633a3a68313137323734323133346465393231303c36636f72653a3a70616e69636b696e673a3a70616e69635f626f756e64735f636865636b3a3a68363630346666363535326232666562323d413c7375627374726174655f72756e74696d655f7374616b696e673a3a4d6f64756c653c543e3e3a3a726566756e643a3a68633362613564623165383537303661313e86013c7375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a52756e74696d6553746f72616765206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a68656161636164343939313263336335363f4e3c7375627374726174655f72756e74696d655f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a696e6a6563745f7265666572656e64756d3a3a6863653264346134373837396137323635404c3c7375627374726174655f72756e74696d655f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a7265666572656e64756d5f696e666f3a3a68356430386136656330613537303133384134616c6c6f633a3a7261775f7665633a3a63617061636974795f6f766572666c6f773a3a686334316261316636346437363033373942473c7375627374726174655f72756e74696d655f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a766f746572735f666f723a3a686539303831303936616133363162333843473c7375627374726174655f72756e74696d655f7374616b696e673a3a4d6f64756c653c543e3e3a3a667265655f62616c616e63653a3a6862653837643063316262386365323731444b3c7375627374726174655f72756e74696d655f7374616b696e673a3a4d6f64756c653c543e3e3a3a72657365727665645f62616c616e63653a3a6865623966656232366134653538343433453e7375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653a3a656e636f64653a3a6835666661663632366231656464306238464d3c7375627374726174655f72756e74696d655f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a636c6561725f7265666572656e64756d3a3a683065326261346565363332393465346547597375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653a3a6765745f6f725f64656661756c743a3a686364633932303862653939363865303148423c7375627374726174655f72756e74696d655f7374616b696e673a3a4d6f64756c653c543e3e3a3a6e65775f6572613a3a6834333536343534386630353530373663493a3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a726573657276653a3a68666363653264376532363234386132664a86013c7375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a52756e74696d6553746f72616765206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a68383237346662353239326530653935384b345f5a4e34636f726533707472313364726f705f696e5f706c61636531376834616536316365303665356638316331452e313933304c6d3c7375627374726174655f72756e74696d655f696f3a3a426c616b6554776f323536206173207375627374726174655f72756e74696d655f696f3a3a48617368696e673e3a3a656e756d6572617465645f747269655f726f6f743a3a68373531363037396363363934643362344d11727573745f626567696e5f756e77696e644e08727573745f6f6f6d4f393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a683934323963666464366239343939316550463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a686638333437636630333536663137633751573c616c6c6f633a3a7665633a3a5665633c75383e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a656e636f64653a3a683562613039363631356162393163653352066d616c6c6f63530466726565542d636f72653a3a70616e69636b696e673a3a70616e69635f666d743a3a68343066313034346338363430636537655536636f72653a3a736c6963653a3a736c6963655f696e6465785f6f726465725f6661696c3a3a6838313330343432303532386232613865564b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6832653739643730623164373537336236574b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6834333337316334333361323734393066584b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6835653639393561353131376336316261594b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68393332616436626561643261373838325a4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68643335646131306634323134323937335b4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68306464323861643233626338353865665c4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68323236353666303366323931393738325d4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68626461366634636434623039663433665e4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68303139363230336638363464396133345f4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6862396532346165643662353163376566604b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6863613166626538323365653436383431614b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6862323236663235303162633264306264624b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6836333364303435386436356363393863634b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6866616563633135353361633333613835644b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6861356133316562653333306639326635654b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6832376361366365373461626664666264664b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a6836323932333830613439323131383638674b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a686163306336633862333061653039663768393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a683063653362633633326336616364326169463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68376636633966373761363663373937636a393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a68343038373662383637653261396330396b463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68383863616164303861633361623961646c393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a68353262366336626163626135633061386d463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68623437366264373632363935623330336e463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68326132353062613265323263336337396f393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a683636323532376436666130383237343470463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a683365363965636439633766616165306371393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a683764313835303766636661646366353972463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a686335663366366638303064303431353273463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a683738366438643636323036316564613074393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a686261353735613734386133306233306375463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a686532653262373435333764623266386476393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a686461363738663731646162613761666577463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a683863323961323539383931333766343978393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a686463356361653038383331346337376679463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68326161633766383935303734356563397a393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a68646433633635373262343532613031347b463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68626462393236656664376432346539387c393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a68653333366232306266663138383930347d463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68346633396332623430636437333963347e393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a68653338643736373866303134323236317f463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a68363862383536613030333235623134628001393c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a68656330653961326130616435633466648101463c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a646f75626c653a3a7b7b636c6f737572657d7d3a3a683838636134306365646335303261316282013a3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a726573657276653a3a683534343836366335623963663730373583013a3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a726573657276653a3a683734393131616635323537633037393784013a3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a726573657276653a3a683735663262666638613830643365623985013a3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a726573657276653a3a683863616636616537333938376436346386013a3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a726573657276653a3a68653033623365323432663733346433308701503c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68393537643736623535353030646266348801c3013c616c6c6f633a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75743c27613e2c204b2c20562c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4c6561663e2c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3e3a3a696e736572743a3a68353731386465393136646662313737328901c3013c616c6c6f633a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75743c27613e2c204b2c20562c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4c6561663e2c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3e3a3a696e736572743a3a68373463373532366661626363646564358a01c7013c616c6c6f633a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75743c27613e2c204b2c20562c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a496e7465726e616c3e2c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3e3a3a696e736572743a3a68343437336564333066636136316137308b01cb013c616c6c6f633a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75743c27613e2c204b2c20562c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a496e7465726e616c3e2c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3e3a3a696e736572745f6669743a3a68326333636630383765623331663734338c01c7013c616c6c6f633a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75743c27613e2c204b2c20562c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a496e7465726e616c3e2c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3e3a3a696e736572743a3a68386365653235383631313166343439668d01cb013c616c6c6f633a3a62747265653a3a6e6f64653a3a48616e646c653c616c6c6f633a3a62747265653a3a6e6f64653a3a4e6f64655265663c616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a4d75743c27613e2c204b2c20562c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a496e7465726e616c3e2c20616c6c6f633a3a62747265653a3a6e6f64653a3a6d61726b65723a3a456467653e3e3a3a696e736572745f6669743a3a68663630346163643262623861646636648e013f7375627374726174655f72756e74696d655f7374616b696e673a3a636f6e74726163743a3a657865637574653a3a68666332303937306166616238363265658f01507375627374726174655f72756e74696d655f7374616b696e673a3a636f6e74726163743a3a657865637574653a3a6578745f7365745f73746f726167653a3a68633235623630316631346635383463389001507375627374726174655f72756e74696d655f7374616b696e673a3a636f6e74726163743a3a657865637574653a3a6578745f6765745f73746f726167653a3a683736613962653764306632343937316491014d7375627374726174655f72756e74696d655f7374616b696e673a3a636f6e74726163743a3a657865637574653a3a6578745f7472616e736665723a3a683632326464636435333464616431363892014b7375627374726174655f72756e74696d655f7374616b696e673a3a636f6e74726163743a3a657865637574653a3a6578745f6372656174653a3a68396363303263356565333664303032379301417375627374726174655f72756e74696d655f73616e64626f783a3a696d703a3a64697370617463685f7468756e6b3a3a683939386139316165306131663037633594017f3c7375627374726174655f72756e74696d655f7374616b696e673a3a4f7665726c61794163636f756e7444623c27612c20543e206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a7365745f73746f726167653a3a683035373136666235306661623636643395017f3c7375627374726174655f72756e74696d655f7374616b696e673a3a4f7665726c61794163636f756e7444623c27612c20543e206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a683031326363613031653639396364643996013b3c616c6c6f633a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e3e3a3a6765743a3a6865383334633533623431306361303264970134616c6c6f633a3a62747265653a3a7365617263683a3a7365617263685f747265653a3a68613435343266643037623530613430349801653c616c6c6f633a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e20617320636f72653a3a697465723a3a7472616974733a3a496e746f4974657261746f723e3a3a696e746f5f697465723a3a68323337613934396465633834333065369901553c616c6c6f633a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68663765393037343761386636613332309a01453c616c6c6f633a3a62747265653a3a6d61703a3a566163616e74456e7472793c27612c204b2c20563e3e3a3a696e736572743a3a68616639316138373166656365356538369b017c3c7375627374726174655f72756e74696d655f7374616b696e673a3a4f7665726c61794163636f756e7444623c27612c20543e206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6765745f636f64653a3a68636634333438326462356135353864349c01793c7375627374726174655f72756e74696d655f7374616b696e673a3a4f7665726c61794163636f756e7444623c27612c20543e206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6d657267653a3a68306134623934346339646231343665329d01653c616c6c6f633a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e20617320636f72653a3a697465723a3a7472616974733a3a496e746f4974657261746f723e3a3a696e746f5f697465723a3a68336331666362643134643933623735619e01553c616c6c6f633a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68626262323936373561396334396234399f012e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a6866313734613335313966343639373764a0016c3c7375627374726174655f72756e74696d655f64656d6f63726163793a3a5072697643616c6c3c543e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a6836313935643931346137663363333636a1010b617574686f726974696573a201563c616c6c6f633a3a7665633a3a5665633c543e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a656e636f64653a3a6834663037313434396230306561366362a30110696e697469616c6973655f626c6f636ba401443c7375627374726174655f72756e74696d655f73797374656d3a3a4d6f64756c653c543e3e3a3a696e697469616c6973653a3a6832326337643330356130373863393035a5010f6170706c795f65787472696e736963a601783c7375627374726174655f72756e74696d655f6578656375746976653a3a4578656375746976653c53797374656d2c20426c6f636b2c205061796d656e742c2046696e616c69736174696f6e3e3e3a3a6170706c795f65787472696e7369635f696e6e65723a3a6836303438333536646465653962326663a7010d657865637574655f626c6f636ba801443c7375627374726174655f72756e74696d655f73797374656d3a3a4d6f64756c653c543e3e3a3a626c6f636b5f686173683a3a6838333036626630323533366265386266a901523c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20493e3e3a3a66726f6d5f697465723a3a6863383933623037366263653438356361aa01423c7375627374726174655f72756e74696d655f73797374656d3a3a4d6f64756c653c543e3e3a3a66696e616c6973653a3a6835643638333133636232646637366465ab010e66696e616c6973655f626c6f636bac010f76616c696461746f725f636f756e74ad010a76616c696461746f7273ae01793c7375627374726174655f72756e74696d655f636f756e63696c3a3a43616c6c3c543e206173207375627374726174655f72756e74696d655f737570706f72743a3a64697370617463683a3a417578446973706174636861626c653e3a3a64697370617463683a3a6836363435303363376332313138323333af01563c55206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a6578697374733a3a6837323366316130366637356338376235b001473c7375627374726174655f72756e74696d655f636f756e63696c3a3a4d6f64756c653c543e3e3a3a72656d6f76655f766f7465723a3a6837326137643235373861356638346333b101563c55206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6830396163353435653961376538333833b2014a3c7375627374726174655f72756e74696d655f7374616b696e673a3a4d6f64756c653c543e3e3a3a6465647563745f756e626f6e6465643a3a6835366234393235363039633261333763b3014c3c7375627374726174655f72756e74696d655f636f756e63696c3a3a4d6f64756c653c543e3e3a3a766f7465725f6c6173745f6163746976653a3a6862336538666236373336303764663063b401473c7375627374726174655f72756e74696d655f636f756e63696c3a3a4d6f64756c653c543e3e3a3a617070726f76616c735f6f663a3a6865333163643561323839663761303839b5014d3c7375627374726174655f72756e74696d655f636f756e63696c3a3a4d6f64756c653c543e3e3a3a63616e6469646174655f7265675f696e666f3a3a6866303561313635613136333135646633b601563c616c6c6f633a3a7665633a3a5665633c543e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a6831613262363530646163366431306537b70186013c7375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a52756e74696d6553746f72616765206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a6866373862303163316265363933623132b801563c616c6c6f633a3a7665633a3a5665633c543e206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a656e636f64653a3a6862636662316161343963386239396538b901543c636f72653a3a697465723a3a436861696e3c412c20423e20617320636f72653a3a697465723a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6839313464643736343236613933323338ba01563c7375627374726174655f72756e74696d655f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a696e7465726e616c5f73746172745f7265666572656e64756d3a3a6864663562353935316539353236643238bb01527375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653a3a726571756972653a3a6862646338666238653461356339396261bc0186013c7375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a52756e74696d6553746f72616765206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a6836363231356566633664633732336432bd015e3c706f6c6b61646f745f72756e74696d653a3a5072697643616c6c206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a6465636f64653a3a6836636664343364363366653539376139be013e7375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653a3a656e636f64653a3a6834356437316332383730346338366538bf01345f5a4e34636f726533707472313364726f705f696e5f706c61636531376834616536316365303665356638316331452e31383434c001473c7375627374726174655f72756e74696d655f73797374656d3a3a4d6f64756c653c543e3e3a3a6163636f756e745f696e6465783a3a6830663032313835306531326631353532c1016d3c706f6c6b61646f745f72756e74696d653a3a43616c6c206173207375627374726174655f72756e74696d655f737570706f72743a3a64697370617463683a3a417578446973706174636861626c653e3a3a64697370617463683a3a6862353365306137383562356439313664c2012e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a6835636361383862626431396436663637c3012e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a6861636366363539333334346266343932c4012d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6865653866663861633636343163366337c501563c55206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6836643335643961613335663530373466c601773c7375627374726174655f72756e74696d655f7374616b696e673a3a4469726563744163636f756e744462206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6839366364653364613533393430373432c701713c7375627374726174655f72756e74696d655f7374616b696e673a3a4469726563744163636f756e744462206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6d657267653a3a6863386138646538333035626335356661c8015e3c616c6c6f633a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a697465723a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6839663430373961306139316533623539c901563c55206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6839633838336432616334356335643565ca015e3c616c6c6f633a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a697465723a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6831353032303864643239373239616232cb013e7375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653a3a656e636f64653a3a6866653733303335653834393636616231cc012b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6837313232393564313131373938333732cd01773c7375627374726174655f72756e74696d655f7374616b696e673a3a4469726563744163636f756e744462206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a6865626533633663393533393837616132ce01743c7375627374726174655f72756e74696d655f7374616b696e673a3a4469726563744163636f756e744462206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6765745f636f64653a3a6837376330653737383334326563333934cf01773c7375627374726174655f72756e74696d655f7374616b696e673a3a4469726563744163636f756e744462206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a7365745f73746f726167653a3a6862663865653331383633303066393130d001743c7375627374726174655f72756e74696d655f7374616b696e673a3a4469726563744163636f756e744462206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a7365745f636f64653a3a6834393266643631333433343565656533d101773c7375627374726174655f72756e74696d655f7374616b696e673a3a4469726563744163636f756e744462206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a7365745f62616c616e63653a3a6861303936363266636534323061373632d2013e3c616c6c6f633a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e3e3a3a696e736572743a3a6863313238323330343366616132306235d3012b636f72653a3a7074723a3a64726f705f696e5f706c6163653a3a6862623666313834333462363831646364d4017f3c7375627374726174655f72756e74696d655f7374616b696e673a3a4f7665726c61794163636f756e7444623c27612c20543e206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6864333339636666326536626431326136d5017c3c7375627374726174655f72756e74696d655f7374616b696e673a3a4f7665726c61794163636f756e7444623c27612c20543e206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a7365745f636f64653a3a6832353031306366393163383531653633d6017f3c7375627374726174655f72756e74696d655f7374616b696e673a3a4f7665726c61794163636f756e7444623c27612c20543e206173207375627374726174655f72756e74696d655f7374616b696e673a3a4163636f756e7444623c543e3e3a3a7365745f62616c616e63653a3a6835663038363634343266663639663034d70186013c7375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a52756e74696d6553746f72616765206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a6833663831363961656164316536306634d8015e3c706f6c6b61646f745f72756e74696d653a3a5072697643616c6c206173207375627374726174655f636f6465633a3a736c696361626c653a3a536c696361626c653e3a3a656e636f64653a3a6864323261663136323532663732653865d901587375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653a3a74616b655f6f725f70616e69633a3a6865373635393838373032386265316365da01597375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653a3a6765745f6f725f64656661756c743a3a6834623732396637663566373061363932db0181013c7375627374726174655f72756e74696d655f636f756e63696c3a3a766f74696e673a3a43616c6c3c543e206173207375627374726174655f72756e74696d655f737570706f72743a3a64697370617463683a3a417578446973706174636861626c653e3a3a64697370617463683a3a6830653834363332383930313361343764dc014a3c7375627374726174655f72756e74696d655f636f756e63696c3a3a766f74696e673a3a4d6f64756c653c543e3e3a3a7665746f5f6f663a3a6862306633653061333063356237626537dd01563c55206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6834336534383363363337326338613963de01563c55206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6866323533306336323935613261646262df01563c55206173207375627374726174655f72756e74696d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6863373164346434623063343438383037e0014c3c706f6c6b61646f745f72756e74696d653a3a5072697643616c6c20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6833623430356561333864626335613735e10134636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6836346333343639613537386236366265e2012e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6830386534373738303065643562646365e3013c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6838643731323265613337623036313336", + "0x0346fb0f1ce64e1a02c4959d38ebad38": "0x00000000" +}}, +"bootNodes": [ + "/ip4/104.211.54.233/tcp/30333/p2p/QmRMGcQh69t8a8YwzHkofVo9SFr7ffggUwhAYjVSTChmrd", + "/ip4/104.211.48.51/tcp/30333/p2p/QmWCnXrhM1in1qPqVT3rDXQEJHedAzbPDMimdjqy2P9fGn", + "/ip4/104.211.48.247/tcp/30333/p2p/QmY33GW69TnTsdQWjAkxJR1GrWTdeV1PmzzcSmUay4HvAB", + "/ip4/40.114.120.164/tcp/30333/p2p/QmWzYU5X1NpFrprD1YZF5Lcj9aE5WF4QEg5FpvQx5XGWG7", + "/ip4/40.117.153.33/tcp/30333/p2p/QmSz8qCADMmi92QB8dTqMPu56JYQQKZBAHz7y8KXjvqcvW" +], +"telemetryUrl": "wss://telemetry.polkadot.io/submit/" +} diff --git a/polkadot/service/src/chain_spec.rs b/polkadot/service/src/chain_spec.rs new file mode 100644 index 0000000000000..dcf487de0bd2d --- /dev/null +++ b/polkadot/service/src/chain_spec.rs @@ -0,0 +1,191 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Polkadot chain configurations. + +use ed25519; +use primitives::AuthorityId; +use polkadot_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfig, + SessionConfig, StakingConfig, TimestampConfig}; +use service::ChainSpec; + +const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; + +pub fn poc_1_testnet_config() -> Result, String> { + ChainSpec::from_embedded(include_bytes!("../res/krummelanke.json")) +} + +fn staging_testnet_config_genesis() -> GenesisConfig { + let initial_authorities = vec![ + hex!["82c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf5"].into(), + hex!["4de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7"].into(), + hex!["063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca5"].into(), + hex!["8101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c"].into(), + ]; + let endowed_accounts = vec![ + hex!["f295940fa750df68a686fcf4abd4111c8a9c5a5a5a83c4c8639c451a94a7adfd"].into(), + ]; + GenesisConfig { + consensus: Some(ConsensusConfig { + code: include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm").to_vec(), // TODO change + authorities: initial_authorities.clone(), + }), + system: None, + session: Some(SessionConfig { + validators: initial_authorities.iter().cloned().map(Into::into).collect(), + session_length: 60, // that's 5 minutes per session. + broken_percent_late: 50, + }), + staking: Some(StakingConfig { + current_era: 0, + intentions: initial_authorities.iter().cloned().map(Into::into).collect(), + transaction_base_fee: 100, + transaction_byte_fee: 1, + existential_deposit: 500, + transfer_fee: 0, + creation_fee: 0, + reclaim_rebate: 0, + early_era_slash: 10000, + session_reward: 100, + balances: endowed_accounts.iter().map(|&k|(k, 1u128 << 60)).collect(), + validator_count: 12, + sessions_per_era: 12, // 1 hour per era + bonding_duration: 24, // 1 day per bond. + }), + democracy: Some(DemocracyConfig { + launch_period: 12 * 60 * 24, // 1 day per public referendum + voting_period: 12 * 60 * 24 * 3, // 3 days to discuss & vote on an active referendum + minimum_deposit: 5000, // 12000 as the minimum deposit for a referendum + }), + council: Some(CouncilConfig { + active_council: vec![], + candidacy_bond: 5000, // 5000 to become a council candidate + voter_bond: 1000, // 1000 down to vote for a candidate + present_slash_per_voter: 1, // slash by 1 per voter for an invalid presentation. + carry_count: 6, // carry over the 6 runners-up to the next council election + presentation_duration: 12 * 60 * 24, // one day for presenting winners. + approval_voting_period: 12 * 60 * 24 * 2, // two days period between possible council elections. + term_duration: 12 * 60 * 24 * 24, // 24 day term duration for the council. + desired_seats: 0, // start with no council: we'll raise this once the stake has been dispersed a bit. + inactive_grace_period: 1, // one addition vote should go by before an inactive voter can be reaped. + + cooloff_period: 12 * 60 * 24 * 4, // 4 day cooling off period if council member vetoes a proposal. + voting_period: 12 * 60 * 24, // 1 day voting period for council members. + }), + parachains: Some(Default::default()), + timestamp: Some(TimestampConfig { + period: 5, // 5 second block time. + }), + } +} + +/// Staging testnet config. +pub fn staging_testnet_config() -> ChainSpec { + let boot_nodes = vec![]; + ChainSpec::from_genesis( + "Staging Testnet", + "staging_testnet", + staging_testnet_config_genesis, + boot_nodes, + Some(STAGING_TELEMETRY_URL.into()), + ) +} + +fn testnet_genesis(initial_authorities: Vec) -> GenesisConfig { + let endowed_accounts = vec![ + ed25519::Pair::from_seed(b"Alice ").public().0.into(), + ed25519::Pair::from_seed(b"Bob ").public().0.into(), + ed25519::Pair::from_seed(b"Charlie ").public().0.into(), + ed25519::Pair::from_seed(b"Dave ").public().0.into(), + ed25519::Pair::from_seed(b"Eve ").public().0.into(), + ed25519::Pair::from_seed(b"Ferdie ").public().0.into(), + ]; + GenesisConfig { + consensus: Some(ConsensusConfig { + code: include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm").to_vec(), + authorities: initial_authorities.clone(), + }), + system: None, + session: Some(SessionConfig { + validators: initial_authorities.iter().cloned().map(Into::into).collect(), + session_length: 10, + broken_percent_late: 30, + }), + staking: Some(StakingConfig { + current_era: 0, + intentions: initial_authorities.iter().cloned().map(Into::into).collect(), + transaction_base_fee: 1, + transaction_byte_fee: 0, + existential_deposit: 500, + transfer_fee: 0, + creation_fee: 0, + reclaim_rebate: 0, + balances: endowed_accounts.iter().map(|&k|(k, (1u128 << 60))).collect(), + validator_count: 2, + sessions_per_era: 5, + bonding_duration: 2, + early_era_slash: 0, + session_reward: 0, + }), + democracy: Some(DemocracyConfig { + launch_period: 9, + voting_period: 18, + minimum_deposit: 10, + }), + council: Some(CouncilConfig { + active_council: endowed_accounts.iter().filter(|a| initial_authorities.iter().find(|&b| a.0 == b.0).is_none()).map(|a| (a.clone(), 1000000)).collect(), + candidacy_bond: 10, + voter_bond: 2, + present_slash_per_voter: 1, + carry_count: 4, + presentation_duration: 10, + approval_voting_period: 20, + term_duration: 1000000, + desired_seats: (endowed_accounts.len() - initial_authorities.len()) as u32, + inactive_grace_period: 1, + + cooloff_period: 75, + voting_period: 20, + }), + parachains: Some(Default::default()), + timestamp: Some(TimestampConfig { + period: 5, // 5 second block time. + }), + } +} + +fn development_config_genesis() -> GenesisConfig { + testnet_genesis(vec![ + ed25519::Pair::from_seed(b"Alice ").public().into(), + ]) +} + +/// Development config (single validator Alice) +pub fn development_config() -> ChainSpec { + ChainSpec::from_genesis("Development", "development", development_config_genesis, vec![], None) +} + +fn local_testnet_genesis() -> GenesisConfig { + testnet_genesis(vec![ + ed25519::Pair::from_seed(b"Alice ").public().into(), + ed25519::Pair::from_seed(b"Bob ").public().into(), + ]) +} + +/// Local testnet config (multivalidator Alice + Bob) +pub fn local_testnet_config() -> ChainSpec { + ChainSpec::from_genesis("Local Testnet", "local_testnet", local_testnet_genesis, vec![], None) +} diff --git a/polkadot/service/src/components.rs b/polkadot/service/src/components.rs deleted file mode 100644 index e8274f4dfccc9..0000000000000 --- a/polkadot/service/src/components.rs +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see .? - -//! Polkadot service components. - -use std::collections::HashMap; -use std::sync::Arc; -use client::{self, Client}; -use client_db; -use codec::{self, Slicable}; -use consensus; -use keystore::Store as Keystore; -use network; -use polkadot_api; -use runtime_primitives::MakeStorage; -use polkadot_executor::Executor as LocalDispatch; -use polkadot_primitives::{Block, BlockId, Hash}; -use state_machine; -use substrate_executor::NativeExecutor; -use transaction_pool::{self, TransactionPool}; -use error; - -/// Code executor. -pub type CodeExecutor = NativeExecutor; - -/// Polkadot service components. -pub trait Components { - /// Client backend type. - type Backend: 'static + client::backend::Backend; - - /// Polkadot API type. - type Api: 'static + polkadot_api::PolkadotApi + Send + Sync; - - /// Code executor type. - type Executor: 'static + client::CallExecutor + Send + Sync; - - /// Create client. - fn build_client(&self, settings: client_db::DatabaseSettings, executor: CodeExecutor, genesis_storage: MakeStorage) - -> Result<(Arc>, Option>>>), error::Error>; - - /// Create api. - fn build_api(&self, client: Arc>) -> Arc; - - /// Create network transaction pool adapter. - fn build_network_tx_pool(&self, client: Arc>, api: Arc, tx_pool: Arc) - -> Arc>; - - /// Create consensus service. - fn build_consensus(&self, client: Arc>, network: Arc>, tx_pool: Arc, keystore: &Keystore) - -> Result, error::Error>; -} - -/// Components for full Polkadot service. -pub struct FullComponents { - /// Is this a validator node? - pub is_validator: bool, -} - -impl Components for FullComponents { - type Backend = client_db::Backend; - type Api = Client; - type Executor = client::LocalCallExecutor, NativeExecutor>; - - fn build_client(&self, db_settings: client_db::DatabaseSettings, executor: CodeExecutor, genesis_storage: MakeStorage) - -> Result<(Arc>, Option>>>), error::Error> { - Ok((Arc::new(client_db::new_client(db_settings, executor, genesis_storage)?), None)) - } - - fn build_api(&self, client: Arc>) -> Arc { - client - } - - fn build_network_tx_pool(&self, client: Arc>, api: Arc, pool: Arc) - -> Arc> { - Arc::new(TransactionPoolAdapter { - imports_external_transactions: true, - pool, - client, - api, - }) - } - - fn build_consensus(&self, client: Arc>, network: Arc>, tx_pool: Arc, keystore: &Keystore) - -> Result, error::Error> { - if !self.is_validator { - return Ok(None); - } - - // Load the first available key - let key = keystore.load(&keystore.contents()?[0], "")?; - info!("Using authority key {:?}", key.public()); - Ok(Some(consensus::Service::new( - client.clone(), - client.clone(), - network.clone(), - tx_pool.clone(), - ::std::time::Duration::from_millis(4000), // TODO: dynamic - key, - ))) - } -} - -/// Components for light Polkadot service. -pub struct LightComponents; - -impl Components for LightComponents { - type Backend = client::light::Backend; - type Api = polkadot_api::light::RemotePolkadotApiWrapper; - type Executor = client::RemoteCallExecutor, network::OnDemand>>; - - fn build_client(&self, _settings: client_db::DatabaseSettings, executor: CodeExecutor, genesis_storage: MakeStorage) - -> Result<(Arc>, Option>>>), error::Error> { - let client_backend = client::light::new_light_backend(); - let fetch_checker = Arc::new(client::light::new_fetch_checker(client_backend.clone(), executor)); - let fetcher = Arc::new(network::OnDemand::new(fetch_checker)); - let client = client::light::new_light(client_backend, fetcher.clone(), genesis_storage)?; - Ok((Arc::new(client), Some(fetcher))) - } - - fn build_api(&self, client: Arc>) -> Arc { - Arc::new(polkadot_api::light::RemotePolkadotApiWrapper(client.clone())) - } - - fn build_network_tx_pool(&self, client: Arc>, api: Arc, pool: Arc) - -> Arc> { - Arc::new(TransactionPoolAdapter { - imports_external_transactions: false, - pool, - client, - api, - }) - } - - fn build_consensus(&self, _client: Arc>, _network: Arc>, _tx_pool: Arc, _keystore: &Keystore) - -> Result, error::Error> { - Ok(None) - } -} - -/// Transaction pool adapter. -pub struct TransactionPoolAdapter where A: Send + Sync, E: Send + Sync { - imports_external_transactions: bool, - pool: Arc, - client: Arc>, - api: Arc, -} - -impl network::TransactionPool for TransactionPoolAdapter - where - B: client::backend::Backend + Send + Sync, - E: client::CallExecutor + Send + Sync, - client::error::Error: From<<>::State as state_machine::backend::Backend>::Error>, - A: polkadot_api::PolkadotApi + Send + Sync, -{ - fn transactions(&self) -> Vec<(Hash, Vec)> { - let best_block = match self.client.info() { - Ok(info) => info.chain.best_hash, - Err(e) => { - debug!("Error getting best block: {:?}", e); - return Vec::new(); - } - }; - - let id = match self.api.check_id(BlockId::hash(best_block)) { - Ok(id) => id, - Err(_) => return Vec::new(), - }; - - let ready = transaction_pool::Ready::create(id, &*self.api); - - self.pool.cull_and_get_pending(ready, |pending| pending - .map(|t| { - let hash = t.hash().clone(); - (hash, t.primitive_extrinsic()) - }) - .collect() - ) - } - - fn import(&self, transaction: &Vec) -> Option { - if !self.imports_external_transactions { - return None; - } - - let encoded = transaction.encode(); - if let Some(uxt) = codec::Slicable::decode(&mut &encoded[..]) { - match self.pool.import_unchecked_extrinsic(uxt) { - Ok(xt) => Some(*xt.hash()), - Err(e) => match *e.kind() { - transaction_pool::ErrorKind::AlreadyImported(hash) => Some(hash[..].into()), - _ => { - debug!("Error adding transaction to the pool: {:?}", e); - None - }, - } - } - } else { - debug!("Error decoding transaction"); - None - } - } - - fn on_broadcasted(&self, propagations: HashMap>) { - self.pool.on_broadcasted(propagations) - } -} diff --git a/polkadot/service/src/config.rs b/polkadot/service/src/config.rs deleted file mode 100644 index c6dff5a584f61..0000000000000 --- a/polkadot/service/src/config.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see .? - -//! Service configuration. - -use transaction_pool; -use runtime_primitives::MakeStorage; -pub use network::Role; -pub use network::NetworkConfiguration; - -/// Service configuration. -pub struct Configuration { - /// Node roles. - pub roles: Role, - /// Transaction pool configuration. - pub transaction_pool: transaction_pool::Options, - /// Network configuration. - pub network: NetworkConfiguration, - /// Path to key files. - pub keystore_path: String, - /// Path to the database. - pub database_path: String, - /// Additional key seeds. - pub keys: Vec, - /// The name of the chain. - pub chain_name: String, - /// Chain configuration. - pub genesis_storage: MakeStorage, - /// Telemetry server URL, optional - only `Some` if telemetry reporting is enabled - pub telemetry: Option, - /// Node name. - pub name: String, -} - -impl Default for Configuration { - fn default() -> Configuration { - Configuration { - roles: Role::FULL, - transaction_pool: Default::default(), - network: Default::default(), - keystore_path: Default::default(), - database_path: Default::default(), - keys: Default::default(), - chain_name: Default::default(), - genesis_storage: Box::new(Default::default), - telemetry: Default::default(), - name: "Anonymous".into(), - } - } -} diff --git a/polkadot/service/src/lib.rs b/polkadot/service/src/lib.rs index 75ddf1ffbee7d..6d2c4aee157b8 100644 --- a/polkadot/service/src/lib.rs +++ b/polkadot/service/src/lib.rs @@ -14,231 +14,331 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! Polkadot service. Starts a thread that spins the network, the client and the transaction pool. -//! Manages communication between them. +#![warn(unused_extern_crates)] + +//! Polkadot service. Specialized wrapper over substrate service. -extern crate futures; extern crate ed25519; -extern crate clap; -extern crate exit_future; -extern crate tokio_timer; extern crate polkadot_primitives; extern crate polkadot_runtime; extern crate polkadot_executor; extern crate polkadot_api; extern crate polkadot_consensus as consensus; extern crate polkadot_transaction_pool as transaction_pool; -extern crate substrate_keystore as keystore; -extern crate substrate_runtime_io as runtime_io; +extern crate polkadot_network; extern crate substrate_primitives as primitives; -extern crate substrate_runtime_primitives as runtime_primitives; extern crate substrate_network as network; extern crate substrate_codec as codec; -extern crate substrate_executor; -extern crate substrate_state_machine as state_machine; - -extern crate tokio_core; extern crate substrate_client as client; -extern crate substrate_client_db as client_db; +extern crate substrate_service as service; +extern crate tokio; -#[macro_use] -extern crate substrate_telemetry; -#[macro_use] -extern crate error_chain; -#[macro_use] -extern crate slog; // needed until we can reexport `slog_info` from `substrate_telemetry` #[macro_use] extern crate log; +#[macro_use] +extern crate hex_literal; -mod components; -mod error; -mod config; +pub mod chain_spec; use std::sync::Arc; -use std::thread; -use futures::prelude::*; -use tokio_core::reactor::Core; +use std::collections::HashMap; + +use codec::Encode; use transaction_pool::TransactionPool; -use keystore::Store as Keystore; -use polkadot_api::PolkadotApi; -use polkadot_primitives::{Block, BlockId, Hash}; -use client::{Client, BlockchainEvents}; -use network::ManageNetwork; -use exit_future::Signal; +use polkadot_api::{PolkadotApi, light::RemotePolkadotApiWrapper}; +use polkadot_primitives::{parachain, AccountId, Block, BlockId, Hash}; +use polkadot_runtime::GenesisConfig; +use client::Client; +use polkadot_network::{PolkadotProtocol, consensus::ConsensusNetwork}; +use tokio::runtime::TaskExecutor; +use service::FactoryFullConfiguration; + +pub use service::{Roles, PruningMode, ExtrinsicPoolOptions, + ErrorKind, Error, ComponentBlock, LightComponents, FullComponents}; +pub use client::ExecutionStrategy; + +/// Specialised polkadot `ChainSpec`. +pub type ChainSpec = service::ChainSpec; +/// Polkadot client type for specialised `Components`. +pub type ComponentClient = Client<::Backend, ::Executor, Block>; +pub type NetworkService = network::Service::NetworkProtocol>; + +/// A collection of type to generalise Polkadot specific components over full / light client. +pub trait Components: service::Components { + /// Polkadot API. + type Api: 'static + PolkadotApi + Send + Sync; + /// Client backend. + type Backend: 'static + client::backend::Backend; + /// Client executor. + type Executor: 'static + client::CallExecutor + Send + Sync; +} + +impl Components for service::LightComponents { + type Api = RemotePolkadotApiWrapper< + as service::Components>::Backend, + as service::Components>::Executor, + >; + type Executor = service::LightExecutor; + type Backend = service::LightBackend; +} + +impl Components for service::FullComponents { + type Api = service::FullClient; + type Executor = service::FullExecutor; + type Backend = service::FullBackend; +} + +/// All configuration for the polkadot node. +pub type Configuration = FactoryFullConfiguration; + +/// Polkadot-specific configuration. +#[derive(Default)] +pub struct CustomConfiguration { + /// Set to `Some` with a collator `AccountId` and desired parachain + /// if the network protocol should be started in collator mode. + pub collating_for: Option<(AccountId, parachain::Id)>, +} + +/// Polkadot config for the substrate service. +pub struct Factory; + +impl service::ServiceFactory for Factory { + type Block = Block; + type NetworkProtocol = PolkadotProtocol; + type RuntimeDispatch = polkadot_executor::Executor; + type FullExtrinsicPool = TransactionPoolAdapter< + service::FullBackend, + service::FullExecutor, + service::FullClient + >; + type LightExtrinsicPool = TransactionPoolAdapter< + service::LightBackend, + service::LightExecutor, + RemotePolkadotApiWrapper, service::LightExecutor> + >; + type Genesis = GenesisConfig; + type Configuration = CustomConfiguration; + + const NETWORK_PROTOCOL_ID: network::ProtocolId = ::polkadot_network::DOT_PROTOCOL_ID; + + fn build_full_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc>) + -> Result + { + let api = client.clone(); + Ok(TransactionPoolAdapter { + pool: Arc::new(TransactionPool::new(config, api)), + client: client, + imports_external_transactions: true, + }) + } -pub use self::error::{ErrorKind, Error}; -pub use self::components::{Components, FullComponents, LightComponents}; -pub use config::{Configuration, Role}; + fn build_light_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc>) + -> Result + { + let api = Arc::new(RemotePolkadotApiWrapper(client.clone())); + Ok(TransactionPoolAdapter { + pool: Arc::new(TransactionPool::new(config, api)), + client: client, + imports_external_transactions: false, + }) + } + + fn build_network_protocol(config: &Configuration) + -> Result + { + if let Some((_, ref para_id)) = config.custom.collating_for { + info!("Starting network in Collator mode for parachain {:?}", para_id); + } + Ok(PolkadotProtocol::new(config.custom.collating_for)) + } +} /// Polkadot service. -pub struct Service { - thread: Option>, - client: Arc>, - network: Arc>, - transaction_pool: Arc, - signal: Option, +pub struct Service { + inner: service::Service, + client: Arc>, + network: Arc, + api: Arc<::Api>, _consensus: Option, } +impl Service { + pub fn client(&self) -> Arc> { + self.client.clone() + } + + pub fn network(&self) -> Arc { + self.network.clone() + } + + pub fn api(&self) -> Arc<::Api> { + self.api.clone() + } +} + /// Creates light client and register protocol with the network service -pub fn new_light(config: Configuration) -> Result, error::Error> { - Service::new(components::LightComponents, config) +pub fn new_light(config: Configuration, executor: TaskExecutor) + -> Result>, Error> +{ + let service = service::Service::>::new(config, executor)?; + let api = Arc::new(RemotePolkadotApiWrapper(service.client())); + Ok(Service { + client: service.client(), + network: service.network(), + api: api, + inner: service, + _consensus: None, + }) } /// Creates full client and register protocol with the network service -pub fn new_full(config: Configuration) -> Result, error::Error> { - let is_validator = (config.roles & Role::VALIDATOR) == Role::VALIDATOR; - Service::new(components::FullComponents { is_validator }, config) +pub fn new_full(config: Configuration, executor: TaskExecutor) + -> Result>, Error> +{ + let is_validator = (config.roles & Roles::AUTHORITY) == Roles::AUTHORITY; + let service = service::Service::>::new(config, executor.clone())?; + // Spin consensus service if configured + let consensus = if is_validator { + // Load the first available key + let key = service.keystore().load(&service.keystore().contents()?[0], "")?; + info!("Using authority key {}", key.public()); + + let client = service.client(); + + let consensus_net = ConsensusNetwork::new(service.network(), client.clone()); + Some(consensus::Service::new( + client.clone(), + client.clone(), + consensus_net, + service.extrinsic_pool(), + executor, + ::std::time::Duration::from_millis(4000), // TODO: dynamic + key, + )) + } else { + None + }; + + Ok(Service { + client: service.client(), + network: service.network(), + api: service.client(), + inner: service, + _consensus: consensus, + }) } -impl Service - where - Components: components::Components, - client::error::Error: From<<<::Backend as client::backend::Backend>::State as state_machine::Backend>::Error>, +/// Creates bare client without any networking. +pub fn new_client(config: Configuration) +-> Result>>, Error> { - /// Creates and register protocol with the network service - fn new(components: Components, config: Configuration) -> Result { - use std::sync::Barrier; - - let (signal, exit) = ::exit_future::signal(); + service::new_client::(config) +} - // Create client - let executor = polkadot_executor::Executor::new(); +impl ::std::ops::Deref for Service { + type Target = service::Service; - let mut keystore = Keystore::open(config.keystore_path.into())?; - for seed in &config.keys { - keystore.generate_from_seed(seed)?; - } + fn deref(&self) -> &Self::Target { + &self.inner + } +} - if keystore.contents()?.is_empty() { - let key = keystore.generate("")?; - info!("Generated a new keypair: {:?}", key.public()); - } +/// Transaction pool adapter. +pub struct TransactionPoolAdapter where A: Send + Sync, E: Send + Sync { + imports_external_transactions: bool, + pool: Arc>, + client: Arc>, +} - let db_settings = client_db::DatabaseSettings { - cache_size: None, - path: config.database_path.into(), - }; +impl TransactionPoolAdapter + where + A: Send + Sync, + B: client::backend::Backend + Send + Sync, + E: client::CallExecutor + Send + Sync, +{ + fn best_block_id(&self) -> Option { + self.client.info() + .map(|info| BlockId::hash(info.chain.best_hash)) + .map_err(|e| { + debug!("Error getting best block: {:?}", e); + }) + .ok() + } +} - let (client, on_demand) = components.build_client(db_settings, executor, config.genesis_storage)?; - let api = components.build_api(client.clone()); - let best_header = client.best_block_header()?; - - info!("Best block is #{}", best_header.number); - telemetry!("node.start"; "height" => best_header.number, "best" => ?best_header.hash()); - - let transaction_pool = Arc::new(TransactionPool::new(config.transaction_pool)); - let transaction_pool_adapter = components.build_network_tx_pool(client.clone(), api.clone(), transaction_pool.clone()); - let network_params = network::Params { - config: network::ProtocolConfig { - roles: config.roles, - }, - network_config: config.network, - chain: client.clone(), - on_demand: on_demand.clone().map(|d| d as Arc), - transaction_pool: transaction_pool_adapter, +impl network::TransactionPool for TransactionPoolAdapter + where + B: client::backend::Backend + Send + Sync, + E: client::CallExecutor + Send + Sync, + A: polkadot_api::PolkadotApi + Send + Sync, +{ + fn transactions(&self) -> Vec<(Hash, Vec)> { + let best_block_id = match self.best_block_id() { + Some(id) => id, + None => return vec![], }; - let network = network::Service::new(network_params)?; - let barrier = ::std::sync::Arc::new(Barrier::new(2)); - on_demand.map(|on_demand| on_demand.set_service_link(Arc::downgrade(&network))); - - let thread = { - let client = client.clone(); - let network = network.clone(); - let txpool = transaction_pool.clone(); - - let thread_barrier = barrier.clone(); - thread::spawn(move || { - network.start_network(); - - thread_barrier.wait(); - let mut core = Core::new().expect("tokio::Core could not be created"); - - // block notifications - let network1 = network.clone(); - let txpool1 = txpool.clone(); - - let events = client.import_notification_stream() - .for_each(move |notification| { - network1.on_block_imported(notification.hash, ¬ification.header); - prune_imported(&*api, &*txpool1, notification.hash); - Ok(()) - }); - core.handle().spawn(events); - - // transaction notifications - let events = txpool.import_notification_stream() - // TODO [ToDr] Consider throttling? - .for_each(move |_| { - network.trigger_repropagate(); - Ok(()) - }); - core.handle().spawn(events); - - if let Err(e) = core.run(exit) { - debug!("Polkadot service event loop shutdown with {:?}", e); - } - debug!("Polkadot service shutdown"); + self.pool.cull_and_get_pending(best_block_id, |pending| pending + .map(|t| { + let hash = t.hash().clone(); + (hash, t.primitive_extrinsic()) }) - }; - - // wait for the network to start up before starting the consensus - // service. - barrier.wait(); - - // Spin consensus service if configured - let consensus_service = components.build_consensus(client.clone(), network.clone(), transaction_pool.clone(), &keystore)?; - - Ok(Service { - thread: Some(thread), - client: client, - network: network, - transaction_pool: transaction_pool, - signal: Some(signal), - _consensus: consensus_service, + .collect() + ).unwrap_or_else(|e| { + warn!("Error retrieving pending set: {}", e); + vec![] }) } - /// Get shared client instance. - pub fn client(&self) -> Arc> { - self.client.clone() - } + fn import(&self, transaction: &Vec) -> Option { + if !self.imports_external_transactions { + return None; + } - /// Get shared network instance. - pub fn network(&self) -> Arc> { - self.network.clone() + let encoded = transaction.encode(); + if let Some(uxt) = codec::Decode::decode(&mut &encoded[..]) { + let best_block_id = self.best_block_id()?; + match self.pool.import_unchecked_extrinsic(best_block_id, uxt) { + Ok(xt) => Some(*xt.hash()), + Err(e) => match *e.kind() { + transaction_pool::ErrorKind::AlreadyImported(hash) => Some(hash[..].into()), + _ => { + debug!("Error adding transaction to the pool: {:?}", e); + None + }, + } + } + } else { + debug!("Error decoding transaction"); + None + } } - /// Get shared transaction pool instance. - pub fn transaction_pool(&self) -> Arc { - self.transaction_pool.clone() + fn on_broadcasted(&self, propagations: HashMap>) { + self.pool.on_broadcasted(propagations) } } -/// Produce a task which prunes any finalized transactions from the pool. -pub fn prune_imported(api: &A, pool: &TransactionPool, hash: Hash) +impl service::ExtrinsicPool for TransactionPoolAdapter where - A: PolkadotApi, + B: client::backend::Backend + Send + Sync + 'static, + E: client::CallExecutor + Send + Sync + 'static, + A: polkadot_api::PolkadotApi + Send + Sync + 'static, { - match api.check_id(BlockId::hash(hash)) { - Ok(id) => { - let ready = transaction_pool::Ready::create(id, api); - pool.cull(None, ready); - }, - Err(e) => warn!("Failed to check block id: {:?}", e), - } -} + type Api = TransactionPool; -impl Drop for Service where Components: components::Components { - fn drop(&mut self) { - self.network.stop_network(); - - if let Some(signal) = self.signal.take() { - signal.fire(); + fn prune_imported(&self, hash: &Hash) { + let block = BlockId::hash(*hash); + if let Err(e) = self.pool.cull(block) { + warn!("Culling error: {:?}", e); } - if let Some(thread) = self.thread.take() { - thread.join().expect("The service thread has panicked"); + if let Err(e) = self.pool.retry_verification(block) { + warn!("Re-verifying error: {:?}", e); } } + + fn api(&self) -> Arc { + self.pool.clone() + } } + diff --git a/polkadot/src/README.adoc b/polkadot/src/README.adoc new file mode 100644 index 0000000000000..fed228df0b6bd --- /dev/null +++ b/polkadot/src/README.adoc @@ -0,0 +1,5 @@ + += Polkadot Src + +placeholder +//TODO Write content :) diff --git a/polkadot/src/main.rs b/polkadot/src/main.rs index 50ff18462e29a..d3e951596e200 100644 --- a/polkadot/src/main.rs +++ b/polkadot/src/main.rs @@ -19,12 +19,59 @@ #![warn(missing_docs)] extern crate polkadot_cli as cli; +extern crate ctrlc; +extern crate futures; #[macro_use] extern crate error_chain; +use cli::{ServiceComponents, Service, VersionInfo}; +use futures::sync::oneshot; +use futures::{future, Future}; + +use std::cell::RefCell; + +mod vergen { + #![allow(unused)] + include!(concat!(env!("OUT_DIR"), "/version.rs")); +} + +// the regular polkadot worker simply does nothing until ctrl-c +struct Worker; +impl cli::IntoExit for Worker { + type Exit = future::MapErr, fn(oneshot::Canceled) -> ()>; + fn into_exit(self) -> Self::Exit { + // can't use signal directly here because CtrlC takes only `Fn`. + let (exit_send, exit) = oneshot::channel(); + + let exit_send_cell = RefCell::new(Some(exit_send)); + ctrlc::CtrlC::set_handler(move || { + if let Some(exit_send) = exit_send_cell.try_borrow_mut().expect("signal handler not reentrant; qed").take() { + exit_send.send(()).expect("Error sending exit notification"); + } + }); + + exit.map_err(drop) + } +} + +impl cli::Worker for Worker { + type Work = ::Exit; + fn work(self, _service: &Service) -> Self::Work { + use cli::IntoExit; + self.into_exit() + } +} + quick_main!(run); fn run() -> cli::error::Result<()> { - cli::run(::std::env::args()) + let version = VersionInfo { + commit: vergen::short_sha(), + version: env!("CARGO_PKG_VERSION"), + executable_name: "polkadot", + author: "Parity Team ", + description: "Polkadot Node Rust Implementation", + }; + cli::run(::std::env::args(), Worker, version) } diff --git a/polkadot/statement-table/Cargo.toml b/polkadot/statement-table/Cargo.toml index 5c8a61e81d33c..b81ee1db907e1 100644 --- a/polkadot/statement-table/Cargo.toml +++ b/polkadot/statement-table/Cargo.toml @@ -4,5 +4,6 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] +substrate-codec = { path = "../../substrate/codec" } substrate-primitives = { path = "../../substrate/primitives" } polkadot-primitives = { path = "../primitives" } diff --git a/polkadot/statement-table/README.adoc b/polkadot/statement-table/README.adoc new file mode 100644 index 0000000000000..402f55108f4e9 --- /dev/null +++ b/polkadot/statement-table/README.adoc @@ -0,0 +1,5 @@ + += Polkadot Statement table + +placeholder +//TODO Write content :) diff --git a/polkadot/statement-table/src/generic.rs b/polkadot/statement-table/src/generic.rs index 4436730b3efce..06f9f94292799 100644 --- a/polkadot/statement-table/src/generic.rs +++ b/polkadot/statement-table/src/generic.rs @@ -27,26 +27,11 @@ //! propose and attest to validity of candidates, and those who can only attest //! to availability. -use std::collections::HashSet; use std::collections::hash_map::{HashMap, Entry}; use std::hash::Hash; use std::fmt::Debug; -/// A batch of statements to send out. -pub trait StatementBatch { - /// Get the target authorities of these statements. - fn targets(&self) -> &[V]; - - /// If the batch is empty. - fn is_empty(&self) -> bool; - - /// Push a statement onto the batch. Returns false when the batch is full. - /// - /// This is meant to do work like incrementally serializing the statements - /// into a vector of bytes while making sure the length is below a certain - /// amount. - fn push(&mut self, statement: T) -> bool; -} +use codec::{Decode, Encode, Input, Output}; /// Context for the statement table. pub trait Context { @@ -103,6 +88,58 @@ pub enum Statement { Invalid(D), } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u8)] +enum StatementKind { + Candidate = 1, + Valid = 2, + Invalid = 3, + Available = 4, +} + +impl Encode for Statement { + fn encode_to(&self, dest: &mut T) { + match *self { + Statement::Candidate(ref candidate) => { + dest.push_byte(StatementKind::Candidate as u8); + dest.push(candidate); + } + Statement::Valid(ref digest) => { + dest.push_byte(StatementKind::Valid as u8); + dest.push(digest); + } + Statement::Invalid(ref digest) => { + dest.push_byte(StatementKind::Invalid as u8); + dest.push(digest); + } + Statement::Available(ref digest) => { + dest.push_byte(StatementKind::Available as u8); + dest.push(digest); + } + } + } +} + +impl Decode for Statement { + fn decode(value: &mut I) -> Option { + match value.read_byte() { + Some(x) if x == StatementKind::Candidate as u8 => { + Decode::decode(value).map(Statement::Candidate) + } + Some(x) if x == StatementKind::Valid as u8 => { + Decode::decode(value).map(Statement::Valid) + } + Some(x) if x == StatementKind::Invalid as u8 => { + Decode::decode(value).map(Statement::Invalid) + } + Some(x) if x == StatementKind::Available as u8 => { + Decode::decode(value).map(Statement::Available) + } + _ => None, + } + } +} + /// A signed statement. #[derive(PartialEq, Eq, Debug, Clone)] pub struct SignedStatement { @@ -114,26 +151,23 @@ pub struct SignedStatement { pub sender: V, } -// A unique trace for a class of valid statements issued by a authority. -// -// We keep track of which statements we have received or sent to other authorities -// in order to prevent relaying the same data multiple times. -// -// The signature of the statement is replaced by the authority because the authority -// is unique while signatures are not (at least under common schemes like -// Schnorr or ECDSA). -#[derive(Hash, PartialEq, Eq, Clone)] -enum StatementTrace { - /// The candidate proposed by the authority. - Candidate(V), - /// A validity statement from that authority about the given digest. - Valid(V, D), - /// An invalidity statement from that authority about the given digest. - Invalid(V, D), - /// An availability statement from that authority about the given digest. - Available(V, D), +impl Encode for SignedStatement { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.statement); + dest.push(&self.signature); + dest.push(&self.sender); + } } +impl Decode for SignedStatement { + fn decode(value: &mut I) -> Option { + Some(SignedStatement { + statement: Decode::decode(value)?, + signature: Decode::decode(value)?, + sender: Decode::decode(value)?, + }) + } +} /// Misbehavior: voting more than one way on candidate validity. /// /// Since there are three possible ways to vote, a double vote is possible in @@ -148,6 +182,19 @@ pub enum ValidityDoubleVote { ValidityAndInvalidity(D, S, S), } +/// Misbehavior: multiple signatures on same statement. +#[derive(PartialEq, Eq, Debug, Clone)] +pub enum DoubleSign { + /// On candidate. + Candidate(C, S, S), + /// On validity. + Validity(D, S, S), + /// On invalidity. + Invalidity(D, S, S), + /// On availability. + Availability(D, S, S), +} + /// Misbehavior: declaring multiple candidates. #[derive(PartialEq, Eq, Debug, Clone)] pub struct MultipleCandidates { @@ -172,20 +219,14 @@ pub enum Misbehavior { ValidityDoubleVote(ValidityDoubleVote), /// Submitted multiple candidates. MultipleCandidates(MultipleCandidates), - /// Submitted a message withou + /// Submitted a message that was unauthorized. UnauthorizedStatement(UnauthorizedStatement), + /// Submitted two valid signatures for the same message. + DoubleSign(DoubleSign), } -/// Fancy work-around for a type alias of context-based misbehavior -/// without producing compiler warnings. -pub trait ResolveMisbehavior { - /// The misbehavior type. - type Misbehavior; -} - -impl ResolveMisbehavior for C { - type Misbehavior = Misbehavior; -} +/// Type alias for misbehavior corresponding to context type. +pub type MisbehaviorFor = Misbehavior<::Candidate, ::Digest, ::AuthorityId, ::Signature>; // kinds of votes for validity #[derive(Clone, PartialEq, Eq)] @@ -251,22 +292,26 @@ impl CandidateData { // authority metadata struct AuthorityData { proposal: Option<(C::Digest, C::Signature)>, - known_statements: HashSet>, } impl Default for AuthorityData { fn default() -> Self { AuthorityData { proposal: None, - known_statements: HashSet::default(), } } } +/// Type alias for the result of a statement import. +pub type ImportResult = Result< + Option::Digest, ::GroupId>>, + MisbehaviorFor +>; + /// Stores votes pub struct Table { authority_data: HashMap>, - detected_misbehavior: HashMap::Misbehavior>, + detected_misbehavior: HashMap>, candidate_votes: HashMap>, includable_count: HashMap, } @@ -328,26 +373,17 @@ impl Table { } /// Import a signed statement. Signatures should be checked for validity, and the - /// sender should be checked to actually be a authority. + /// sender should be checked to actually be an authority. /// - /// This can note the origin of the statement to indicate that he has - /// seen it already. + /// If this returns `None`, the statement was either duplicate or invalid. pub fn import_statement( &mut self, context: &C, statement: SignedStatement, - from: Option ) -> Option> { let SignedStatement { statement, signature, sender: signer } = statement; - let trace = match statement { - Statement::Candidate(_) => StatementTrace::Candidate(signer.clone()), - Statement::Valid(ref d) => StatementTrace::Valid(signer.clone(), d.clone()), - Statement::Invalid(ref d) => StatementTrace::Invalid(signer.clone(), d.clone()), - Statement::Available(ref d) => StatementTrace::Available(signer.clone(), d.clone()), - }; - - let (maybe_misbehavior, maybe_summary) = match statement { + let res = match statement { Statement::Candidate(candidate) => self.import_candidate( context, signer.clone(), @@ -374,19 +410,15 @@ impl Table { ), }; - if let Some(misbehavior) = maybe_misbehavior { - // all misbehavior in agreement is provable and actively malicious. - // punishments are not cumulative. - self.detected_misbehavior.insert(signer, misbehavior); - } else { - if let Some(from) = from { - self.note_trace_seen(trace.clone(), from); + match res { + Ok(maybe_summary) => maybe_summary, + Err(misbehavior) => { + // all misbehavior in agreement is provable and actively malicious. + // punishments are not cumulative. + self.detected_misbehavior.insert(signer, misbehavior); + None } - - self.note_trace_seen(trace, signer); } - - maybe_summary } /// Get a candidate by digest. @@ -396,7 +428,7 @@ impl Table { /// Access all witnessed misbehavior. pub fn get_misbehavior(&self) - -> &HashMap::Misbehavior> + -> &HashMap> { &self.detected_misbehavior } @@ -406,155 +438,22 @@ impl Table { self.includable_count.len() } - /// Fill a statement batch and note messages as seen by the targets. - pub fn fill_batch(&mut self, batch: &mut B) - where B: StatementBatch< - C::AuthorityId, - SignedStatement, - > - { - // naively iterate all statements so far, taking any that - // at least one of the targets has not seen. - - // workaround for the fact that it's inconvenient to borrow multiple - // entries out of a hashmap mutably -- we just move them out and - // replace them when we're done. - struct SwappedTargetData<'a, C: 'a + Context> { - authority_data: &'a mut HashMap>, - target_data: Vec<(C::AuthorityId, AuthorityData)>, - } - - impl<'a, C: 'a + Context> Drop for SwappedTargetData<'a, C> { - fn drop(&mut self) { - for (id, data) in self.target_data.drain(..) { - self.authority_data.insert(id, data); - } - } - } - - // pre-fetch authority data for all the targets. - let mut target_data = { - let authority_data = &mut self.authority_data; - let mut target_data = Vec::with_capacity(batch.targets().len()); - for target in batch.targets() { - let active_data = match authority_data.get_mut(target) { - None => Default::default(), - Some(x) => ::std::mem::replace(x, Default::default()), - }; - - target_data.push((target.clone(), active_data)); - } - - SwappedTargetData { - authority_data, - target_data - } - }; - - let target_data = &mut target_data.target_data; - - macro_rules! attempt_send { - ($trace:expr, sender=$sender:expr, sig=$sig:expr, statement=$statement:expr) => {{ - let trace = $trace; - let can_send = target_data.iter() - .any(|t| !t.1.known_statements.contains(&trace)); - - if can_send { - let statement = SignedStatement { - statement: $statement, - signature: $sig, - sender: $sender, - }; - - if batch.push(statement) { - for target in target_data.iter_mut() { - target.1.known_statements.insert(trace.clone()); - } - } else { - return; - } - } - }} - } - - // reconstruct statements for anything whose trace passes the filter. - for (digest, candidate) in self.candidate_votes.iter() { - let issuance_iter = candidate.validity_votes.iter() - .filter(|&(_, x)| if let ValidityVote::Issued(_) = *x { true } else { false }); - - let validity_iter = candidate.validity_votes.iter() - .filter(|&(_, x)| if let ValidityVote::Issued(_) = *x { false } else { true }); - - // send issuance statements before votes. - for (sender, vote) in issuance_iter.chain(validity_iter) { - match *vote { - ValidityVote::Issued(ref sig) => { - attempt_send!( - StatementTrace::Candidate(sender.clone()), - sender = sender.clone(), - sig = sig.clone(), - statement = Statement::Candidate(candidate.candidate.clone()) - ) - } - ValidityVote::Valid(ref sig) => { - attempt_send!( - StatementTrace::Valid(sender.clone(), digest.clone()), - sender = sender.clone(), - sig = sig.clone(), - statement = Statement::Valid(digest.clone()) - ) - } - ValidityVote::Invalid(ref sig) => { - attempt_send!( - StatementTrace::Invalid(sender.clone(), digest.clone()), - sender = sender.clone(), - sig = sig.clone(), - statement = Statement::Invalid(digest.clone()) - ) - } - } - }; - - - // and lastly send availability. - for (sender, sig) in candidate.availability_votes.iter() { - attempt_send!( - StatementTrace::Available(sender.clone(), digest.clone()), - sender = sender.clone(), - sig = sig.clone(), - statement = Statement::Available(digest.clone()) - ) - } - } - - } - - fn note_trace_seen(&mut self, trace: StatementTrace, known_by: C::AuthorityId) { - self.authority_data.entry(known_by).or_insert_with(|| AuthorityData { - proposal: None, - known_statements: HashSet::default(), - }).known_statements.insert(trace); - } - fn import_candidate( &mut self, context: &C, from: C::AuthorityId, candidate: C::Candidate, signature: C::Signature, - ) -> (Option<::Misbehavior>, Option>) { + ) -> ImportResult { let group = C::candidate_group(&candidate); if !context.is_member_of(&from, &group) { - return ( - Some(Misbehavior::UnauthorizedStatement(UnauthorizedStatement { - statement: SignedStatement { - signature, - statement: Statement::Candidate(candidate), - sender: from, - }, - })), - None, - ); + return Err(Misbehavior::UnauthorizedStatement(UnauthorizedStatement { + statement: SignedStatement { + signature, + statement: Statement::Candidate(candidate), + sender: from, + }, + })); } // check that authority hasn't already specified another candidate. @@ -578,13 +477,10 @@ impl Table { .candidate .clone(); - return ( - Some(Misbehavior::MultipleCandidates(MultipleCandidates { - first: (old_candidate, old_sig.clone()), - second: (candidate, signature.clone()), - })), - None, - ); + return Err(Misbehavior::MultipleCandidates(MultipleCandidates { + first: (old_candidate, old_sig.clone()), + second: (candidate, signature.clone()), + })); } false @@ -596,7 +492,6 @@ impl Table { Entry::Vacant(vacant) => { vacant.insert(AuthorityData { proposal: Some((digest.clone(), signature.clone())), - known_statements: HashSet::new(), }); true } @@ -628,9 +523,9 @@ impl Table { from: C::AuthorityId, digest: C::Digest, vote: ValidityVote, - ) -> (Option<::Misbehavior>, Option>) { + ) -> ImportResult { let votes = match self.candidate_votes.get_mut(&digest) { - None => return (None, None), // TODO: queue up but don't get DoS'ed + None => return Ok(None), Some(votes) => votes, }; @@ -647,50 +542,56 @@ impl Table { checking group membership of issuer; qed"), }; - return ( - Some(Misbehavior::UnauthorizedStatement(UnauthorizedStatement { - statement: SignedStatement { - signature: sig, - sender: from, - statement: if valid { - Statement::Valid(digest) - } else { - Statement::Invalid(digest) - } + return Err(Misbehavior::UnauthorizedStatement(UnauthorizedStatement { + statement: SignedStatement { + signature: sig, + sender: from, + statement: if valid { + Statement::Valid(digest) + } else { + Statement::Invalid(digest) } - })), - None, - ); + } + })); } // check for double votes. match votes.validity_votes.entry(from.clone()) { Entry::Occupied(occ) => { - if occ.get() != &vote { - let double_vote_proof = match (occ.get().clone(), vote) { + let make_vdv = |v| Misbehavior::ValidityDoubleVote(v); + let make_ds = |ds| Misbehavior::DoubleSign(ds); + return if occ.get() != &vote { + Err(match (occ.get().clone(), vote) { + // valid vote conflicting with candidate statement (ValidityVote::Issued(iss), ValidityVote::Valid(good)) | (ValidityVote::Valid(good), ValidityVote::Issued(iss)) => - ValidityDoubleVote::IssuedAndValidity((votes.candidate.clone(), iss), (digest, good)), + make_vdv(ValidityDoubleVote::IssuedAndValidity((votes.candidate.clone(), iss), (digest, good))), + + // invalid vote conflicting with candidate statement (ValidityVote::Issued(iss), ValidityVote::Invalid(bad)) | (ValidityVote::Invalid(bad), ValidityVote::Issued(iss)) => - ValidityDoubleVote::IssuedAndInvalidity((votes.candidate.clone(), iss), (digest, bad)), + make_vdv(ValidityDoubleVote::IssuedAndInvalidity((votes.candidate.clone(), iss), (digest, bad))), + + // valid vote conflicting with invalid vote (ValidityVote::Valid(good), ValidityVote::Invalid(bad)) | (ValidityVote::Invalid(bad), ValidityVote::Valid(good)) => - ValidityDoubleVote::ValidityAndInvalidity(digest, good, bad), - _ => { - // this would occur if two different but valid signatures - // on the same kind of vote occurred. - return (None, None); - } - }; - - return ( - Some(Misbehavior::ValidityDoubleVote(double_vote_proof)), - None, - ) - } + make_vdv(ValidityDoubleVote::ValidityAndInvalidity(digest, good, bad)), + + // two signatures on same candidate + (ValidityVote::Issued(a), ValidityVote::Issued(b)) => + make_ds(DoubleSign::Candidate(votes.candidate.clone(), a, b)), + + // two signatures on same validity vote + (ValidityVote::Valid(a), ValidityVote::Valid(b)) => + make_ds(DoubleSign::Validity(digest, a, b)), - return (None, None); + // two signature on same invalidity vote + (ValidityVote::Invalid(a), ValidityVote::Invalid(b)) => + make_ds(DoubleSign::Invalidity(digest, a, b)), + }) + } else { + Ok(None) + } } Entry::Vacant(vacant) => { if let ValidityVote::Invalid(_) = vote { @@ -704,7 +605,7 @@ impl Table { let is_includable = votes.can_be_included(v_threshold, a_threshold); update_includable_count(&mut self.includable_count, &votes.group_id, was_includable, is_includable); - (None, Some(votes.summary(digest))) + Ok(Some(votes.summary(digest))) } fn availability_vote( @@ -713,9 +614,9 @@ impl Table { from: C::AuthorityId, digest: C::Digest, signature: C::Signature, - ) -> (Option<::Misbehavior>, Option>) { + ) -> ImportResult { let votes = match self.candidate_votes.get_mut(&digest) { - None => return (None, None), // TODO: queue up but don't get DoS'ed + None => return Ok(None), Some(votes) => votes, }; @@ -724,24 +625,26 @@ impl Table { // check that this authority actually can vote in this group. if !context.is_availability_guarantor_of(&from, &votes.group_id) { - return ( - Some(Misbehavior::UnauthorizedStatement(UnauthorizedStatement { - statement: SignedStatement { - signature: signature.clone(), - statement: Statement::Available(digest), - sender: from, - } - })), - None - ); + return Err(Misbehavior::UnauthorizedStatement(UnauthorizedStatement { + statement: SignedStatement { + signature: signature, + statement: Statement::Available(digest), + sender: from, + } + })); } - votes.availability_votes.insert(from, signature); + match votes.availability_votes.entry(from) { + Entry::Occupied(ref occ) if occ.get() != &signature => return Err( + Misbehavior::DoubleSign(DoubleSign::Availability(digest, signature, occ.get().clone())) + ), + entry => { let _ = entry.or_insert(signature); }, + } let is_includable = votes.can_be_included(v_threshold, a_threshold); update_includable_count(&mut self.includable_count, &votes.group_id, was_includable, is_includable); - (None, Some(votes.summary(digest))) + Ok(Some(votes.summary(digest))) } } @@ -765,26 +668,6 @@ mod tests { use super::*; use std::collections::HashMap; - #[derive(Debug, Clone)] - struct VecBatch { - pub max_len: usize, - pub targets: Vec, - pub items: Vec, - } - - impl ::generic::StatementBatch for VecBatch { - fn targets(&self) -> &[V] { &self.targets } - fn is_empty(&self) -> bool { self.items.is_empty() } - fn push(&mut self, item: T) -> bool { - if self.items.len() == self.max_len { - false - } else { - self.items.push(item); - true - } - } - } - fn create() -> Table { Table::default() } @@ -878,10 +761,10 @@ mod tests { sender: AuthorityId(1), }; - table.import_statement(&context, statement_a, None); + table.import_statement(&context, statement_a); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); - table.import_statement(&context, statement_b, None); + table.import_statement(&context, statement_b); assert_eq!( table.detected_misbehavior.get(&AuthorityId(1)).unwrap(), &Misbehavior::MultipleCandidates(MultipleCandidates { @@ -908,7 +791,7 @@ mod tests { sender: AuthorityId(1), }; - table.import_statement(&context, statement, None); + table.import_statement(&context, statement); assert_eq!( table.detected_misbehavior.get(&AuthorityId(1)).unwrap(), @@ -949,8 +832,8 @@ mod tests { }; let candidate_b_digest = Digest(987); - table.import_statement(&context, candidate_a, None); - table.import_statement(&context, candidate_b, None); + table.import_statement(&context, candidate_a); + table.import_statement(&context, candidate_b); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2))); @@ -960,7 +843,7 @@ mod tests { signature: Signature(1), sender: AuthorityId(1), }; - table.import_statement(&context, bad_availability_vote, None); + table.import_statement(&context, bad_availability_vote); assert_eq!( table.detected_misbehavior.get(&AuthorityId(1)).unwrap(), @@ -979,7 +862,7 @@ mod tests { signature: Signature(2), sender: AuthorityId(2), }; - table.import_statement(&context, bad_validity_vote, None); + table.import_statement(&context, bad_validity_vote); assert_eq!( table.detected_misbehavior.get(&AuthorityId(2)).unwrap(), @@ -1012,7 +895,7 @@ mod tests { }; let candidate_digest = Digest(100); - table.import_statement(&context, statement, None); + table.import_statement(&context, statement); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); let valid_statement = SignedStatement { @@ -1027,10 +910,10 @@ mod tests { sender: AuthorityId(2), }; - table.import_statement(&context, valid_statement, None); + table.import_statement(&context, valid_statement); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2))); - table.import_statement(&context, invalid_statement, None); + table.import_statement(&context, invalid_statement); assert_eq!( table.detected_misbehavior.get(&AuthorityId(2)).unwrap(), @@ -1042,6 +925,102 @@ mod tests { ); } + #[test] + fn candidate_double_signature_is_misbehavior() { + let context = TestContext { + authorities: { + let mut map = HashMap::new(); + map.insert(AuthorityId(1), (GroupId(2), GroupId(455))); + map.insert(AuthorityId(2), (GroupId(2), GroupId(246))); + map + } + }; + + let mut table = create(); + let statement = SignedStatement { + statement: Statement::Candidate(Candidate(2, 100)), + signature: Signature(1), + sender: AuthorityId(1), + }; + + table.import_statement(&context, statement); + assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); + + let invalid_statement = SignedStatement { + statement: Statement::Candidate(Candidate(2, 100)), + signature: Signature(999), + sender: AuthorityId(1), + }; + + table.import_statement(&context, invalid_statement); + assert!(table.detected_misbehavior.contains_key(&AuthorityId(1))); + } + + #[test] + fn validity_invalidity_double_signature_is_misbehavior() { + let context = TestContext { + authorities: { + let mut map = HashMap::new(); + map.insert(AuthorityId(1), (GroupId(2), GroupId(455))); + map.insert(AuthorityId(2), (GroupId(2), GroupId(246))); + map.insert(AuthorityId(3), (GroupId(2), GroupId(222))); + map + } + }; + + let mut table = create(); + let statement = SignedStatement { + statement: Statement::Candidate(Candidate(2, 100)), + signature: Signature(1), + sender: AuthorityId(1), + }; + + table.import_statement(&context, statement); + assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); + + // insert two validity votes from authority 2 with different signatures + { + let statement = SignedStatement { + statement: Statement::Valid(Digest(100)), + signature: Signature(2), + sender: AuthorityId(2), + }; + + table.import_statement(&context, statement); + assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2))); + + let invalid_statement = SignedStatement { + statement: Statement::Valid(Digest(100)), + signature: Signature(222), + sender: AuthorityId(2), + }; + + table.import_statement(&context, invalid_statement); + assert!(table.detected_misbehavior.contains_key(&AuthorityId(2))); + } + + // insert two invalidity votes from authority 2 with different signatures + { + let statement = SignedStatement { + statement: Statement::Invalid(Digest(100)), + signature: Signature(3), + sender: AuthorityId(3), + }; + + table.import_statement(&context, statement); + assert!(!table.detected_misbehavior.contains_key(&AuthorityId(3))); + + let invalid_statement = SignedStatement { + statement: Statement::Invalid(Digest(100)), + signature: Signature(333), + sender: AuthorityId(3), + }; + + table.import_statement(&context, invalid_statement); + assert!(table.detected_misbehavior.contains_key(&AuthorityId(3))); + } + } + #[test] fn issue_and_vote_is_misbehavior() { let context = TestContext { @@ -1060,7 +1039,7 @@ mod tests { }; let candidate_digest = Digest(100); - table.import_statement(&context, statement, None); + table.import_statement(&context, statement); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); let extra_vote = SignedStatement { @@ -1069,7 +1048,7 @@ mod tests { sender: AuthorityId(1), }; - table.import_statement(&context, extra_vote, None); + table.import_statement(&context, extra_vote); assert_eq!( table.detected_misbehavior.get(&AuthorityId(1)).unwrap(), &Misbehavior::ValidityDoubleVote(ValidityDoubleVote::IssuedAndValidity( @@ -1133,7 +1112,7 @@ mod tests { }; let candidate_digest = Digest(100); - table.import_statement(&context, statement, None); + table.import_statement(&context, statement); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); assert!(!table.candidate_includable(&candidate_digest, &context)); assert!(table.includable_count.is_empty()); @@ -1144,7 +1123,7 @@ mod tests { sender: AuthorityId(2), }; - table.import_statement(&context, vote, None); + table.import_statement(&context, vote); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2))); assert!(!table.candidate_includable(&candidate_digest, &context)); assert!(table.includable_count.is_empty()); @@ -1156,7 +1135,7 @@ mod tests { sender: AuthorityId(4), }; - table.import_statement(&context, vote, None); + table.import_statement(&context, vote); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(4))); assert!(table.candidate_includable(&candidate_digest, &context)); assert!(table.includable_count.get(&GroupId(2)).is_some()); @@ -1168,7 +1147,7 @@ mod tests { sender: AuthorityId(3), }; - table.import_statement(&context, vote, None); + table.import_statement(&context, vote); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2))); assert!(!table.candidate_includable(&candidate_digest, &context)); assert!(table.includable_count.is_empty()); @@ -1191,7 +1170,7 @@ mod tests { sender: AuthorityId(1), }; - let summary = table.import_statement(&context, statement, None) + let summary = table.import_statement(&context, statement) .expect("candidate import to give summary"); assert_eq!(summary.candidate, Digest(100)); @@ -1219,7 +1198,7 @@ mod tests { }; let candidate_digest = Digest(100); - table.import_statement(&context, statement, None); + table.import_statement(&context, statement); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); let vote = SignedStatement { @@ -1228,7 +1207,7 @@ mod tests { sender: AuthorityId(2), }; - let summary = table.import_statement(&context, vote, None) + let summary = table.import_statement(&context, vote) .expect("candidate vote to give summary"); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2))); @@ -1258,7 +1237,7 @@ mod tests { }; let candidate_digest = Digest(100); - table.import_statement(&context, statement, None); + table.import_statement(&context, statement); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); let vote = SignedStatement { @@ -1267,7 +1246,7 @@ mod tests { sender: AuthorityId(2), }; - let summary = table.import_statement(&context, vote, None) + let summary = table.import_statement(&context, vote) .expect("candidate vote to give summary"); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2))); @@ -1277,55 +1256,4 @@ mod tests { assert_eq!(summary.validity_votes, 1); assert_eq!(summary.availability_votes, 1); } - - #[test] - fn filling_batch_sets_known_flag() { - let context = TestContext { - authorities: { - let mut map = HashMap::new(); - for i in 1..10 { - map.insert(AuthorityId(i), (GroupId(2), GroupId(400 + i))); - } - map - } - }; - - let mut table = create(); - let statement = SignedStatement { - statement: Statement::Candidate(Candidate(2, 100)), - signature: Signature(1), - sender: AuthorityId(1), - }; - - table.import_statement(&context, statement, None); - - for i in 2..10 { - let statement = SignedStatement { - statement: Statement::Valid(Digest(100)), - signature: Signature(i), - sender: AuthorityId(i), - }; - - table.import_statement(&context, statement, None); - } - - let mut batch = VecBatch { - max_len: 5, - targets: (1..10).map(AuthorityId).collect(), - items: Vec::new(), - }; - - // 9 statements in the table, each seen by one. - table.fill_batch(&mut batch); - assert_eq!(batch.items.len(), 5); - - // 9 statements in the table, 5 of which seen by all targets. - batch.items.clear(); - table.fill_batch(&mut batch); - assert_eq!(batch.items.len(), 4); - - batch.items.clear(); - table.fill_batch(&mut batch); - assert!(batch.items.is_empty()); - } } diff --git a/polkadot/statement-table/src/lib.rs b/polkadot/statement-table/src/lib.rs index 86b95b0d90ff1..ecbe832b6a530 100644 --- a/polkadot/statement-table/src/lib.rs +++ b/polkadot/statement-table/src/lib.rs @@ -14,6 +14,7 @@ //! propose and attest to validity of candidates, and those who can only attest //! to availability. +extern crate substrate_codec as codec; extern crate substrate_primitives; extern crate polkadot_primitives as primitives; @@ -82,27 +83,3 @@ impl generic::Context for C { Context::requisite_votes(self, group) } } - -/// A batch of statements to send out. -pub trait StatementBatch { - /// Get the target authorities of these statements. - fn targets(&self) -> &[SessionKey]; - - /// If the batch is empty. - fn is_empty(&self) -> bool; - - /// Push a statement onto the batch. Returns false when the batch is full. - /// - /// This is meant to do work like incrementally serializing the statements - /// into a vector of bytes while making sure the length is below a certain - /// amount. - fn push(&mut self, statement: SignedStatement) -> bool; -} - -impl generic::StatementBatch for T { - fn targets(&self) -> &[SessionKey] { StatementBatch::targets(self ) } - fn is_empty(&self) -> bool { StatementBatch::is_empty(self) } - fn push(&mut self, statement: SignedStatement) -> bool { - StatementBatch::push(self, statement) - } -} diff --git a/polkadot/transaction-pool/Cargo.toml b/polkadot/transaction-pool/Cargo.toml index 89fa3e88c03b2..588db7ef0b11d 100644 --- a/polkadot/transaction-pool/Cargo.toml +++ b/polkadot/transaction-pool/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] [dependencies] log = "0.3.0" -error-chain = "0.11" +error-chain = "0.12" parking_lot = "0.4" polkadot-api = { path = "../api" } polkadot-primitives = { path = "../primitives" } diff --git a/polkadot/transaction-pool/README.adoc b/polkadot/transaction-pool/README.adoc new file mode 100644 index 0000000000000..868a3434b3e9e --- /dev/null +++ b/polkadot/transaction-pool/README.adoc @@ -0,0 +1,5 @@ + += Polkadot Transactin pool + +placeholder +//TODO Write content :) diff --git a/polkadot/transaction-pool/src/error.rs b/polkadot/transaction-pool/src/error.rs index 78f9d3e771041..ef6cdf6b4166c 100644 --- a/polkadot/transaction-pool/src/error.rs +++ b/polkadot/transaction-pool/src/error.rs @@ -15,12 +15,14 @@ // along with Polkadot. If not, see . use extrinsic_pool::{self, txpool}; +use polkadot_api; use primitives::Hash; use runtime::{Address, UncheckedExtrinsic}; error_chain! { links { Pool(txpool::Error, txpool::ErrorKind); + Api(polkadot_api::Error, polkadot_api::ErrorKind); } errors { /// Unexpected extrinsic format submitted @@ -53,11 +55,6 @@ error_chain! { description("Unrecognised address in extrinsic"), display("Unrecognised address in extrinsic: {}", who), } - /// Extrinsic is not yet checked. - NotReady { - description("Indexed address is unverified"), - display("Indexed address is unverified"), - } } } diff --git a/polkadot/transaction-pool/src/lib.rs b/polkadot/transaction-pool/src/lib.rs index 843af20fb16f2..265f72ba9903a 100644 --- a/polkadot/transaction-pool/src/lib.rs +++ b/polkadot/transaction-pool/src/lib.rs @@ -15,9 +15,10 @@ // along with Polkadot. If not, see . extern crate ed25519; +extern crate substrate_client as client; extern crate substrate_codec as codec; extern crate substrate_extrinsic_pool as extrinsic_pool; -extern crate substrate_primitives as substrate_primitives; +extern crate substrate_primitives; extern crate substrate_runtime_primitives; extern crate polkadot_runtime as runtime; extern crate polkadot_primitives as primitives; @@ -37,87 +38,41 @@ mod error; use std::{ cmp::Ordering, - collections::{hash_map::Entry, HashMap}, + collections::HashMap, ops::Deref, sync::Arc, - result }; -use parking_lot::Mutex; -use codec::Slicable; -use extrinsic_pool::{Pool, txpool::{self, Readiness, scoring::{Change, Choice}}}; -use extrinsic_pool::api::ExtrinsicPool; +use codec::{Decode, Encode}; +use extrinsic_pool::{ + api::{ExtrinsicPool, EventStream}, + txpool::{self, Readiness, scoring::{Change, Choice}}, + watcher::Watcher, + Pool, + Listener, +}; use polkadot_api::PolkadotApi; -use primitives::{AccountId, AccountIndex, Hash, Index, UncheckedExtrinsic as FutureProofUncheckedExtrinsic}; -use runtime::{Address, RawAddress, UncheckedExtrinsic}; -use substrate_runtime_primitives::traits::{Bounded, Checkable, Hashing, BlakeTwo256}; +use primitives::{AccountId, BlockId, Hash, Index, UncheckedExtrinsic as FutureProofUncheckedExtrinsic}; +use runtime::{Address, UncheckedExtrinsic}; +use substrate_runtime_primitives::traits::{Bounded, Checkable, Hash as HashT, BlakeTwo256}; pub use extrinsic_pool::txpool::{Options, Status, LightStatus, VerifiedTransaction as VerifiedTransactionOps}; pub use error::{Error, ErrorKind, Result}; /// Type alias for convenience. -pub type CheckedExtrinsic = ::Checked; +pub type CheckedExtrinsic = std::result::Result>>::Checked; /// A verified transaction which should be includable and non-inherent. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct VerifiedTransaction { original: UncheckedExtrinsic, - // `create()` will leave this as `Some` only if the `Address` is an `AccountId`, otherwise a - // call to `polish` is needed. - inner: Mutex>, + inner: Option, + sender: Option, hash: Hash, encoded_size: usize, } -impl Clone for VerifiedTransaction { - fn clone(&self) -> Self { - VerifiedTransaction { - original: self.original.clone(), - inner: Mutex::new(self.inner.lock().clone()), - hash: self.hash.clone(), - encoded_size: self.encoded_size.clone(), - } - } -} - impl VerifiedTransaction { - /// Attempt to verify a transaction. - fn create(original: UncheckedExtrinsic) -> Result { - if !original.is_signed() { - bail!(ErrorKind::IsInherent(original)) - } - const UNAVAILABLE_MESSAGE: &'static str = "chain state not available"; - let (encoded_size, hash) = original.using_encoded(|e| (e.len(), BlakeTwo256::hash(e))); - let lookup = |a| match a { - RawAddress::Id(i) => Ok(i), - _ => Err(UNAVAILABLE_MESSAGE), - }; - let inner = Mutex::new(match original.clone().check(lookup) { - Ok(xt) => Some(xt), - Err(e) if e == UNAVAILABLE_MESSAGE => None, - Err(e) => bail!(ErrorKind::BadSignature(e)), - }); - Ok(VerifiedTransaction { original, inner, hash, encoded_size }) - } - - /// If this transaction isn't really verified, verify it and morph it into a really verified - /// transaction. - pub fn polish(&self, lookup: F) -> Result<()> where - F: FnOnce(Address) -> result::Result + Send + Sync - { - let inner: result::Result = self.original - .clone() - .check(lookup) - .map_err(|e| ErrorKind::BadSignature(e).into()); - *self.inner.lock() = Some(inner?); - Ok(()) - } - - /// Is this transaction *really* verified? - pub fn is_really_verified(&self) -> bool { - self.inner.lock().is_some() - } - /// Access the underlying transaction. pub fn as_transaction(&self) -> &UncheckedExtrinsic { &self.original @@ -125,13 +80,13 @@ impl VerifiedTransaction { /// Convert to primitive unchecked extrinsic. pub fn primitive_extrinsic(&self) -> ::primitives::UncheckedExtrinsic { - Slicable::decode(&mut self.as_transaction().encode().as_slice()) + Decode::decode(&mut self.as_transaction().encode().as_slice()) .expect("UncheckedExtrinsic shares repr with Vec; qed") } - /// Consume the verified transaciton, yielding the unchecked counterpart. - pub fn into_inner(self) -> Result { - self.inner.lock().clone().ok_or_else(|| ErrorKind::NotReady.into()) + /// Consume the verified transaction, yielding the checked counterpart. + pub fn into_inner(self) -> Option { + self.inner } /// Get the 256-bit hash of this transaction. @@ -140,8 +95,8 @@ impl VerifiedTransaction { } /// Get the account ID of the sender of this transaction. - pub fn sender(&self) -> Result { - self.inner.lock().as_ref().map(|i| i.signed.clone()).ok_or_else(|| ErrorKind::NotReady.into()) + pub fn sender(&self) -> Option { + self.sender } /// Get the account ID of the sender of this transaction. @@ -153,22 +108,27 @@ impl VerifiedTransaction { pub fn encoded_size(&self) -> usize { self.encoded_size } + + /// Returns `true` if the transaction is not yet fully verified. + pub fn is_fully_verified(&self) -> bool { + self.inner.is_some() + } } impl txpool::VerifiedTransaction for VerifiedTransaction { type Hash = Hash; - type Sender = Address; + type Sender = Option; fn hash(&self) -> &Self::Hash { &self.hash } fn sender(&self) -> &Self::Sender { - self.original.sender() + &self.sender } fn mem_usage(&self) -> usize { - 1 // TODO + self.encoded_size // TODO } } @@ -184,7 +144,19 @@ impl txpool::Scoring for Scoring { old.index().cmp(&other.index()) } - fn choose(&self, _old: &VerifiedTransaction, _new: &VerifiedTransaction) -> Choice { + fn choose(&self, old: &VerifiedTransaction, new: &VerifiedTransaction) -> Choice { + if old.is_fully_verified() { + assert!(new.is_fully_verified(), "Scoring::choose called with transactions from different senders"); + if old.index() == new.index() { + // TODO [ToDr] Do we allow replacement? If yes then it should be Choice::ReplaceOld + return Choice::RejectNew; + } + } + + // This will keep both transactions, even though they have the same indices. + // It's fine for not fully verified transactions, we might also allow it for + // verified transactions but it would mean that only one of the two is actually valid + // (most likely the first to be included in the block). Choice::InsertNew } @@ -195,33 +167,37 @@ impl txpool::Scoring for Scoring { _change: Change<()> ) { for i in 0..xts.len() { - // all the same score since there are no fees. - // TODO: prioritize things like misbehavior or fishermen reports - scores[i] = 1; + if !xts[i].is_fully_verified() { + scores[i] = 0; + } else { + // all the same score since there are no fees. + // TODO: prioritize things like misbehavior or fishermen reports + scores[i] = 1; + } } } - fn should_replace(&self, _old: &VerifiedTransaction, _new: &VerifiedTransaction) -> bool { - false // no fees to determine which is better. + + fn should_replace(&self, old: &VerifiedTransaction, _new: &VerifiedTransaction) -> bool { + // Always replace not fully verified transactions. + !old.is_fully_verified() } } /// Readiness evaluator for polkadot transactions. -pub struct Ready<'a, T: 'a + PolkadotApi> { - at_block: T::CheckedBlockId, - api: &'a T, - known_nonces: HashMap, - known_indexes: HashMap, +pub struct Ready<'a, A: 'a + PolkadotApi> { + at_block: BlockId, + api: &'a A, + known_nonces: HashMap, } -impl<'a, T: 'a + PolkadotApi> Ready<'a, T> { +impl<'a, A: 'a + PolkadotApi> Ready<'a, A> { /// Create a new readiness evaluator at the given block. Requires that /// the ID has already been checked for local corresponding and available state. - pub fn create(at: T::CheckedBlockId, api: &'a T) -> Self { + fn create(at: BlockId, api: &'a A) -> Self { Ready { at_block: at, api, known_nonces: HashMap::new(), - known_indexes: HashMap::new(), } } } @@ -232,139 +208,244 @@ impl<'a, T: 'a + PolkadotApi> Clone for Ready<'a, T> { at_block: self.at_block.clone(), api: self.api, known_nonces: self.known_nonces.clone(), - known_indexes: self.known_indexes.clone(), } } } -impl<'a, T: 'a + PolkadotApi> txpool::Ready for Ready<'a, T> +impl<'a, A: 'a + PolkadotApi> txpool::Ready for Ready<'a, A> { fn is_ready(&mut self, xt: &VerifiedTransaction) -> Readiness { - if !xt.is_really_verified() { - let id = match xt.original.extrinsic.signed.clone() { - RawAddress::Id(id) => id.clone(), // should never happen, since we're not verified. - RawAddress::Index(i) => match self.known_indexes.entry(i) { - Entry::Occupied(e) => e.get().clone(), - Entry::Vacant(e) => { - let (api, at_block) = (&self.api, &self.at_block); - if let Some(id) = api.lookup(at_block, RawAddress::Index(i)) - .ok() - .and_then(|o| o) - { - e.insert(id.clone()); - id - } else { - // Invalid index. - // return stale in order to get the pool to throw it away. - return Readiness::Stale - } - } - }, - }; - if VerifiedTransaction::polish(xt, move |_| Ok(id)).is_err() { - // Invalid signature. - // return stale in order to get the pool to throw it away. - return Readiness::Stale - } - } - - // guaranteed to be properly verified at this point. + let sender = match xt.sender() { + Some(sender) => sender, + None => return Readiness::Future + }; - let sender = xt.sender().expect("only way to get here is `is_really_verified` or successful `polish`; either guarantees `is_really_verified`; `sender` is `Ok` if `is_really_verified`; qed"); trace!(target: "transaction-pool", "Checking readiness of {} (from {})", xt.hash, Hash::from(sender)); - let is_index_sender = match xt.original.extrinsic.signed { RawAddress::Index(_) => false, _ => true }; - // TODO: find a way to handle index error properly -- will need changes to // transaction-pool trait. let (api, at_block) = (&self.api, &self.at_block); - let get_nonce = || api.index(at_block, sender).ok().unwrap_or_else(Bounded::max_value); - let (next_nonce, was_index_sender) = self.known_nonces.entry(sender).or_insert_with(|| (get_nonce(), is_index_sender)); - - trace!(target: "transaction-pool", "Next index for sender is {}; xt index is {}", next_nonce, xt.original.extrinsic.index); - - if *was_index_sender == is_index_sender || get_nonce() == *next_nonce { - match xt.original.extrinsic.index.cmp(&next_nonce) { - Ordering::Greater => Readiness::Future, - Ordering::Less => Readiness::Stale, - Ordering::Equal => { - // remember to increment `next_nonce` - // TODO: this won't work perfectly since accounts can now be killed, returning the nonce - // to zero. - *next_nonce = next_nonce.saturating_add(1); - Readiness::Ready - } - } - } else { - // ignore for now. - Readiness::Future - } + let next_index = self.known_nonces.entry(sender) + .or_insert_with(|| api.index(at_block, sender).ok().unwrap_or_else(Bounded::max_value)); + + trace!(target: "transaction-pool", "Next index for sender is {}; xt index is {}", next_index, xt.original.extrinsic.index); + + let result = match xt.original.extrinsic.index.cmp(&next_index) { + // TODO: this won't work perfectly since accounts can now be killed, returning the nonce + // to zero. + // We should detect if the index was reset and mark all transactions as `Stale` for cull to work correctly. + // Otherwise those transactions will keep occupying the queue. + // Perhaps we could mark as stale if `index - state_index` > X? + Ordering::Greater => Readiness::Future, + Ordering::Equal => Readiness::Ready, + // TODO [ToDr] Should mark transactions referrencing too old blockhash as `Stale` as well. + Ordering::Less => Readiness::Stale, + }; + + // remember to increment `next_index` + *next_index = next_index.saturating_add(1); + + result } } -pub struct Verifier; +pub struct Verifier<'a, A: 'a> { + api: &'a A, + at_block: BlockId, +} -impl txpool::Verifier for Verifier { +impl<'a, A> Verifier<'a, A> where + A: 'a + PolkadotApi, +{ + const NO_ACCOUNT: &'static str = "Account not found."; + + fn lookup(&self, address: Address) -> ::std::result::Result { + // TODO [ToDr] Consider introducing a cache for this. + match self.api.lookup(&self.at_block, address.clone()) { + Ok(Some(address)) => Ok(address), + Ok(None) => Err(Self::NO_ACCOUNT.into()), + Err(e) => { + error!("Error looking up address: {:?}: {:?}", address, e); + Err("API error.") + }, + } + } +} + +impl<'a, A> txpool::Verifier for Verifier<'a, A> where + A: 'a + PolkadotApi, +{ type VerifiedTransaction = VerifiedTransaction; type Error = Error; fn verify_transaction(&self, uxt: UncheckedExtrinsic) -> Result { - info!("Extrinsic Submitted: {:?}", uxt); - VerifiedTransaction::create(uxt) + + if !uxt.is_signed() { + bail!(ErrorKind::IsInherent(uxt)) + } + + let encoded = uxt.encode(); + let (encoded_size, hash) = (encoded.len(), BlakeTwo256::hash(&encoded)); + + debug!(target: "transaction-pool", "Transaction submitted: {}", ::substrate_primitives::hexdisplay::HexDisplay::from(&encoded)); + + let inner = match uxt.clone().check_with(|a| self.lookup(a)) { + Ok(xt) => Some(xt), + // keep the transaction around in the future pool and attempt to promote it later. + Err(Self::NO_ACCOUNT) => None, + Err(e) => bail!(e), + }; + let sender = inner.as_ref().map(|x| x.signed.clone()); + + if encoded_size < 1024 { + info!(target: "transaction-pool", "Transaction verified: {} => {:?}", hash, uxt); + } else { + info!(target: "transaction-pool", "Transaction verified: {} ({} bytes is too large to display)", hash, encoded_size); + } + + Ok(VerifiedTransaction { + original: uxt, + inner, + sender, + hash, + encoded_size + }) } } /// The polkadot transaction pool. /// /// Wraps a `extrinsic_pool::Pool`. -pub struct TransactionPool { - inner: Pool, +pub struct TransactionPool { + inner: Pool, + api: Arc, } -impl TransactionPool { +impl TransactionPool where + A: PolkadotApi, +{ /// Create a new transaction pool. - pub fn new(options: Options) -> Self { + pub fn new(options: Options, api: Arc) -> Self { TransactionPool { - inner: Pool::new(options, Verifier, Scoring), + inner: Pool::new(options, Scoring), + api, + } + } + + /// Attempt to directly import `UncheckedExtrinsic` without going through serialization. + pub fn import_unchecked_extrinsic(&self, block: BlockId, uxt: UncheckedExtrinsic) -> Result> { + let verifier = Verifier { + api: &*self.api, + at_block: block, + }; + self.inner.submit(verifier, vec![uxt]).map(|mut v| v.swap_remove(0)) + } + + /// Retry to import all semi-verified transactions (unknown account indices) + pub fn retry_verification(&self, block: BlockId) -> Result<()> { + let to_reverify = self.inner.remove_sender(None); + let verifier = Verifier { + api: &*self.api, + at_block: block, + }; + + self.inner.submit(verifier, to_reverify.into_iter().map(|tx| tx.original.clone()))?; + Ok(()) + } + + /// Reverify transaction that has been reported incorrect. + /// + /// Returns `Ok(None)` in case the hash is missing, `Err(e)` in case of verification error and new transaction + /// reference otherwise. + /// + /// TODO [ToDr] That method is currently unused, should be used together with BlockBuilder + /// when we detect that particular transaction has failed. + /// In such case we will attempt to remove or re-verify it. + pub fn reverify_transaction(&self, block: BlockId, hash: Hash) -> Result>> { + let result = self.inner.remove(&[hash], false).pop().expect("One hash passed; one result received; qed"); + if let Some(tx) = result { + self.import_unchecked_extrinsic(block, tx.original.clone()).map(Some) + } else { + Ok(None) } } - // TODO: remove. This is pointless - just use `submit()` directly. - pub fn import_unchecked_extrinsic(&self, uxt: UncheckedExtrinsic) -> Result> { - self.inner.submit(vec![uxt]).map(|mut v| v.swap_remove(0)) + /// Cull old transactions from the queue. + pub fn cull(&self, block: BlockId) -> Result { + let ready = Ready::create(block, &*self.api); + Ok(self.inner.cull(None, ready)) + } + + /// Cull transactions from the queue and then compute the pending set. + pub fn cull_and_get_pending(&self, block: BlockId, f: F) -> Result where + F: FnOnce(txpool::PendingIterator, Scoring, Listener>) -> T, + { + let ready = Ready::create(block, &*self.api); + self.inner.cull(None, ready.clone()); + Ok(self.inner.pending(ready, f)) + } + + /// Remove a set of transactions idenitified by hashes. + pub fn remove(&self, hashes: &[Hash], is_valid: bool) -> Vec>> { + self.inner.remove(hashes, is_valid) } } -impl Deref for TransactionPool { - type Target = Pool; +impl Deref for TransactionPool { + type Target = Pool; fn deref(&self) -> &Self::Target { &self.inner } } -impl ExtrinsicPool for TransactionPool { +// TODO: more general transaction pool, which can handle more kinds of vec-encoded transactions, +// even when runtime is out of date. +impl ExtrinsicPool for TransactionPool where + A: Send + Sync + 'static, + A: PolkadotApi, +{ type Error = Error; - fn submit(&self, xts: Vec) -> Result> { - // TODO: more general transaction pool, which can handle more kinds of vec-encoded transactions, - // even when runtime is out of date. + fn submit(&self, block: BlockId, xts: Vec) -> Result> { xts.into_iter() .map(|xt| xt.encode()) - .map(|encoded| UncheckedExtrinsic::decode(&mut &encoded[..])) - .map(|maybe_decoded| maybe_decoded.ok_or_else(|| ErrorKind::InvalidExtrinsicFormat.into())) - .map(|x| x.and_then(|x| self.import_unchecked_extrinsic(x))) - .map(|x| x.map(|x| x.hash().clone())) + .map(|encoded| { + let decoded = UncheckedExtrinsic::decode(&mut &encoded[..]).ok_or(ErrorKind::InvalidExtrinsicFormat)?; + let tx = self.import_unchecked_extrinsic(block, decoded)?; + Ok(*tx.hash()) + }) .collect() } + + fn submit_and_watch(&self, block: BlockId, xt: FutureProofUncheckedExtrinsic) -> Result> { + let encoded = xt.encode(); + let decoded = UncheckedExtrinsic::decode(&mut &encoded[..]).ok_or(ErrorKind::InvalidExtrinsicFormat)?; + + let verifier = Verifier { + api: &*self.api, + at_block: block, + }; + + self.inner.submit_and_watch(verifier, decoded) + } + + fn light_status(&self) -> LightStatus { + self.inner.light_status() + } + + fn import_notification_stream(&self) -> EventStream { + self.inner.import_notification_stream() + } } #[cfg(test)] mod tests { - use super::{TransactionPool, Ready}; + use std::sync::{atomic::{self, AtomicBool}, Arc}; + use super::TransactionPool; use substrate_keyring::Keyring::{self, *}; - use codec::Slicable; - use polkadot_api::{PolkadotApi, BlockBuilder, CheckedBlockId, Result}; + use codec::{Decode, Encode}; + use polkadot_api::{PolkadotApi, BlockBuilder, Result}; use primitives::{AccountId, AccountIndex, Block, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic as FutureProofUncheckedExtrinsic}; use runtime::{RawAddress, Call, TimestampCall, BareExtrinsic, Extrinsic, UncheckedExtrinsic}; @@ -377,44 +458,52 @@ mod tests { fn bake(self) -> Result { unimplemented!() } } - #[derive(Clone)] - struct TestCheckedBlockId(pub BlockId); - impl CheckedBlockId for TestCheckedBlockId { - fn block_id(&self) -> &BlockId { &self.0 } + fn number_of(at: &BlockId) -> u32 { + match at { + generic::BlockId::Number(n) => *n as u32, + _ => 0, + } } - fn number_of(at: &TestCheckedBlockId) -> u32 { - match at.0 { - generic::BlockId::Number(n) => n as u32, - _ => 0, + #[derive(Default, Clone)] + struct TestPolkadotApi { + no_lookup: Arc, + } + + impl TestPolkadotApi { + fn without_lookup() -> Self { + TestPolkadotApi { + no_lookup: Arc::new(AtomicBool::new(true)), + } + } + + pub fn enable_lookup(&self) { + self.no_lookup.store(false, atomic::Ordering::SeqCst); } } - #[derive(Clone)] - struct TestPolkadotApi; impl PolkadotApi for TestPolkadotApi { - type CheckedBlockId = TestCheckedBlockId; type BlockBuilder = TestBlockBuilder; - fn check_id(&self, id: BlockId) -> Result { Ok(TestCheckedBlockId(id)) } - fn session_keys(&self, _at: &TestCheckedBlockId) -> Result> { unimplemented!() } - fn validators(&self, _at: &TestCheckedBlockId) -> Result> { unimplemented!() } - fn random_seed(&self, _at: &TestCheckedBlockId) -> Result { unimplemented!() } - fn duty_roster(&self, _at: &TestCheckedBlockId) -> Result { unimplemented!() } - fn timestamp(&self, _at: &TestCheckedBlockId) -> Result { unimplemented!() } - fn evaluate_block(&self, _at: &TestCheckedBlockId, _block: Block) -> Result { unimplemented!() } - fn active_parachains(&self, _at: &TestCheckedBlockId) -> Result> { unimplemented!() } - fn parachain_code(&self, _at: &TestCheckedBlockId, _parachain: ParaId) -> Result>> { unimplemented!() } - fn parachain_head(&self, _at: &TestCheckedBlockId, _parachain: ParaId) -> Result>> { unimplemented!() } - fn build_block(&self, _at: &TestCheckedBlockId, _timestamp: Timestamp, _new_heads: Vec) -> Result { unimplemented!() } - fn inherent_extrinsics(&self, _at: &TestCheckedBlockId, _timestamp: Timestamp, _new_heads: Vec) -> Result>> { unimplemented!() } - - fn index(&self, _at: &TestCheckedBlockId, _account: AccountId) -> Result { + fn session_keys(&self, _at: &BlockId) -> Result> { unimplemented!() } + fn validators(&self, _at: &BlockId) -> Result> { unimplemented!() } + fn random_seed(&self, _at: &BlockId) -> Result { unimplemented!() } + fn duty_roster(&self, _at: &BlockId) -> Result { unimplemented!() } + fn timestamp(&self, _at: &BlockId) -> Result { unimplemented!() } + fn evaluate_block(&self, _at: &BlockId, _block: Block) -> Result { unimplemented!() } + fn active_parachains(&self, _at: &BlockId) -> Result> { unimplemented!() } + fn parachain_code(&self, _at: &BlockId, _parachain: ParaId) -> Result>> { unimplemented!() } + fn parachain_head(&self, _at: &BlockId, _parachain: ParaId) -> Result>> { unimplemented!() } + fn build_block(&self, _at: &BlockId, _timestamp: Timestamp, _new_heads: Vec) -> Result { unimplemented!() } + fn inherent_extrinsics(&self, _at: &BlockId, _timestamp: Timestamp, _new_heads: Vec) -> Result>> { unimplemented!() } + + fn index(&self, _at: &BlockId, _account: AccountId) -> Result { Ok((_account[0] as u32) + number_of(_at)) } - fn lookup(&self, _at: &TestCheckedBlockId, _address: RawAddress) -> Result> { + fn lookup(&self, _at: &BlockId, _address: RawAddress) -> Result> { match _address { RawAddress::Id(i) => Ok(Some(i)), + RawAddress::Index(_) if self.no_lookup.load(atomic::Ordering::SeqCst) => Ok(None), RawAddress::Index(i) => Ok(match (i < 8, i + (number_of(_at) as u64) % 8) { (false, _) => None, (_, 0) => Some(Alice.to_raw_public().into()), @@ -456,130 +545,168 @@ mod tests { }, MaybeUnsigned(sig.into())).using_encoded(|e| UncheckedExtrinsic::decode(&mut &e[..])).unwrap() } + fn pool(api: &TestPolkadotApi) -> TransactionPool { + TransactionPool::new(Default::default(), Arc::new(api.clone())) + } + #[test] fn id_submission_should_work() { - let pool = TransactionPool::new(Default::default()); - pool.submit(vec![uxt(Alice, 209, true)]).unwrap(); + let api = TestPolkadotApi::default(); + let pool = pool(&api); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, true)).unwrap(); - let ready = Ready::create(TestPolkadotApi.check_id(BlockId::number(0)).unwrap(), &TestPolkadotApi); - let pending: Vec<_> = pool.cull_and_get_pending(ready, |p| p.map(|a| (a.sender().ok(), a.index())).collect()); + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); assert_eq!(pending, vec![(Some(Alice.to_raw_public().into()), 209)]); } #[test] fn index_submission_should_work() { - let pool = TransactionPool::new(Default::default()); - pool.submit(vec![uxt(Alice, 209, false)]).unwrap(); + let api = TestPolkadotApi::default(); + let pool = pool(&api); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, false)).unwrap(); - let ready = Ready::create(TestPolkadotApi.check_id(BlockId::number(0)).unwrap(), &TestPolkadotApi); - let pending: Vec<_> = pool.cull_and_get_pending(ready, |p| p.map(|a| (a.sender().ok(), a.index())).collect()); + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); assert_eq!(pending, vec![(Some(Alice.to_raw_public().into()), 209)]); } #[test] fn multiple_id_submission_should_work() { - let pool = TransactionPool::new(Default::default()); - pool.submit(vec![uxt(Alice, 209, true)]).unwrap(); - pool.submit(vec![uxt(Alice, 210, true)]).unwrap(); + let api = TestPolkadotApi::default(); + let pool = pool(&api); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, true)).unwrap(); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 210, true)).unwrap(); - let ready = Ready::create(TestPolkadotApi.check_id(BlockId::number(0)).unwrap(), &TestPolkadotApi); - let pending: Vec<_> = pool.cull_and_get_pending(ready, |p| p.map(|a| (a.sender().ok(), a.index())).collect()); + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); assert_eq!(pending, vec![(Some(Alice.to_raw_public().into()), 209), (Some(Alice.to_raw_public().into()), 210)]); } #[test] fn multiple_index_submission_should_work() { - let pool = TransactionPool::new(Default::default()); - pool.submit(vec![uxt(Alice, 209, false)]).unwrap(); - pool.submit(vec![uxt(Alice, 210, false)]).unwrap(); + let api = TestPolkadotApi::default(); + let pool = pool(&api); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, false)).unwrap(); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 210, false)).unwrap(); - let ready = Ready::create(TestPolkadotApi.check_id(BlockId::number(0)).unwrap(), &TestPolkadotApi); - let pending: Vec<_> = pool.cull_and_get_pending(ready, |p| p.map(|a| (a.sender().ok(), a.index())).collect()); + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); assert_eq!(pending, vec![(Some(Alice.to_raw_public().into()), 209), (Some(Alice.to_raw_public().into()), 210)]); } #[test] fn id_based_early_nonce_should_be_culled() { - let pool = TransactionPool::new(Default::default()); - pool.submit(vec![uxt(Alice, 208, true)]).unwrap(); + let api = TestPolkadotApi::default(); + let pool = pool(&api); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 208, true)).unwrap(); - let ready = Ready::create(TestPolkadotApi.check_id(BlockId::number(0)).unwrap(), &TestPolkadotApi); - let pending: Vec<_> = pool.cull_and_get_pending(ready, |p| p.map(|a| (a.sender().ok(), a.index())).collect()); + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); assert_eq!(pending, vec![]); } #[test] fn index_based_early_nonce_should_be_culled() { - let pool = TransactionPool::new(Default::default()); - pool.submit(vec![uxt(Alice, 208, false)]).unwrap(); + let api = TestPolkadotApi::default(); + let pool = pool(&api); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 208, false)).unwrap(); - let ready = Ready::create(TestPolkadotApi.check_id(BlockId::number(0)).unwrap(), &TestPolkadotApi); - let pending: Vec<_> = pool.cull_and_get_pending(ready, |p| p.map(|a| (a.sender().ok(), a.index())).collect()); + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); assert_eq!(pending, vec![]); } #[test] fn id_based_late_nonce_should_be_queued() { - let pool = TransactionPool::new(Default::default()); - let ready = || Ready::create(TestPolkadotApi.check_id(BlockId::number(0)).unwrap(), &TestPolkadotApi); + let api = TestPolkadotApi::default(); + let pool = pool(&api); - pool.submit(vec![uxt(Alice, 210, true)]).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(ready(), |p| p.map(|a| (a.sender().ok(), a.index())).collect()); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 210, true)).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); assert_eq!(pending, vec![]); - pool.submit(vec![uxt(Alice, 209, true)]).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(ready(), |p| p.map(|a| (a.sender().ok(), a.index())).collect()); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, true)).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); assert_eq!(pending, vec![(Some(Alice.to_raw_public().into()), 209), (Some(Alice.to_raw_public().into()), 210)]); } #[test] fn index_based_late_nonce_should_be_queued() { - let pool = TransactionPool::new(Default::default()); - let ready = || Ready::create(TestPolkadotApi.check_id(BlockId::number(0)).unwrap(), &TestPolkadotApi); + let api = TestPolkadotApi::default(); + let pool = pool(&api); - pool.submit(vec![uxt(Alice, 210, false)]).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(ready(), |p| p.map(|a| (a.sender().ok(), a.index())).collect()); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 210, false)).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); assert_eq!(pending, vec![]); - pool.submit(vec![uxt(Alice, 209, false)]).unwrap(); - let pending: Vec<_> = pool.cull_and_get_pending(ready(), |p| p.map(|a| (a.sender().ok(), a.index())).collect()); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, false)).unwrap(); + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); assert_eq!(pending, vec![(Some(Alice.to_raw_public().into()), 209), (Some(Alice.to_raw_public().into()), 210)]); } #[test] fn index_then_id_submission_should_make_progress() { - let pool = TransactionPool::new(Default::default()); - pool.submit(vec![uxt(Alice, 209, false)]).unwrap(); - pool.submit(vec![uxt(Alice, 210, true)]).unwrap(); + let api = TestPolkadotApi::without_lookup(); + let pool = pool(&api); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, false)).unwrap(); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 210, true)).unwrap(); + + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + assert_eq!(pending, vec![]); - let ready = Ready::create(TestPolkadotApi.check_id(BlockId::number(0)).unwrap(), &TestPolkadotApi); - let pending: Vec<_> = pool.cull_and_get_pending(ready, |p| p.map(|a| (a.sender().ok(), a.index())).collect()); + api.enable_lookup(); + pool.retry_verification(BlockId::number(0)).unwrap(); + + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); assert_eq!(pending, vec![ - (Some(Alice.to_raw_public().into()), 209) + (Some(Alice.to_raw_public().into()), 209), + (Some(Alice.to_raw_public().into()), 210) ]); } + #[test] + fn retrying_verification_might_not_change_anything() { + let api = TestPolkadotApi::without_lookup(); + let pool = pool(&api); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, false)).unwrap(); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 210, true)).unwrap(); + + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + assert_eq!(pending, vec![]); + + pool.retry_verification(BlockId::number(1)).unwrap(); + + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + assert_eq!(pending, vec![]); + } + #[test] fn id_then_index_submission_should_make_progress() { - let pool = TransactionPool::new(Default::default()); - pool.submit(vec![uxt(Alice, 209, true)]).unwrap(); - pool.submit(vec![uxt(Alice, 210, false)]).unwrap(); + let api = TestPolkadotApi::without_lookup(); + let pool = pool(&api); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 209, true)).unwrap(); + pool.import_unchecked_extrinsic(BlockId::number(0), uxt(Alice, 210, false)).unwrap(); - let ready = Ready::create(TestPolkadotApi.check_id(BlockId::number(0)).unwrap(), &TestPolkadotApi); - let pending: Vec<_> = pool.cull_and_get_pending(ready, |p| p.map(|a| (a.sender().ok(), a.index())).collect()); + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); assert_eq!(pending, vec![ (Some(Alice.to_raw_public().into()), 209) ]); + + // when + api.enable_lookup(); + pool.retry_verification(BlockId::number(0)).unwrap(); + + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(0), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); + assert_eq!(pending, vec![ + (Some(Alice.to_raw_public().into()), 209), + (Some(Alice.to_raw_public().into()), 210) + ]); } #[test] fn index_change_should_result_in_second_tx_culled_or_future() { - let pool = TransactionPool::new(Default::default()); - pool.submit(vec![uxt(Alice, 209, false)]).unwrap(); - pool.submit(vec![uxt(Alice, 210, false)]).unwrap(); + let api = TestPolkadotApi::default(); + let pool = pool(&api); + let block = BlockId::number(0); + pool.import_unchecked_extrinsic(block, uxt(Alice, 209, false)).unwrap(); + let hash = *pool.import_unchecked_extrinsic(block, uxt(Alice, 210, false)).unwrap().hash(); - let ready = Ready::create(TestPolkadotApi.check_id(BlockId::number(0)).unwrap(), &TestPolkadotApi); - let pending: Vec<_> = pool.cull_and_get_pending(ready, |p| p.map(|a| (a.sender().ok(), a.index())).collect()); + let pending: Vec<_> = pool.cull_and_get_pending(block, |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); assert_eq!(pending, vec![ (Some(Alice.to_raw_public().into()), 209), (Some(Alice.to_raw_public().into()), 210) @@ -593,11 +720,14 @@ mod tests { // after this, a re-evaluation of the second's readiness should result in it being thrown // out (or maybe placed in future queue). -/* - // TODO: uncomment once the new queue design is in. - let ready = Ready::create(TestPolkadotApi.check_id(BlockId::number(1)).unwrap(), &TestPolkadotApi); - let pending: Vec<_> = pool.cull_and_get_pending(ready, |p| p.map(|a| (a.sender().ok(), a.index())).collect()); + let err = pool.reverify_transaction(BlockId::number(1), hash).unwrap_err(); + match *err.kind() { + ::error::ErrorKind::Msg(ref m) if m == "bad signature in extrinsic" => {}, + ref e => assert!(false, "The transaction should be rejected with BadSignature error, got: {:?}", e), + } + + let pending: Vec<_> = pool.cull_and_get_pending(BlockId::number(1), |p| p.map(|a| (a.sender(), a.index())).collect()).unwrap(); assert_eq!(pending, vec![]); -*/ + } } diff --git a/subkey/Cargo.toml b/subkey/Cargo.toml index 8ea7a05fc1dae..c9bb23962dea4 100644 --- a/subkey/Cargo.toml +++ b/subkey/Cargo.toml @@ -7,3 +7,6 @@ authors = ["Parity Technologies "] ed25519 = { version = "*", path = "../substrate/ed25519" } substrate-primitives = { version = "*", path = "../substrate/primitives" } rand = "0.4" + +[features] +bench = [] diff --git a/subkey/README.adoc b/subkey/README.adoc new file mode 100644 index 0000000000000..e895ab07adae8 --- /dev/null +++ b/subkey/README.adoc @@ -0,0 +1,22 @@ += Subkey + +A key generation utility with vanity address support. + +Usage: + + subkey + +Sample use: + + $ subkey +or + $ subkey polka +or + $ subkey polka 3 + + +Result: + + 5CxS39ykKsmPetYQjTqW6aJXkSChnuvPdziA8uphuPaCyRZ1: 406ac59ccbb8358f7c95b726d3ccb039afe35e2dd62045189d1abae8d7805b8a (54%) + 5CujMhFmChyq3AMUwMasfbqSpZYpbFfZS5UQ7zUn2d63CGBo: 5b6ac59ccbb8358f7c95b726d3ccb039afe35e2dd62045189d1abae8d7805b8a (69%) + 5EfdN3zChABKsXT9bEg33zqPsBu4YCu1h7yoovvjtsUMqyFU: c46ac59ccbb8358f7c95b726d3ccb039afe35e2dd62045189d1abae8d7805b8a (69%) diff --git a/subkey/src/main.rs b/subkey/src/main.rs index 1186ad8a51c10..471ed8754175c 100644 --- a/subkey/src/main.rs +++ b/subkey/src/main.rs @@ -1,3 +1,6 @@ +#![cfg_attr(feature = "bench", feature(test))] +#[cfg(feature = "bench")] +extern crate test; extern crate ed25519; extern crate substrate_primitives; extern crate rand; @@ -6,6 +9,7 @@ use rand::{OsRng, Rng}; use std::env::args; use ed25519::Pair; use substrate_primitives::hexdisplay::HexDisplay; +use std::cmp; fn good_waypoint(done: u64) -> u64 { match done { @@ -26,39 +30,60 @@ fn next_seed(mut seed: [u8; 32]) -> [u8; 32] { return seed; } -fn main() { - if args().len() != 2 { - println!("Usage: subkey "); - return; - } - let desired = args().last().unwrap(); - let score = |s: &str| { - for truncate in 0..desired.len() - 1 { - let snip_size = desired.len() - truncate; - let truncated = &desired[0..snip_size]; - if let Some(pos) = s.find(truncated) { - return (31 - pos) + (snip_size * 32); - } +/// A structure used to carry both Pair and seed. +/// This should usually NOT been used. If unsure, use Pair. +pub struct KeyPair { + pub pair: Pair, + pub seed: [u8; 32], + pub score: usize, +} + +/// Calculate the score of a key based on the desired +/// input. +fn calculate_score(_desired: &str, key: &str) -> usize { + for truncate in 0.._desired.len() { + let snip_size = _desired.len() - truncate; + let truncated = &_desired[0..snip_size]; + if let Some(pos) = key.find(truncated) { + let score = cmp::min(100, (51 - pos) + (snip_size * 50 / _desired.len())); + return score; } - 0 - }; - let top = 30 + (desired.len() * 32); + } + 0 +} + +pub fn generate_key(_desired: &str, _amount: usize, paranoiac: bool) -> Result, &str> { + println!("Generating {} keys with pattern '{}'", _amount, &_desired); + + let top = 30 + (_desired.len() * 32); let mut best = 0; let mut seed = [0u8; 32]; let mut done = 0; + let mut res = vec![]; + + OsRng::new().unwrap().fill_bytes(&mut seed[..]); + loop { + if res.len() >= _amount { break; } + // reset to a new random seed at beginning and regularly after for paranoia. - if done % 100000 == 0 { + if paranoiac || done % 100000 == 0 { OsRng::new().unwrap().fill_bytes(&mut seed[..]); } let p = Pair::from_seed(&seed); let ss58 = p.public().to_ss58check(); - let s = score(&ss58); - if s > best { - println!("{}: {} ({}% complete)", ss58, HexDisplay::from(&seed), s * 100 / top); - best = s; + let score = calculate_score(&_desired, &ss58); + if score > best || _desired.len() < 2 { + best = score; + let keypair = KeyPair { + pair: p, + seed: seed.clone(), + score: score, + }; + res.push(keypair); if best == top { + println!("best: {} == top: {}", best, top); break; } } @@ -66,7 +91,85 @@ fn main() { done += 1; if done % good_waypoint(done) == 0 { - println!("{} keys searched", done); + println!("Stopping after {} keys searched", done); + break; } } + res.sort_unstable_by(|a, b| b.score.cmp(&a.score)); + Ok(res) +} + +fn main() { + let desired: String = args().nth(1).unwrap_or_default(); + let amount_of_keys: String = args().nth(2).unwrap_or_else(|| String::from("1")); + let amount_of_keys: usize = amount_of_keys.parse::().expect("Failed to parse number"); + + let keys = generate_key(&desired, amount_of_keys, true).expect("Key generation failed"); + for key in keys { + println!("{} - {} ({}%)", + key.pair.public().to_ss58check(), + HexDisplay::from(&key.seed), + key.score); + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[cfg(feature = "bench")] + use test::Bencher; + + #[test] + fn test_generation_no_args() { + assert!(generate_key("",1, false).unwrap().len() == 1); + } + + #[test] + fn test_generation_with_single_char() { + assert!(generate_key("j", 1, false).unwrap().len() == 1); + } + + #[test] + fn test_generation_with_args() { + assert!(generate_key("polka", 2, false).unwrap().len() == 2); + } + + #[test] + fn test_score_1_char_100() { + let score = calculate_score("j", "5jolkadotwHY5k9GpdTgpqs9xjuNvtv8EcwCFpEeyEf3KHim"); + assert!(score == 100, format!("Wrong score, we found {}", score)); + } + + #[test] + fn test_score_100() { + let score = calculate_score("Polkadot", "5PolkadotwHY5k9GpdTgpqs9xjuNvtv8EcwCFpEeyEf3KHim"); + assert!( score == 100, format!("Wrong score, we found {}", score)); + } + + #[test] + fn test_score_50_2() { + // 50% for the position + 50% for the size + assert!(calculate_score("Polkadot", "5PolkXXXXwHY5k9GpdTgpqs9xjuNvtv8EcwCFpEeyEf3KHim") == 75); + } + + #[test] + fn test_score_0() { + assert!(calculate_score("Polkadot", "5GUWv4bLCchGUHJrzULXnh4JgXsMpTKRnjuXTY7Qo1Kh9uYK") == 0); + } + + #[cfg(feature = "bench")] + #[bench] + fn bench_paranoiac(b: &mut Bencher) { + b.iter(|| { + generate_key("polka", 3, true) + }); + } + + #[cfg(feature = "bench")] + #[bench] + fn bench_not_paranoiac(b: &mut Bencher) { + b.iter(|| { + generate_key("polka", 3, false) + }); + } } diff --git a/substrate/bft/Cargo.toml b/substrate/bft/Cargo.toml index 68179536b4330..52367a06711ad 100644 --- a/substrate/bft/Cargo.toml +++ b/substrate/bft/Cargo.toml @@ -9,13 +9,14 @@ substrate-codec = { path = "../codec" } substrate-primitives = { path = "../primitives" } substrate-runtime-support = { path = "../runtime-support" } substrate-runtime-primitives = { path = "../runtime/primitives" } +substrate-runtime-version = { path = "../runtime/version" } ed25519 = { path = "../ed25519" } -tokio-timer = "0.1.2" +tokio = "0.1.7" parking_lot = "0.4" -error-chain = "0.11" +error-chain = "0.12" log = "0.3" +rhododendron = "0.2" [dev-dependencies] substrate-keyring = { path = "../keyring" } substrate-executor = { path = "../executor" } -tokio-core = "0.1.12" diff --git a/substrate/bft/src/error.rs b/substrate/bft/src/error.rs index c18528a3f1e09..d8de262364965 100644 --- a/substrate/bft/src/error.rs +++ b/substrate/bft/src/error.rs @@ -15,6 +15,7 @@ // along with Substrate. If not, see . //! Error types in the BFT service. +use runtime_version::RuntimeVersion; error_chain! { errors { @@ -31,9 +32,9 @@ error_chain! { } /// Unable to schedule wakeup. - FaultyTimer { - description("Faulty timer: unable to schedule wakeup"), - display("Faulty timer: unable to schedule wakeup"), + FaultyTimer(e: ::tokio::timer::Error) { + description("Timer error"), + display("Timer error: {}", e), } /// Unable to propose a block. @@ -54,6 +55,24 @@ error_chain! { display("Message sender {:?} is not a valid authority.", a), } + /// Authoring interface does not match the runtime. + IncompatibleAuthoringRuntime(native: RuntimeVersion, on_chain: RuntimeVersion) { + description("Authoring for current runtime is not supported"), + display("Authoring for current runtime is not supported. Native ({}) cannot author for on-chain ({}).", native, on_chain), + } + + /// Authoring interface does not match the runtime. + RuntimeVersionMissing { + description("Current runtime has no version"), + display("Authoring for current runtime is not supported since it has no version."), + } + + /// Authoring interface does not match the runtime. + NativeRuntimeMissing { + description("This build has no native runtime"), + display("Authoring in current build is not supported since it has no runtime."), + } + /// Justification requirements not met. InvalidJustification { description("Invalid justification"), @@ -68,8 +87,8 @@ error_chain! { } } -impl From<::generic::InputStreamConcluded> for Error { - fn from(_: ::generic::InputStreamConcluded) -> Error { +impl From<::rhododendron::InputStreamConcluded> for Error { + fn from(_: ::rhododendron::InputStreamConcluded) -> Error { ErrorKind::IoTerminated.into() } } diff --git a/substrate/bft/src/generic/accumulator.rs b/substrate/bft/src/generic/accumulator.rs deleted file mode 100644 index 811826b7d68a4..0000000000000 --- a/substrate/bft/src/generic/accumulator.rs +++ /dev/null @@ -1,883 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate 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. - -// Substrate 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 Substrate. If not, see . - -//! Vote accumulator for each round of BFT consensus. - -use std::collections::{HashMap, HashSet}; -use std::collections::hash_map::Entry; -use std::hash::Hash; - -use generic::{Vote, LocalizedMessage, LocalizedProposal}; - -/// Justification for some state at a given round. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct UncheckedJustification { - /// The round. - pub round_number: usize, - /// The digest prepared for. - pub digest: D, - /// Signatures for the prepare messages. - pub signatures: Vec, -} - -impl UncheckedJustification { - /// Fails if there are duplicate signatures or invalid. - /// - /// Provide a closure for checking whether the signature is valid on a - /// digest. - /// - /// The closure should returns a checked justification iff the round number, digest, and signature - /// represent a valid message and the signer was authorized to issue - /// it. - /// - /// The `check_message` closure may vary based on context. - pub fn check(self, threshold: usize, mut check_message: F) - -> Result, Self> - where - F: FnMut(usize, &D, &S) -> Option, - V: Hash + Eq, - { - let checks_out = { - let mut checks_out = || { - let mut voted = HashSet::new(); - - for signature in &self.signatures { - match check_message(self.round_number, &self.digest, signature) { - None => return false, - Some(v) => { - if !voted.insert(v) { - return false; - } - } - } - } - - voted.len() >= threshold - }; - - checks_out() - }; - - if checks_out { - Ok(Justification(self)) - } else { - Err(self) - } - } -} - -/// A checked justification. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Justification(UncheckedJustification); - -impl Justification { - /// Convert this justification back to unchecked. - pub fn uncheck(self) -> UncheckedJustification { - self.0 - } -} - -impl ::std::ops::Deref for Justification { - type Target = UncheckedJustification; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -/// Type alias to represent a justification specifically for a prepare. -pub type PrepareJustification = Justification; - -/// The round's state, based on imported messages. -#[derive(PartialEq, Eq, Debug)] -pub enum State { - /// No proposal yet. - Begin, - /// Proposal received. - Proposed(Candidate), - /// Seen n - f prepares for this digest. - Prepared(PrepareJustification), - /// Seen n - f commits for a digest. - Committed(Justification), - /// Seen n - f round-advancement messages. - Advanced(Option>), -} - -#[derive(Debug, Default)] -struct VoteCounts { - prepared: usize, - committed: usize, -} - -#[derive(Debug)] -struct Proposal { - proposal: Candidate, - digest: Digest, - digest_signature: Signature, -} - -/// Misbehavior which can occur. -#[derive(Debug, Clone)] -pub enum Misbehavior { - /// Proposed out-of-turn. - ProposeOutOfTurn(usize, Digest, Signature), - /// Issued two conflicting proposals. - DoublePropose(usize, (Digest, Signature), (Digest, Signature)), - /// Issued two conflicting prepare messages. - DoublePrepare(usize, (Digest, Signature), (Digest, Signature)), - /// Issued two conflicting commit messages. - DoubleCommit(usize, (Digest, Signature), (Digest, Signature)), -} - -/// Accumulates messages for a given round of BFT consensus. -/// -/// This isn't tied to the "view" of a single authority. It -/// keeps accurate track of the state of the BFT consensus based -/// on all messages imported. -#[derive(Debug)] -pub struct Accumulator - where - Candidate: Eq + Clone, - Digest: Hash + Eq + Clone, - AuthorityId: Hash + Eq + Clone, - Signature: Eq + Clone, -{ - round_number: usize, - threshold: usize, - round_proposer: AuthorityId, - proposal: Option>, - prepares: HashMap, - commits: HashMap, - vote_counts: HashMap, - advance_round: HashSet, - state: State, -} - -impl Accumulator - where - Candidate: Eq + Clone, - Digest: Hash + Eq + Clone, - AuthorityId: Hash + Eq + Clone, - Signature: Eq + Clone, -{ - /// Create a new state accumulator. - pub fn new(round_number: usize, threshold: usize, round_proposer: AuthorityId) -> Self { - Accumulator { - round_number, - threshold, - round_proposer, - proposal: None, - prepares: HashMap::new(), - commits: HashMap::new(), - vote_counts: HashMap::new(), - advance_round: HashSet::new(), - state: State::Begin, - } - } - - /// How advance votes we have seen. - pub fn advance_votes(&self) -> usize { - self.advance_round.len() - } - - /// Get the round number. - pub fn round_number(&self) -> usize { - self.round_number.clone() - } - - pub fn proposal(&self) -> Option<&Candidate> { - self.proposal.as_ref().map(|p| &p.proposal) - } - - /// Inspect the current consensus state. - pub fn state(&self) -> &State { - &self.state - } - - /// Import a message. Importing duplicates is fine, but the signature - /// and authorization should have already been checked. - pub fn import_message( - &mut self, - message: LocalizedMessage, - ) -> Result<(), Misbehavior> { - // message from different round. - if message.round_number() != self.round_number { - return Ok(()); - } - - match message { - LocalizedMessage::Propose(proposal) => self.import_proposal(proposal), - LocalizedMessage::Vote(vote) => { - let (sender, signature) = (vote.sender, vote.signature); - match vote.vote { - Vote::Prepare(_, d) => self.import_prepare(d, sender, signature), - Vote::Commit(_, d) => self.import_commit(d, sender, signature), - Vote::AdvanceRound(_) => self.import_advance_round(sender), - } - } - } - } - - fn import_proposal( - &mut self, - proposal: LocalizedProposal, - ) -> Result<(), Misbehavior> { - let sender = proposal.sender; - - if sender != self.round_proposer { - return Err(Misbehavior::ProposeOutOfTurn( - self.round_number, - proposal.digest, - proposal.digest_signature) - ); - } - - match self.proposal { - Some(ref p) if &p.digest != &proposal.digest => { - return Err(Misbehavior::DoublePropose( - self.round_number, - { - let old = self.proposal.as_ref().expect("just checked to be Some; qed"); - (old.digest.clone(), old.digest_signature.clone()) - }, - (proposal.digest.clone(), proposal.digest_signature.clone()) - )) - } - _ => {}, - } - - debug!(target: "bft", "Importing proposal for round {}", self.round_number); - - self.proposal = Some(Proposal { - proposal: proposal.proposal.clone(), - digest: proposal.digest, - digest_signature: proposal.digest_signature, - }); - - if let State::Begin = self.state { - self.state = State::Proposed(proposal.proposal); - } - - Ok(()) - } - - fn import_prepare( - &mut self, - digest: Digest, - sender: AuthorityId, - signature: Signature, - ) -> Result<(), Misbehavior> { - // ignore any subsequent prepares by the same sender. - let threshold_prepared = match self.prepares.entry(sender.clone()) { - Entry::Vacant(vacant) => { - vacant.insert((digest.clone(), signature)); - let count = self.vote_counts.entry(digest.clone()).or_insert_with(Default::default); - count.prepared += 1; - - if count.prepared >= self.threshold { - Some(digest) - } else { - None - } - } - Entry::Occupied(occupied) => { - // if digest is different, that's misbehavior. - if occupied.get().0 != digest { - return Err(Misbehavior::DoublePrepare( - self.round_number, - occupied.get().clone(), - (digest, signature) - )); - } - - None - } - }; - - // only allow transition to prepare from begin or proposed state. - let valid_transition = match self.state { - State::Begin | State::Proposed(_) => true, - _ => false, - }; - - if let (true, Some(threshold_prepared)) = (valid_transition, threshold_prepared) { - let signatures = self.prepares - .values() - .filter(|&&(ref d, _)| d == &threshold_prepared) - .map(|&(_, ref s)| s.clone()) - .collect(); - - trace!(target: "bft", "observed threshold-prepare for round {}", self.round_number); - self.state = State::Prepared(Justification(UncheckedJustification { - round_number: self.round_number, - digest: threshold_prepared, - signatures: signatures, - })); - } - - Ok(()) - } - - fn import_commit( - &mut self, - digest: Digest, - sender: AuthorityId, - signature: Signature, - ) -> Result<(), Misbehavior> { - // ignore any subsequent commits by the same sender. - let threshold_committed = match self.commits.entry(sender.clone()) { - Entry::Vacant(vacant) => { - vacant.insert((digest.clone(), signature)); - let count = self.vote_counts.entry(digest.clone()).or_insert_with(Default::default); - count.committed += 1; - - if count.committed >= self.threshold { - Some(digest) - } else { - None - } - } - Entry::Occupied(occupied) => { - // if digest is different, that's misbehavior. - if occupied.get().0 != digest { - return Err(Misbehavior::DoubleCommit( - self.round_number, - occupied.get().clone(), - (digest, signature) - )); - } - - None - } - }; - - // transition to concluded state always valid. - // only weird case is if the prior state was "advanced", - // but technically it's the same behavior as if the order of receiving - // the last "advance round" and "commit" messages were reversed. - if let Some(threshold_committed) = threshold_committed { - let signatures = self.commits - .values() - .filter(|&&(ref d, _)| d == &threshold_committed) - .map(|&(_, ref s)| s.clone()) - .collect(); - - trace!(target: "bft", "observed threshold-commit for round {}", self.round_number); - self.state = State::Committed(Justification(UncheckedJustification { - round_number: self.round_number, - digest: threshold_committed, - signatures: signatures, - })); - } - - Ok(()) - } - - fn import_advance_round( - &mut self, - sender: AuthorityId, - ) -> Result<(), Misbehavior> { - self.advance_round.insert(sender); - - if self.advance_round.len() < self.threshold { return Ok(()) } - trace!(target: "bft", "Witnessed threshold advance-round messages for round {}", self.round_number); - - // allow transition to new round only if we haven't produced a justification - // yet. - self.state = match ::std::mem::replace(&mut self.state, State::Begin) { - State::Committed(j) => State::Committed(j), - State::Prepared(j) => State::Advanced(Some(j)), - State::Advanced(j) => State::Advanced(j), - State::Begin | State::Proposed(_) => State::Advanced(None), - }; - - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use generic::{LocalizedMessage, LocalizedProposal, LocalizedVote}; - - #[derive(Clone, PartialEq, Eq, Debug)] - pub struct Candidate(usize); - - #[derive(Hash, PartialEq, Eq, Clone, Debug)] - pub struct Digest(usize); - - #[derive(Hash, PartialEq, Eq, Debug, Clone)] - pub struct AuthorityId(usize); - - #[derive(PartialEq, Eq, Clone, Debug)] - pub struct Signature(usize, usize); - - #[test] - fn justification_checks_out() { - let mut justification = UncheckedJustification { - round_number: 2, - digest: Digest(600), - signatures: (0..10).map(|i| Signature(600, i)).collect(), - }; - - let check_message = |r, d: &Digest, s: &Signature| { - if r == 2 && d.0 == 600 && s.0 == 600 { - Some(AuthorityId(s.1)) - } else { - None - } - }; - - assert!(justification.clone().check(7, &check_message).is_ok()); - assert!(justification.clone().check(11, &check_message).is_err()); - - { - // one bad signature is enough to spoil it. - justification.signatures.push(Signature(1001, 255)); - assert!(justification.clone().check(7, &check_message).is_err()); - - justification.signatures.pop(); - } - // duplicates not allowed. - justification.signatures.extend((0..10).map(|i| Signature(600, i))); - assert!(justification.clone().check(11, &check_message).is_err()); - } - - #[test] - fn accepts_proposal_from_proposer_only() { - let mut accumulator = Accumulator::<_, Digest, _, _>::new(1, 7, AuthorityId(8)); - assert_eq!(accumulator.state(), &State::Begin); - - let res = accumulator.import_message(LocalizedMessage::Propose(LocalizedProposal { - sender: AuthorityId(5), - full_signature: Signature(999, 5), - digest_signature: Signature(999, 5), - proposal: Candidate(999), - digest: Digest(999), - round_number: 1, - })); - - assert!(res.is_err()); - - assert_eq!(accumulator.state(), &State::Begin); - - accumulator.import_message(LocalizedMessage::Propose(LocalizedProposal { - sender: AuthorityId(8), - full_signature: Signature(999, 8), - digest_signature: Signature(999, 8), - proposal: Candidate(999), - digest: Digest(999), - round_number: 1, - })).unwrap(); - - assert_eq!(accumulator.state(), &State::Proposed(Candidate(999))); - } - - #[test] - fn reaches_prepare_phase() { - let mut accumulator = Accumulator::new(1, 7, AuthorityId(8)); - assert_eq!(accumulator.state(), &State::Begin); - - accumulator.import_message(LocalizedMessage::Propose(LocalizedProposal { - sender: AuthorityId(8), - full_signature: Signature(999, 8), - digest_signature: Signature(999, 8), - round_number: 1, - proposal: Candidate(999), - digest: Digest(999), - })).unwrap(); - - assert_eq!(accumulator.state(), &State::Proposed(Candidate(999))); - - for i in 0..6 { - accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(999, i), - vote: Vote::Prepare(1, Digest(999)), - }.into()).unwrap(); - - assert_eq!(accumulator.state(), &State::Proposed(Candidate(999))); - } - - accumulator.import_message(LocalizedVote { - sender: AuthorityId(7), - signature: Signature(999, 7), - vote: Vote::Prepare(1, Digest(999)), - }.into()).unwrap(); - - match accumulator.state() { - &State::Prepared(ref j) => assert_eq!(j.digest, Digest(999)), - s => panic!("wrong state: {:?}", s), - } - } - - #[test] - fn prepare_to_commit() { - let mut accumulator = Accumulator::new(1, 7, AuthorityId(8)); - assert_eq!(accumulator.state(), &State::Begin); - - accumulator.import_message(LocalizedMessage::Propose(LocalizedProposal { - sender: AuthorityId(8), - full_signature: Signature(999, 8), - digest_signature: Signature(999, 8), - round_number: 1, - proposal: Candidate(999), - digest: Digest(999), - })).unwrap(); - - assert_eq!(accumulator.state(), &State::Proposed(Candidate(999))); - - for i in 0..6 { - accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(999, i), - vote: Vote::Prepare(1, Digest(999)), - }.into()).unwrap(); - - assert_eq!(accumulator.state(), &State::Proposed(Candidate(999))); - } - - accumulator.import_message(LocalizedVote { - sender: AuthorityId(7), - signature: Signature(999, 7), - vote: Vote::Prepare(1, Digest(999)), - }.into()).unwrap(); - - match accumulator.state() { - &State::Prepared(ref j) => assert_eq!(j.digest, Digest(999)), - s => panic!("wrong state: {:?}", s), - } - - for i in 0..6 { - accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(999, i), - vote: Vote::Commit(1, Digest(999)), - }.into()).unwrap(); - - match accumulator.state() { - &State::Prepared(_) => {}, - s => panic!("wrong state: {:?}", s), - } - } - - accumulator.import_message(LocalizedVote { - sender: AuthorityId(7), - signature: Signature(999, 7), - vote: Vote::Commit(1, Digest(999)), - }.into()).unwrap(); - - match accumulator.state() { - &State::Committed(ref j) => assert_eq!(j.digest, Digest(999)), - s => panic!("wrong state: {:?}", s), - } - } - - #[test] - fn prepare_to_advance() { - let mut accumulator = Accumulator::new(1, 7, AuthorityId(8)); - assert_eq!(accumulator.state(), &State::Begin); - - accumulator.import_message(LocalizedMessage::Propose(LocalizedProposal { - sender: AuthorityId(8), - full_signature: Signature(999, 8), - digest_signature: Signature(999, 8), - round_number: 1, - proposal: Candidate(999), - digest: Digest(999), - })).unwrap(); - - assert_eq!(accumulator.state(), &State::Proposed(Candidate(999))); - - for i in 0..7 { - accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(999, i), - vote: Vote::Prepare(1, Digest(999)), - }.into()).unwrap(); - } - - match accumulator.state() { - &State::Prepared(ref j) => assert_eq!(j.digest, Digest(999)), - s => panic!("wrong state: {:?}", s), - } - - for i in 0..6 { - accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(999, i), - vote: Vote::AdvanceRound(1), - }.into()).unwrap(); - - match accumulator.state() { - &State::Prepared(_) => {}, - s => panic!("wrong state: {:?}", s), - } - } - - accumulator.import_message(LocalizedVote { - sender: AuthorityId(7), - signature: Signature(999, 7), - vote: Vote::AdvanceRound(1), - }.into()).unwrap(); - - match accumulator.state() { - &State::Advanced(Some(_)) => {}, - s => panic!("wrong state: {:?}", s), - } - } - - #[test] - fn conclude_different_than_proposed() { - let mut accumulator = Accumulator::::new(1, 7, AuthorityId(8)); - assert_eq!(accumulator.state(), &State::Begin); - - for i in 0..7 { - accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(999, i), - vote: Vote::Prepare(1, Digest(999)), - }.into()).unwrap(); - } - - match accumulator.state() { - &State::Prepared(ref j) => assert_eq!(j.digest, Digest(999)), - s => panic!("wrong state: {:?}", s), - } - - for i in 0..7 { - accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(999, i), - vote: Vote::Commit(1, Digest(999)), - }.into()).unwrap(); - } - - match accumulator.state() { - &State::Committed(ref j) => assert_eq!(j.digest, Digest(999)), - s => panic!("wrong state: {:?}", s), - } - } - - #[test] - fn propose_after_prepared_does_not_clobber_state() { - let mut accumulator = Accumulator::::new(1, 7, AuthorityId(8)); - assert_eq!(accumulator.state(), &State::Begin); - - for i in 0..7 { - accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(999, i), - vote: Vote::Prepare(1, Digest(999)), - }.into()).unwrap(); - } - - match accumulator.state() { - &State::Prepared(ref j) => assert_eq!(j.digest, Digest(999)), - s => panic!("wrong state: {:?}", s), - } - - accumulator.import_message(LocalizedMessage::Propose(LocalizedProposal { - sender: AuthorityId(8), - full_signature: Signature(999, 8), - digest_signature: Signature(999, 8), - round_number: 1, - proposal: Candidate(999), - digest: Digest(999), - })).unwrap(); - - match accumulator.state() { - &State::Prepared(ref j) => assert_eq!(j.digest, Digest(999)), - s => panic!("wrong state: {:?}", s), - } - } - - #[test] - fn propose_after_committed_does_not_clobber_state() { - let mut accumulator = Accumulator::::new(1, 7, AuthorityId(8)); - assert_eq!(accumulator.state(), &State::Begin); - - for i in 0..7 { - accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(999, i), - vote: Vote::Commit(1, Digest(999)), - }.into()).unwrap(); - } - - match accumulator.state() { - &State::Committed(ref j) => assert_eq!(j.digest, Digest(999)), - s => panic!("wrong state: {:?}", s), - } - - accumulator.import_message(LocalizedMessage::Propose(LocalizedProposal { - sender: AuthorityId(8), - full_signature: Signature(999, 8), - digest_signature: Signature(999, 8), - round_number: 1, - proposal: Candidate(999), - digest: Digest(999), - })).unwrap(); - - match accumulator.state() { - &State::Committed(ref j) => assert_eq!(j.digest, Digest(999)), - s => panic!("wrong state: {:?}", s), - } - } - - #[test] - fn propose_after_advance_does_not_clobber_state() { - let mut accumulator = Accumulator::::new(1, 7, AuthorityId(8)); - assert_eq!(accumulator.state(), &State::Begin); - - for i in 0..7 { - accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(1, i), - vote: Vote::AdvanceRound(1), - }.into()).unwrap(); - } - - match accumulator.state() { - &State::Advanced(_) => {} - s => panic!("wrong state: {:?}", s), - } - - accumulator.import_message(LocalizedMessage::Propose(LocalizedProposal { - sender: AuthorityId(8), - full_signature: Signature(999, 8), - digest_signature: Signature(999, 8), - round_number: 1, - proposal: Candidate(999), - digest: Digest(999), - })).unwrap(); - - match accumulator.state() { - &State::Advanced(_) => {} - s => panic!("wrong state: {:?}", s), - } - } - - #[test] - fn begin_to_advance() { - let mut accumulator = Accumulator::::new(1, 7, AuthorityId(8)); - assert_eq!(accumulator.state(), &State::Begin); - - for i in 0..7 { - accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(1, i), - vote: Vote::AdvanceRound(1), - }.into()).unwrap(); - } - - match accumulator.state() { - &State::Advanced(ref j) => assert!(j.is_none()), - s => panic!("wrong state: {:?}", s), - } - } - - #[test] - fn conclude_without_prepare() { - let mut accumulator = Accumulator::::new(1, 7, AuthorityId(8)); - assert_eq!(accumulator.state(), &State::Begin); - - for i in 0..7 { - accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(999, i), - vote: Vote::Commit(1, Digest(999)), - }.into()).unwrap(); - } - - match accumulator.state() { - &State::Committed(ref j) => assert_eq!(j.digest, Digest(999)), - s => panic!("wrong state: {:?}", s), - } - } - - #[test] - fn double_prepare_is_misbehavior() { - let mut accumulator = Accumulator::::new(1, 7, AuthorityId(8)); - assert_eq!(accumulator.state(), &State::Begin); - - for i in 0..7 { - accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(999, i), - vote: Vote::Prepare(1, Digest(999)), - }.into()).unwrap(); - - let res = accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(123, i), - vote: Vote::Prepare(1, Digest(123)), - }.into()); - - assert!(res.is_err()); - - } - } - - #[test] - fn double_commit_is_misbehavior() { - let mut accumulator = Accumulator::::new(1, 7, AuthorityId(8)); - assert_eq!(accumulator.state(), &State::Begin); - - for i in 0..7 { - accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(999, i), - vote: Vote::Commit(1, Digest(999)), - }.into()).unwrap(); - - let res = accumulator.import_message(LocalizedVote { - sender: AuthorityId(i), - signature: Signature(123, i), - vote: Vote::Commit(1, Digest(123)), - }.into()); - - assert!(res.is_err()); - - } - } - - #[test] - fn double_propose_is_misbehavior() { - let mut accumulator = Accumulator::::new(1, 7, AuthorityId(8)); - assert_eq!(accumulator.state(), &State::Begin); - - accumulator.import_message(LocalizedMessage::Propose(LocalizedProposal { - sender: AuthorityId(8), - full_signature: Signature(999, 8), - digest_signature: Signature(999, 8), - round_number: 1, - proposal: Candidate(999), - digest: Digest(999), - })).unwrap(); - - let res = accumulator.import_message(LocalizedMessage::Propose(LocalizedProposal { - sender: AuthorityId(8), - full_signature: Signature(500, 8), - digest_signature: Signature(500, 8), - round_number: 1, - proposal: Candidate(500), - digest: Digest(500), - })); - - assert!(res.is_err()); - } -} diff --git a/substrate/bft/src/generic/mod.rs b/substrate/bft/src/generic/mod.rs deleted file mode 100644 index 6d4715e80612f..0000000000000 --- a/substrate/bft/src/generic/mod.rs +++ /dev/null @@ -1,842 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate 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. - -// Substrate 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 Substrate. If not, see . - -//! BFT Agreement based on a rotating proposer in different rounds. -//! Very general implementation. - -use std::collections::{HashMap, BTreeMap, VecDeque}; -use std::collections::hash_map; -use std::fmt::Debug; -use std::hash::Hash; - -use futures::{future, Future, Stream, Sink, Poll, Async, AsyncSink}; - -use self::accumulator::State; - -pub use self::accumulator::{Accumulator, Justification, PrepareJustification, UncheckedJustification, Misbehavior}; - -mod accumulator; - -#[cfg(test)] -mod tests; - -/// Votes during a round. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum Vote { - /// Prepare to vote for proposal with digest D. - Prepare(usize, D), - /// Commit to proposal with digest D.. - Commit(usize, D), - /// Propose advancement to a new round. - AdvanceRound(usize), -} - -impl Vote { - /// Extract the round number. - pub fn round_number(&self) -> usize { - match *self { - Vote::Prepare(round, _) => round, - Vote::Commit(round, _) => round, - Vote::AdvanceRound(round) => round, - } - } -} - -/// Messages over the proposal. -/// Each message carries an associated round number. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum Message { - /// A proposal itself. - Propose(usize, C), - /// A vote of some kind, localized to a round number. - Vote(Vote), -} - -impl From> for Message { - fn from(vote: Vote) -> Self { - Message::Vote(vote) - } -} - -/// A localized proposal message. Contains two signed pieces of data. -#[derive(Debug, Clone)] -pub struct LocalizedProposal { - /// The round number. - pub round_number: usize, - /// The proposal sent. - pub proposal: C, - /// The digest of the proposal. - pub digest: D, - /// The sender of the proposal - pub sender: V, - /// The signature on the message (propose, round number, digest) - pub digest_signature: S, - /// The signature on the message (propose, round number, proposal) - pub full_signature: S, -} - -/// A localized vote message, including the sender. -#[derive(Debug, Clone)] -pub struct LocalizedVote { - /// The message sent. - pub vote: Vote, - /// The sender of the message - pub sender: V, - /// The signature of the message. - pub signature: S, -} - -/// A localized message. -#[derive(Debug, Clone)] -pub enum LocalizedMessage { - /// A proposal. - Propose(LocalizedProposal), - /// A vote. - Vote(LocalizedVote), -} - -impl LocalizedMessage { - /// Extract the sender. - pub fn sender(&self) -> &V { - match *self { - LocalizedMessage::Propose(ref proposal) => &proposal.sender, - LocalizedMessage::Vote(ref vote) => &vote.sender, - } - } - - /// Extract the round number. - pub fn round_number(&self) -> usize { - match *self { - LocalizedMessage::Propose(ref proposal) => proposal.round_number, - LocalizedMessage::Vote(ref vote) => vote.vote.round_number(), - } - } -} - -impl From> for LocalizedMessage { - fn from(vote: LocalizedVote) -> Self { - LocalizedMessage::Vote(vote) - } -} - -/// Context necessary for agreement. -/// -/// Provides necessary types for protocol messages, and functions necessary for a -/// participant to evaluate and create those messages. -pub trait Context { - /// Errors which can occur from the futures in this context. - type Error: From; - /// Candidate proposed. - type Candidate: Debug + Eq + Clone; - /// Candidate digest. - type Digest: Debug + Hash + Eq + Clone; - /// Authority ID. - type AuthorityId: Debug + Hash + Eq + Clone; - /// Signature. - type Signature: Debug + Eq + Clone; - /// A future that resolves when a round timeout is concluded. - type RoundTimeout: Future; - /// A future that resolves when a proposal is ready. - type CreateProposal: Future; - /// A future that resolves when a proposal has been evaluated. - type EvaluateProposal: Future; - - /// Get the local authority ID. - fn local_id(&self) -> Self::AuthorityId; - - /// Get the best proposal. - fn proposal(&self) -> Self::CreateProposal; - - /// Get the digest of a candidate. - fn candidate_digest(&self, candidate: &Self::Candidate) -> Self::Digest; - - /// Sign a message using the local authority ID. - /// In the case of a proposal message, it should sign on the hash and - /// the bytes of the proposal. - fn sign_local(&self, message: Message) - -> LocalizedMessage; - - /// Get the proposer for a given round of consensus. - fn round_proposer(&self, round: usize) -> Self::AuthorityId; - - /// Whether the proposal is valid. - fn proposal_valid(&self, proposal: &Self::Candidate) -> Self::EvaluateProposal; - - /// Create a round timeout. The context will determine the correct timeout - /// length, and create a future that will resolve when the timeout is - /// concluded. - fn begin_round_timeout(&self, round: usize) -> Self::RoundTimeout; -} - -/// Communication that can occur between participants in consensus. -#[derive(Debug, Clone)] -pub enum Communication { - /// A consensus message (proposal or vote) - Consensus(LocalizedMessage), - /// Auxiliary communication (just proof-of-lock for now). - Auxiliary(PrepareJustification), -} - -/// Hack to get around type alias warning. -pub trait TypeResolve { - /// Communication type. - type Communication; -} - -impl TypeResolve for C { - type Communication = Communication; -} - -#[derive(Debug)] -struct Sending { - items: VecDeque, - flushing: bool, -} - -impl Sending { - fn with_capacity(n: usize) -> Self { - Sending { - items: VecDeque::with_capacity(n), - flushing: false, - } - } - - fn push(&mut self, item: T) { - self.items.push_back(item); - self.flushing = false; - } - - // process all the sends into the sink. - fn process_all>(&mut self, sink: &mut S) -> Poll<(), S::SinkError> { - while let Some(item) = self.items.pop_front() { - match sink.start_send(item) { - Err(e) => return Err(e), - Ok(AsyncSink::NotReady(item)) => { - self.items.push_front(item); - return Ok(Async::NotReady); - } - Ok(AsyncSink::Ready) => { self.flushing = true; } - } - } - - if self.flushing { - match sink.poll_complete() { - Err(e) => return Err(e), - Ok(Async::NotReady) => return Ok(Async::NotReady), - Ok(Async::Ready(())) => { self.flushing = false; } - } - } - - Ok(Async::Ready(())) - } -} - -/// Error returned when the input stream concludes. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct InputStreamConcluded; - -impl ::std::fmt::Display for InputStreamConcluded { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "{}", ::std::error::Error::description(self)) - } -} - -impl ::std::error::Error for InputStreamConcluded { - fn description(&self) -> &str { - "input stream of messages concluded prematurely" - } -} - -// get the "full BFT" threshold based on an amount of nodes and -// a maximum faulty. if nodes == 3f + 1, then threshold == 2f + 1. -fn bft_threshold(nodes: usize, max_faulty: usize) -> usize { - nodes - max_faulty -} - -/// Committed successfully. -#[derive(Debug, Clone)] -pub struct Committed { - /// The candidate committed for. This will be unknown if - /// we never witnessed the proposal of the last round. - pub candidate: Option, - /// A justification for the candidate. - pub justification: Justification, -} - -struct Locked { - justification: PrepareJustification, -} - -impl Locked { - fn digest(&self) -> &D { - &self.justification.digest - } -} - -// the state of the local node during the current state of consensus. -// -// behavior is different when locked on a proposal. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum LocalState { - Start, - Proposed, - Prepared(bool), // whether we thought it valid. - Committed, - VoteAdvance, -} - -// This structure manages a single "view" of consensus. -// -// We maintain two message accumulators: one for the round we are currently in, -// and one for a future round. -// -// We advance the round accumulators when one of two conditions is met: -// - we witness consensus of advancement in the current round. in this case we -// advance by one. -// - a higher threshold-prepare is broadcast to us. in this case we can -// advance to the round of the threshold-prepare. this is an indication -// that we have experienced severe asynchrony/clock drift with the remainder -// of the other authorities, and it is unlikely that we can assist in -// consensus meaningfully. nevertheless we make an attempt. -struct Strategy { - nodes: usize, - max_faulty: usize, - fetching_proposal: Option, - evaluating_proposal: Option, - round_timeout: future::Fuse, - local_state: LocalState, - locked: Option>, - notable_candidates: HashMap, - current_accumulator: Accumulator, - future_accumulators: BTreeMap>, - local_id: C::AuthorityId, - misbehavior: HashMap>, -} - -impl Strategy { - fn create(context: &C, nodes: usize, max_faulty: usize) -> Self { - let timeout = context.begin_round_timeout(0); - let threshold = bft_threshold(nodes, max_faulty); - - let current_accumulator = Accumulator::new( - 0, - threshold, - context.round_proposer(0), - ); - - Strategy { - nodes, - max_faulty, - current_accumulator, - future_accumulators: BTreeMap::new(), - fetching_proposal: None, - evaluating_proposal: None, - local_state: LocalState::Start, - locked: None, - notable_candidates: HashMap::new(), - round_timeout: timeout.fuse(), - local_id: context.local_id(), - misbehavior: HashMap::new(), - } - } - - fn current_round(&self) -> usize { - self.current_accumulator.round_number() - } - - fn import_message( - &mut self, - context: &C, - msg: LocalizedMessage - ) { - let round_number = msg.round_number(); - - let sender = msg.sender().clone(); - let current_round = self.current_round(); - let misbehavior = if round_number == current_round { - self.current_accumulator.import_message(msg) - } else if round_number > current_round { - let threshold = bft_threshold(self.nodes, self.max_faulty); - - let mut future_acc = self.future_accumulators.entry(round_number).or_insert_with(|| { - Accumulator::new( - round_number, - threshold, - context.round_proposer(round_number), - ) - }); - - future_acc.import_message(msg) - } else { - Ok(()) - }; - - if let Err(misbehavior) = misbehavior { - self.misbehavior.insert(sender, misbehavior); - } - } - - fn import_lock_proof( - &mut self, - context: &C, - justification: PrepareJustification, - ) { - // TODO: find a way to avoid processing of the signatures if the sender is - // not the primary or the round number is low. - if justification.round_number > self.current_round() { - // jump ahead to the prior round as this is an indication of a supermajority - // good nodes being at least on that round. - self.advance_to_round(context, justification.round_number); - } - - let lock_to_new = self.locked.as_ref() - .map_or(true, |l| l.justification.round_number < justification.round_number); - - if lock_to_new { - self.locked = Some(Locked { justification }) - } - } - - // poll the strategy: this will queue messages to be sent and advance - // rounds if necessary. - // - // only call within the context of a `Task`. - fn poll( - &mut self, - context: &C, - sending: &mut Sending<::Communication> - ) - -> Poll, C::Error> - { - let mut last_watermark = (self.current_round(), self.local_state); - - // poll until either completion or state doesn't change. - loop { - trace!(target: "bft", "Polling BFT logic. State={:?}", last_watermark); - match self.poll_once(context, sending)? { - Async::Ready(x) => return Ok(Async::Ready(x)), - Async::NotReady => { - let new_watermark = (self.current_round(), self.local_state); - - if new_watermark == last_watermark { - return Ok(Async::NotReady) - } else { - last_watermark = new_watermark; - } - } - } - } - } - - // perform one round of polling: attempt to broadcast messages and change the state. - // if the round or internal round-state changes, this should be called again. - fn poll_once( - &mut self, - context: &C, - sending: &mut Sending<::Communication> - ) - -> Poll, C::Error> - { - self.propose(context, sending)?; - self.prepare(context, sending)?; - self.commit(context, sending); - self.vote_advance(context, sending)?; - - let advance = match self.current_accumulator.state() { - &State::Advanced(ref p_just) => { - // lock to any witnessed prepare justification. - if let Some(p_just) = p_just.as_ref() { - self.locked = Some(Locked { justification: p_just.clone() }); - } - - let round_number = self.current_round(); - Some(round_number + 1) - } - &State::Committed(ref just) => { - // fetch the agreed-upon candidate: - // - we may not have received the proposal in the first place - // - there is no guarantee that the proposal we got was agreed upon - // (can happen if faulty primary) - // - look in the candidates of prior rounds just in case. - let candidate = self.current_accumulator - .proposal() - .and_then(|c| if context.candidate_digest(c) == just.digest { - Some(c.clone()) - } else { - None - }) - .or_else(|| self.notable_candidates.get(&just.digest).cloned()); - - let committed = Committed { - candidate, - justification: just.clone() - }; - - return Ok(Async::Ready(committed)) - } - _ => None, - }; - - if let Some(new_round) = advance { - self.advance_to_round(context, new_round); - } - - Ok(Async::NotReady) - } - - fn propose( - &mut self, - context: &C, - sending: &mut Sending<::Communication> - ) - -> Result<(), C::Error> - { - if let LocalState::Start = self.local_state { - let mut propose = false; - if let &State::Begin = self.current_accumulator.state() { - let round_number = self.current_round(); - let primary = context.round_proposer(round_number); - propose = self.local_id == primary; - }; - - if !propose { return Ok(()) } - - // obtain the proposal to broadcast. - let proposal = match self.locked { - Some(ref locked) => { - // TODO: it's possible but very unlikely that we don't have the - // corresponding proposal for what we are locked to. - // - // since this is an edge case on an edge case, it is fine - // to eat the round timeout for now, but it can be optimized by - // broadcasting an advance vote. - self.notable_candidates.get(locked.digest()).cloned() - } - None => { - let res = self.fetching_proposal - .get_or_insert_with(|| context.proposal()) - .poll()?; - - match res { - Async::Ready(p) => Some(p), - Async::NotReady => None, - } - } - }; - - if let Some(proposal) = proposal { - self.fetching_proposal = None; - - let message = Message::Propose( - self.current_round(), - proposal - ); - - self.import_and_send_message(message, context, sending); - - // broadcast the justification along with the proposal if we are locked. - if let Some(ref locked) = self.locked { - sending.push( - Communication::Auxiliary(locked.justification.clone()) - ); - } - - self.local_state = LocalState::Proposed; - } - } - - Ok(()) - } - - fn prepare( - &mut self, - context: &C, - sending: &mut Sending<::Communication> - ) - -> Result<(), C::Error> - { - // prepare only upon start or having proposed. - match self.local_state { - LocalState::Start | LocalState::Proposed => {}, - _ => return Ok(()) - }; - - let mut prepare_for = None; - - // we can't prepare until something was proposed. - if let &State::Proposed(ref candidate) = self.current_accumulator.state() { - let digest = context.candidate_digest(candidate); - - // vote to prepare only if we believe the candidate to be valid and - // we are not locked on some other candidate. - match self.locked { - Some(ref locked) if locked.digest() != &digest => {} - Some(_) => { - // don't check validity if we are locked. - // this is necessary to preserve the liveness property. - self.local_state = LocalState::Prepared(true); - prepare_for = Some(digest); - } - None => { - let res = self.evaluating_proposal - .get_or_insert_with(|| context.proposal_valid(candidate)) - .poll()?; - - if let Async::Ready(valid) = res { - self.evaluating_proposal = None; - self.local_state = LocalState::Prepared(valid); - - if valid { - prepare_for = Some(digest); - } - } - } - } - } - - if let Some(digest) = prepare_for { - let message = Vote::Prepare( - self.current_round(), - digest - ).into(); - - self.import_and_send_message(message, context, sending); - } - - Ok(()) - } - - fn commit( - &mut self, - context: &C, - sending: &mut Sending<::Communication> - ) { - // commit only if we haven't voted to advance or committed already - match self.local_state { - LocalState::Committed | LocalState::VoteAdvance => return, - _ => {} - } - - let mut commit_for = None; - - if let &State::Prepared(ref p_just) = self.current_accumulator.state() { - // we are now locked to this prepare justification. - let digest = p_just.digest.clone(); - self.locked = Some(Locked { justification: p_just.clone() }); - commit_for = Some(digest); - } - - if let Some(digest) = commit_for { - let message = Vote::Commit( - self.current_round(), - digest - ).into(); - - self.import_and_send_message(message, context, sending); - self.local_state = LocalState::Committed; - } - } - - fn vote_advance( - &mut self, - context: &C, - sending: &mut Sending<::Communication> - ) - -> Result<(), C::Error> - { - // we can vote for advancement under all circumstances unless we have already. - if let LocalState::VoteAdvance = self.local_state { return Ok(()) } - - // if we got f + 1 advance votes, or the timeout has fired, and we haven't - // sent an AdvanceRound message yet, do so. - let mut attempt_advance = self.current_accumulator.advance_votes() > self.max_faulty; - - // if we evaluated the proposal and it was bad, vote to advance round. - if let LocalState::Prepared(false) = self.local_state { - attempt_advance = true; - } - - // if the timeout has fired, vote to advance round. - if let Async::Ready(_) = self.round_timeout.poll()? { - attempt_advance = true; - } - - if attempt_advance { - let message = Vote::AdvanceRound( - self.current_round(), - ).into(); - - self.import_and_send_message(message, context, sending); - self.local_state = LocalState::VoteAdvance; - } - - Ok(()) - } - - fn advance_to_round(&mut self, context: &C, round: usize) { - assert!(round > self.current_round()); - trace!(target: "bft", "advancing to round {}", round); - - self.fetching_proposal = None; - self.evaluating_proposal = None; - self.round_timeout = context.begin_round_timeout(round).fuse(); - self.local_state = LocalState::Start; - - // when advancing from a round, store away the witnessed proposal. - // - // if we or other participants end up locked on that candidate, - // we will have it. - if let Some(proposal) = self.current_accumulator.proposal() { - let digest = context.candidate_digest(proposal); - self.notable_candidates.entry(digest).or_insert_with(|| proposal.clone()); - } - - // if we jump ahead more than one round, get rid of the ones in between. - for irrelevant in (self.current_round() + 1)..round { - self.future_accumulators.remove(&irrelevant); - } - - // use stored future accumulator for given round or create if it doesn't exist. - self.current_accumulator = match self.future_accumulators.remove(&round) { - Some(x) => x, - None => Accumulator::new( - round, - bft_threshold(self.nodes, self.max_faulty), - context.round_proposer(round), - ), - }; - } - - fn import_and_send_message( - &mut self, - message: Message, - context: &C, - sending: &mut Sending<::Communication> - ) { - let signed_message = context.sign_local(message); - self.import_message(context, signed_message.clone()); - sending.push(Communication::Consensus(signed_message)); - } -} - -/// Future that resolves upon BFT agreement for a candidate. -#[must_use = "futures do nothing unless polled"] -pub struct Agreement { - context: C, - input: I, - output: O, - concluded: Option>, - sending: Sending<::Communication>, - strategy: Strategy, -} - -impl Future for Agreement - where - C: Context, - I: Stream::Communication,Error=C::Error>, - O: Sink::Communication,SinkError=C::Error>, -{ - type Item = Committed; - type Error = C::Error; - - fn poll(&mut self) -> Poll { - // even if we've observed the conclusion, wait until all - // pending outgoing messages are flushed. - if let Some(just) = self.concluded.take() { - return Ok(match self.sending.process_all(&mut self.output)? { - Async::Ready(()) => Async::Ready(just), - Async::NotReady => { - self.concluded = Some(just); - Async::NotReady - } - }) - } - - // drive state machine as long as there are new messages. - let mut driving = true; - while driving { - driving = match self.input.poll()? { - Async::Ready(msg) => { - match msg.ok_or(InputStreamConcluded)? { - Communication::Consensus(message) => self.strategy.import_message(&self.context, message), - Communication::Auxiliary(lock_proof) - => self.strategy.import_lock_proof(&self.context, lock_proof), - } - - true - } - Async::NotReady => false, - }; - - // drive state machine after handling new input. - if let Async::Ready(just) = self.strategy.poll(&self.context, &mut self.sending)? { - self.concluded = Some(just); - return self.poll(); - } - } - - // make progress on flushing all pending messages. - let _ = self.sending.process_all(&mut self.output)?; - Ok(Async::NotReady) - } -} - -impl Agreement { - /// Get a reference to the underlying context. - pub fn context(&self) -> &C { - &self.context - } - - /// Drain the misbehavior vector. - pub fn drain_misbehavior(&mut self) -> hash_map::Drain> { - self.strategy.misbehavior.drain() - } -} - -/// Attempt to reach BFT agreement on a candidate. -/// -/// `nodes` is the number of nodes in the system. -/// `max_faulty` is the maximum number of faulty nodes. Should be less than -/// 1/3 of `nodes`, otherwise agreement may never be reached. -/// -/// The input stream should never logically conclude. The logic here assumes -/// that messages flushed to the output stream will eventually reach other nodes. -/// -/// Note that it is possible to witness agreement being reached without ever -/// seeing the candidate. Any candidates seen will be checked for validity. -/// -/// Although technically the agreement will always complete (given the eventual -/// delivery of messages), in practice it is possible for this future to -/// conclude without having witnessed the conclusion. -/// In general, this future should be pre-empted by the import of a justification -/// set for this block height. -pub fn agree(context: C, nodes: usize, max_faulty: usize, input: I, output: O) - -> Agreement - where - C: Context, - I: Stream::Communication,Error=C::Error>, - O: Sink::Communication,SinkError=C::Error>, -{ - let strategy = Strategy::create(&context, nodes, max_faulty); - Agreement { - context, - input, - output, - concluded: None, - sending: Sending::with_capacity(4), - strategy: strategy, - } -} diff --git a/substrate/bft/src/generic/tests.rs b/substrate/bft/src/generic/tests.rs deleted file mode 100644 index b683d751e6ed5..0000000000000 --- a/substrate/bft/src/generic/tests.rs +++ /dev/null @@ -1,504 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Substrate 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. - -// Substrate 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 Substrate. If not, see . - -//! Tests for the candidate agreement strategy. - -use super::*; - -use std::collections::BTreeSet; -use std::sync::{Arc, Mutex}; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::time::Duration; - -use futures::prelude::*; -use futures::sync::{oneshot, mpsc}; -use futures::future::FutureResult; - -use tokio_timer::{self, Timer}; - -const ROUND_DURATION: Duration = Duration::from_millis(50); - -struct Network { - endpoints: Vec>, - input: mpsc::UnboundedReceiver<(usize, T)>, -} - -impl Network { - fn new(nodes: usize) - -> (Self, Vec>, Vec>) - { - let mut inputs = Vec::with_capacity(nodes); - let mut outputs = Vec::with_capacity(nodes); - let mut endpoints = Vec::with_capacity(nodes); - - let (in_tx, in_rx) = mpsc::unbounded(); - for _ in 0..nodes { - let (out_tx, out_rx) = mpsc::unbounded(); - inputs.push(in_tx.clone()); - outputs.push(out_rx); - endpoints.push(out_tx); - } - - let network = Network { - endpoints, - input: in_rx, - }; - - (network, inputs, outputs) - } - - fn route_on_thread(self) { - ::std::thread::spawn(move || { let _ = self.wait(); }); - } -} - -impl Future for Network { - type Item = (); - type Error = (); - - fn poll(&mut self) -> Poll<(), Self::Error> { - match try_ready!(self.input.poll()) { - None => Ok(Async::Ready(())), - Some((sender, item)) => { - { - let receiving_endpoints = self.endpoints - .iter() - .enumerate() - .filter(|&(i, _)| i != sender) - .map(|(_, x)| x); - - for endpoint in receiving_endpoints { - let _ = endpoint.unbounded_send(item.clone()); - } - } - - self.poll() - } - } - } -} - -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -struct Candidate(usize); - -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -struct Digest(usize); - -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -struct AuthorityId(usize); - -#[derive(Debug, PartialEq, Eq, Clone)] -struct Signature(Message, AuthorityId); - -#[derive(Debug)] -struct Error; - -impl From for Error { - fn from(_: InputStreamConcluded) -> Error { - Error - } -} - -struct TestContext { - local_id: AuthorityId, - proposal: Mutex, - node_count: usize, - current_round: Arc, - timer: Timer, - evaluated: Mutex>, -} - -impl Context for TestContext { - type Error = Error; - type Candidate = Candidate; - type Digest = Digest; - type AuthorityId = AuthorityId; - type Signature = Signature; - type RoundTimeout = Box>; - type CreateProposal = FutureResult; - type EvaluateProposal = FutureResult; - - fn local_id(&self) -> AuthorityId { - self.local_id.clone() - } - - fn proposal(&self) -> Self::CreateProposal { - let proposal = { - let mut p = self.proposal.lock().unwrap(); - let x = *p; - *p += self.node_count; - x - }; - - Ok(Candidate(proposal)).into_future() - } - - fn candidate_digest(&self, candidate: &Candidate) -> Digest { - Digest(candidate.0) - } - - fn sign_local(&self, message: Message) - -> LocalizedMessage - { - let signature = Signature(message.clone(), self.local_id.clone()); - - match message { - Message::Propose(r, proposal) => LocalizedMessage::Propose(LocalizedProposal { - round_number: r, - digest: Digest(proposal.0), - proposal, - digest_signature: signature.clone(), - full_signature: signature, - sender: self.local_id.clone(), - }), - Message::Vote(vote) => LocalizedMessage::Vote(LocalizedVote { - vote, - signature, - sender: self.local_id.clone(), - }), - } - } - - fn round_proposer(&self, round: usize) -> AuthorityId { - AuthorityId(round % self.node_count) - } - - fn proposal_valid(&self, proposal: &Candidate) -> FutureResult { - if !self.evaluated.lock().unwrap().insert(proposal.0) { - panic!("Evaluated proposal {:?} twice", proposal.0); - } - - Ok(proposal.0 % 3 != 0).into_future() - } - - fn begin_round_timeout(&self, round: usize) -> Self::RoundTimeout { - if round < self.current_round.load(Ordering::SeqCst) { - Box::new(Ok(()).into_future()) - } else { - let mut round_duration = ROUND_DURATION; - for _ in 0..round { - round_duration *= 2; - } - - let current_round = self.current_round.clone(); - let timeout = self.timer.sleep(round_duration) - .map(move |_| { - current_round.compare_and_swap(round, round + 1, Ordering::SeqCst); - }) - .map_err(|_| Error); - - Box::new(timeout) - } - } -} - -fn timeout_in(t: Duration) -> oneshot::Receiver<()> { - let (tx, rx) = oneshot::channel(); - ::std::thread::spawn(move || { - ::std::thread::sleep(t); - let _ = tx.send(()); - }); - - rx -} - -#[test] -fn consensus_completes_with_minimum_good() { - let node_count = 10; - let max_faulty = 3; - - let timer = tokio_timer::wheel().tick_duration(ROUND_DURATION).build(); - - let (network, net_send, net_recv) = Network::new(node_count); - network.route_on_thread(); - - let nodes = net_send - .into_iter() - .zip(net_recv) - .take(node_count - max_faulty) - .enumerate() - .map(|(i, (tx, rx))| { - let ctx = TestContext { - local_id: AuthorityId(i), - proposal: Mutex::new(i), - current_round: Arc::new(AtomicUsize::new(0)), - timer: timer.clone(), - evaluated: Mutex::new(BTreeSet::new()), - node_count, - }; - - agree( - ctx, - node_count, - max_faulty, - rx.map_err(|_| Error), - tx.sink_map_err(|_| Error).with(move |t| Ok((i, t))), - ) - }) - .collect::>(); - - let timeout = timeout_in(Duration::from_millis(500)).map_err(|_| Error); - let results = ::futures::future::join_all(nodes) - .map(Some) - .select(timeout.map(|_| None)) - .wait() - .map(|(i, _)| i) - .map_err(|(e, _)| e) - .expect("to complete") - .expect("to not time out"); - - for result in &results { - assert_eq!(&result.justification.digest, &results[0].justification.digest); - } -} - -#[test] -fn consensus_completes_with_minimum_good_all_initial_proposals_bad() { - let node_count = 10; - let max_faulty = 3; - - let timer = tokio_timer::wheel().tick_duration(ROUND_DURATION).build(); - - let (network, net_send, net_recv) = Network::new(node_count); - network.route_on_thread(); - - let nodes = net_send - .into_iter() - .zip(net_recv) - .take(node_count - max_faulty) - .enumerate() - .map(|(i, (tx, rx))| { - // the first 5 proposals are going to be bad. - let proposal = if i < 5 { - i * 3 // proposals considered bad in the tests if they are % 3 - } else { - (i * 3) + 1 - }; - - let ctx = TestContext { - local_id: AuthorityId(i), - proposal: Mutex::new(proposal), - current_round: Arc::new(AtomicUsize::new(0)), - timer: timer.clone(), - evaluated: Mutex::new(BTreeSet::new()), - node_count, - }; - - agree( - ctx, - node_count, - max_faulty, - rx.map_err(|_| Error), - tx.sink_map_err(|_| Error).with(move |t| Ok((i, t))), - ) - }) - .collect::>(); - - let timeout = timeout_in(Duration::from_millis(500)).map_err(|_| Error); - let results = ::futures::future::join_all(nodes) - .map(Some) - .select(timeout.map(|_| None)) - .wait() - .map(|(i, _)| i) - .map_err(|(e, _)| e) - .expect("to complete") - .expect("to not time out"); - - for result in &results { - assert_eq!(&result.justification.digest, &results[0].justification.digest); - } -} - -#[test] -fn consensus_does_not_complete_without_enough_nodes() { - let node_count = 10; - let max_faulty = 3; - - let timer = tokio_timer::wheel().tick_duration(ROUND_DURATION).build(); - - let (network, net_send, net_recv) = Network::new(node_count); - network.route_on_thread(); - - let nodes = net_send - .into_iter() - .zip(net_recv) - .take(node_count - max_faulty - 1) - .enumerate() - .map(|(i, (tx, rx))| { - let ctx = TestContext { - local_id: AuthorityId(i), - proposal: Mutex::new(i), - current_round: Arc::new(AtomicUsize::new(0)), - timer: timer.clone(), - evaluated: Mutex::new(BTreeSet::new()), - node_count, - }; - - agree( - ctx, - node_count, - max_faulty, - rx.map_err(|_| Error), - tx.sink_map_err(|_| Error).with(move |t| Ok((i, t))), - ) - }) - .collect::>(); - - let timeout = timeout_in(Duration::from_millis(500)).map_err(|_| Error); - let result = ::futures::future::join_all(nodes) - .map(Some) - .select(timeout.map(|_| None)) - .wait() - .map(|(i, _)| i) - .map_err(|(e, _)| e) - .expect("to complete"); - - assert!(result.is_none(), "not enough online nodes"); -} - -#[test] -fn threshold_plus_one_locked_on_proposal_only_one_with_candidate() { - let node_count = 10; - let max_faulty = 3; - - let locked_proposal = Candidate(999_999_999); - let locked_digest = Digest(999_999_999); - let locked_round = 1; - let justification = UncheckedJustification { - round_number: locked_round, - digest: locked_digest.clone(), - signatures: (0..7) - .map(|i| Signature(Message::Vote(Vote::Prepare(locked_round, locked_digest.clone())), AuthorityId(i))) - .collect() - }.check(7, |_, _, s| Some(s.1.clone())).unwrap(); - - let timer = tokio_timer::wheel().tick_duration(ROUND_DURATION).build(); - - let (network, net_send, net_recv) = Network::new(node_count); - network.route_on_thread(); - - let nodes = net_send - .into_iter() - .zip(net_recv) - .enumerate() - .map(|(i, (tx, rx))| { - let ctx = TestContext { - local_id: AuthorityId(i), - proposal: Mutex::new(i), - current_round: Arc::new(AtomicUsize::new(locked_round + 1)), - timer: timer.clone(), - evaluated: Mutex::new(BTreeSet::new()), - node_count, - }; - let mut agreement = agree( - ctx, - node_count, - max_faulty, - rx.map_err(|_| Error), - tx.sink_map_err(|_| Error).with(move |t| Ok((i, t))), - ); - - agreement.strategy.advance_to_round( - &agreement.context, - locked_round + 1 - ); - - if i <= max_faulty { - agreement.strategy.locked = Some(Locked { - justification: justification.clone(), - }) - } - - if i == max_faulty { - agreement.strategy.notable_candidates.insert( - locked_digest.clone(), - locked_proposal.clone(), - ); - } - - agreement - }) - .collect::>(); - - let timeout = timeout_in(Duration::from_millis(1000)).map_err(|_| Error); - let results = ::futures::future::join_all(nodes) - .map(Some) - .select(timeout.map(|_| None)) - .wait() - .map(|(i, _)| i) - .map_err(|(e, _)| e) - .expect("to complete") - .expect("to not time out"); - - for result in &results { - assert_eq!(&result.justification.digest, &locked_digest); - } -} - -#[test] -fn consensus_completes_even_when_nodes_start_with_a_delay() { - let node_count = 10; - let max_faulty = 3; - let base_sleep = Duration::from_millis(75); - - let timer = tokio_timer::wheel().tick_duration(ROUND_DURATION).build(); - - let (network, net_send, net_recv) = Network::new(node_count); - network.route_on_thread(); - - let nodes = net_send - .into_iter() - .zip(net_recv) - .take(node_count - max_faulty) - .enumerate() - .map(|(i, (tx, rx))| { - let ctx = TestContext { - local_id: AuthorityId(i), - proposal: Mutex::new(i), - current_round: Arc::new(AtomicUsize::new(0)), - timer: timer.clone(), - evaluated: Mutex::new(BTreeSet::new()), - node_count, - }; - - let sleep_duration = base_sleep * i as u32; - - timer.sleep(sleep_duration).map_err(|_| Error).and_then(move |_| { - agree( - ctx, - node_count, - max_faulty, - rx.map_err(|_| Error), - tx.sink_map_err(|_| Error).with(move |t| Ok((i, t))), - ) - }) - }) - .collect::>(); - - let timeout = timeout_in(Duration::from_millis(750)).map_err(|_| Error); - let results = ::futures::future::join_all(nodes) - .map(Some) - .select(timeout.map(|_| None)) - .wait() - .map(|(i, _)| i) - .map_err(|(e, _)| e) - .expect("to complete") - .expect("to not time out"); - - for result in &results { - assert_eq!(&result.justification.digest, &results[0].justification.digest); - } -} diff --git a/substrate/bft/src/lib.rs b/substrate/bft/src/lib.rs index 313a0e731cb04..fcdc36d480315 100644 --- a/substrate/bft/src/lib.rs +++ b/substrate/bft/src/lib.rs @@ -15,17 +15,34 @@ // along with Substrate. If not, see . //! BFT Agreement based on a rotating proposer in different rounds. +//! +//! Where this crate refers to input stream, should never logically conclude. +//! The logic in this crate assumes that messages flushed to the output stream +//! will eventually reach other nodes and that our own messages are not included +//! in the input stream. +//! +//! Note that it is possible to witness agreement being reached without ever +//! seeing the candidate. Any candidates seen will be checked for validity. +//! +//! Although technically the agreement will always complete (given the eventual +//! delivery of messages), in practice it is possible for this future to +//! conclude without having witnessed the conclusion. +//! In general, this future should be pre-empted by the import of a justification +//! set for this block height. + +#![recursion_limit="128"] pub mod error; -pub mod generic; extern crate substrate_codec as codec; extern crate substrate_primitives as primitives; extern crate substrate_runtime_support as runtime_support; extern crate substrate_runtime_primitives as runtime_primitives; +extern crate substrate_runtime_version as runtime_version; extern crate ed25519; -extern crate tokio_timer; +extern crate tokio; extern crate parking_lot; +extern crate rhododendron; #[macro_use] extern crate log; @@ -40,7 +57,7 @@ use std::mem; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; -use codec::Slicable; +use codec::Encode; use ed25519::LocalizedSignature; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{Block, Header}; @@ -49,18 +66,18 @@ use primitives::AuthorityId; use futures::{task, Async, Stream, Sink, Future, IntoFuture}; use futures::sync::oneshot; -use tokio_timer::Timer; +use tokio::timer::Delay; use parking_lot::Mutex; -pub use generic::InputStreamConcluded; +pub use rhododendron::InputStreamConcluded; pub use error::{Error, ErrorKind}; /// Messages over the proposal. /// Each message carries an associated round number. -pub type Message = generic::Message::Hash>; +pub type Message = rhododendron::Message::Hash>; /// Localized message type. -pub type LocalizedMessage = generic::LocalizedMessage< +pub type LocalizedMessage = rhododendron::LocalizedMessage< B, ::Hash, AuthorityId, @@ -68,56 +85,79 @@ pub type LocalizedMessage = generic::LocalizedMessage< >; /// Justification of some hash. -pub type Justification = generic::Justification; +pub type Justification = rhododendron::Justification; /// Justification of a prepare message. -pub type PrepareJustification = generic::PrepareJustification; +pub type PrepareJustification = rhododendron::PrepareJustification; /// Unchecked justification. -pub type UncheckedJustification = generic::UncheckedJustification; +pub struct UncheckedJustification(rhododendron::UncheckedJustification); + +impl UncheckedJustification { + /// Create a new, unchecked justification. + pub fn new(digest: H, signatures: Vec, round_number: usize) -> Self { + UncheckedJustification(rhododendron::UncheckedJustification { + digest, + signatures, + round_number, + }) + } +} + +impl From> for UncheckedJustification { + fn from(inner: rhododendron::UncheckedJustification) -> Self { + UncheckedJustification(inner) + } +} impl From> for UncheckedJustification { fn from(just: PrimitiveJustification) -> Self { - UncheckedJustification { + UncheckedJustification(rhododendron::UncheckedJustification { round_number: just.round_number as usize, digest: just.hash, signatures: just.signatures.into_iter().map(|(from, sig)| LocalizedSignature { - signer: ed25519::Public(from), + signer: from.into(), signature: sig, }).collect(), - } + }) } } impl Into> for UncheckedJustification { fn into(self) -> PrimitiveJustification { PrimitiveJustification { - round_number: self.round_number as u32, - hash: self.digest, - signatures: self.signatures.into_iter().map(|s| (s.signer.into(), s.signature)).collect(), + round_number: self.0.round_number as u32, + hash: self.0.digest, + signatures: self.0.signatures.into_iter().map(|s| (s.signer.into(), s.signature)).collect(), } } } /// Result of a committed round of BFT -pub type Committed = generic::Committed::Hash, LocalizedSignature>; +pub type Committed = rhododendron::Committed::Hash, LocalizedSignature>; /// Communication between BFT participants. -pub type Communication = generic::Communication::Hash, AuthorityId, LocalizedSignature>; +pub type Communication = rhododendron::Communication::Hash, AuthorityId, LocalizedSignature>; /// Misbehavior observed from BFT participants. -pub type Misbehavior = generic::Misbehavior; +pub type Misbehavior = rhododendron::Misbehavior; -/// Proposer factory. Can be used to create a proposer instance. -pub trait ProposerFactory { +/// Environment producer for a BFT instance. Creates proposer instance and communication streams. +pub trait Environment { /// The proposer type this creates. type Proposer: Proposer; + /// The input stream type. + type Input: Stream, Error=>::Error>; + /// The output stream type. + type Output: Sink, SinkError=>::Error>; /// Error which can occur upon creation. type Error: From; /// Initialize the proposal logic on top of a specific header. + /// Produces the proposer and message streams for this instance of BFT agreement. // TODO: provide state context explicitly? - fn init(&self, parent_header: &B::Header, authorities: &[AuthorityId], sign_with: Arc) -> Result; + fn init(&self, parent_header: &B::Header, authorities: &[AuthorityId], sign_with: Arc) + -> Result<(Self::Proposer, Self::Input, Self::Output), Self::Error>; } /// Logic for a proposer. @@ -149,7 +189,7 @@ pub trait Proposer { /// Block import trait. pub trait BlockImport { /// Import a block alongside its corresponding justification. - fn import_block(&self, block: B, justification: Justification); + fn import_block(&self, block: B, justification: Justification, authorities: &[AuthorityId]); } /// Trait for getting the authorities at a given block. @@ -163,12 +203,11 @@ struct BftInstance { key: Arc, authorities: Vec, parent_hash: B::Hash, - timer: Timer, round_timeout_multiplier: u64, proposer: P, } -impl> generic::Context for BftInstance +impl> rhododendron::Context for BftInstance where B: Clone + Eq, B::Hash: ::std::hash::Hash, @@ -178,12 +217,12 @@ impl> generic::Context for BftInstance type Digest = B::Hash; type Signature = LocalizedSignature; type Candidate = B; - type RoundTimeout = Box + Send>; + type RoundTimeout = Box>; type CreateProposal = ::Future; type EvaluateProposal = ::Future; fn local_id(&self) -> AuthorityId { - self.key.public().0 + self.key.public().into() } fn proposal(&self) -> Self::CreateProposal { @@ -207,16 +246,18 @@ impl> generic::Context for BftInstance } fn begin_round_timeout(&self, round: usize) -> Self::RoundTimeout { - use std::time::Duration; + use std::time::{Instant, Duration}; let round = ::std::cmp::min(63, round) as u32; let timeout = 1u64.checked_shl(round) .unwrap_or_else(u64::max_value) .saturating_mul(self.round_timeout_multiplier); - Box::new(self.timer.sleep(Duration::from_secs(timeout)) - .map_err(|_| Error::from(ErrorKind::FaultyTimer)) - .map_err(Into::into)) + let fut = Delay::new(Instant::now() + Duration::from_secs(timeout)) + .map_err(|e| Error::from(ErrorKind::FaultyTimer(e))) + .map_err(Into::into); + + Box::new(fut) } } @@ -229,7 +270,7 @@ pub struct BftFuture where InStream: Stream, Error=P::Error>, OutSink: Sink, SinkError=P::Error>, { - inner: generic::Agreement, InStream, OutSink>, + inner: rhododendron::Agreement, InStream, OutSink>, cancel: Arc, send_task: Option>, import: Arc, @@ -258,10 +299,8 @@ impl Future for BftFuture Future for BftFuture { client: Arc, live_agreement: Mutex>, - timer: Timer, round_timeout_multiplier: u64, key: Arc, // TODO: key changing over time. factory: P, @@ -324,8 +365,7 @@ pub struct BftService { impl BftService where B: Block + Clone + Eq, - B::Hash: ::std::hash::Hash, - P: ProposerFactory, + P: Environment, >::Error: ::std::fmt::Display, I: BlockImport + Authorities, { @@ -335,7 +375,6 @@ impl BftService BftService { client: client, live_agreement: Mutex::new(None), - timer: Timer::default(), round_timeout_multiplier: 4, key: key, // TODO: key changing over time. factory: factory, @@ -345,7 +384,7 @@ impl BftService /// Get the local Authority ID. pub fn local_id(&self) -> AuthorityId { // TODO: based on a header and some keystore. - self.key.public().0 + self.key.public().into() } /// Signal that a valid block with the given header has been imported. @@ -353,10 +392,16 @@ impl BftService /// If the local signing key is an authority, this will begin the consensus process to build a /// block on top of it. If the executor fails to run the future, an error will be returned. /// Returns `None` if the agreement on the block with given parent is already in progress. - pub fn build_upon(&self, header: &B::Header, input: InStream, output: OutSink) - -> Result>::Proposer, I, InStream, OutSink>>, P::Error> where - InStream: Stream, Error=<

>::Proposer as Proposer>::Error>, - OutSink: Sink, SinkError=<

>::Proposer as Proposer>::Error>, + pub fn build_upon(&self, header: &B::Header) + -> Result>::Proposer, + I, +

>::Input, +

>::Output, + >>, P::Error> + where { let hash = header.hash(); if self.live_agreement.lock().as_ref().map_or(false, |&(ref h, _)| h == &hash) { @@ -377,18 +422,17 @@ impl BftService Err(From::from(ErrorKind::InvalidAuthority(local_id)))?; } - let proposer = self.factory.init(header, &authorities, self.key.clone())?; + let (proposer, input, output) = self.factory.init(header, &authorities, self.key.clone())?; let bft_instance = BftInstance { proposer, parent_hash: hash.clone(), round_timeout_multiplier: self.round_timeout_multiplier, - timer: self.timer.clone(), key: self.key.clone(), authorities: authorities, }; - let agreement = generic::agree( + let agreement = rhododendron::agree( bft_instance, n, max_faulty, @@ -444,8 +488,8 @@ fn check_justification_signed_message(authorities: &[AuthorityId], message: & -> Result, UncheckedJustification> { // TODO: return additional error information. - just.check(authorities.len() - max_faulty_of(authorities.len()), |_, _, sig| { - let auth_id = sig.signer.0; + just.0.check(authorities.len() - max_faulty_of(authorities.len()), |_, _, sig| { + let auth_id = sig.signer.clone().into(); if !authorities.contains(&auth_id) { return None } if ed25519::verify_strong(&sig.signature, message, &sig.signer) { @@ -453,7 +497,7 @@ fn check_justification_signed_message(authorities: &[AuthorityId], message: & } else { None } - }) + }).map_err(UncheckedJustification) } /// Check a full justification for a header hash. @@ -463,9 +507,9 @@ fn check_justification_signed_message(authorities: &[AuthorityId], message: & pub fn check_justification(authorities: &[AuthorityId], parent: B::Hash, just: UncheckedJustification) -> Result, UncheckedJustification> { - let message = Slicable::encode(&PrimitiveMessage:: { + let message = Encode::encode(&PrimitiveMessage:: { parent, - action: PrimitiveAction::Commit(just.round_number as u32, just.digest.clone()), + action: PrimitiveAction::Commit(just.0.round_number as u32, just.0.digest.clone()), }); check_justification_signed_message(authorities, &message[..], just) @@ -478,9 +522,9 @@ pub fn check_justification(authorities: &[AuthorityId], parent: B::Has pub fn check_prepare_justification(authorities: &[AuthorityId], parent: B::Hash, just: UncheckedJustification) -> Result, UncheckedJustification> { - let message = Slicable::encode(&PrimitiveMessage:: { + let message = Encode::encode(&PrimitiveMessage:: { parent, - action: PrimitiveAction::Prepare(just.round_number as u32, just.digest.clone()), + action: PrimitiveAction::Prepare(just.0.round_number as u32, just.0.digest.clone()), }); check_justification_signed_message(authorities, &message[..], just) @@ -491,7 +535,7 @@ pub fn check_prepare_justification(authorities: &[AuthorityId], parent pub fn check_proposal( authorities: &[AuthorityId], parent_hash: &B::Hash, - propose: &::generic::LocalizedProposal) + propose: &::rhododendron::LocalizedProposal) -> Result<(), Error> { if !authorities.contains(&propose.sender) { @@ -509,7 +553,7 @@ pub fn check_proposal( pub fn check_vote( authorities: &[AuthorityId], parent_hash: &B::Hash, - vote: &::generic::LocalizedVote) + vote: &::rhododendron::LocalizedVote) -> Result<(), Error> { if !authorities.contains(&vote.sender) { @@ -517,9 +561,9 @@ pub fn check_vote( } let action = match vote.vote { - ::generic::Vote::Prepare(r, ref h) => PrimitiveAction::Prepare(r as u32, h.clone()), - ::generic::Vote::Commit(r, ref h) => PrimitiveAction::Commit(r as u32, h.clone()), - ::generic::Vote::AdvanceRound(r) => PrimitiveAction::AdvanceRound(r as u32), + ::rhododendron::Vote::Prepare(r, ref h) => PrimitiveAction::Prepare(r as u32, h.clone()), + ::rhododendron::Vote::Commit(r, ref h) => PrimitiveAction::Commit(r as u32, h.clone()), + ::rhododendron::Vote::AdvanceRound(r) => PrimitiveAction::AdvanceRound(r as u32), }; check_action::(action, parent_hash, &vote.signature) } @@ -530,7 +574,7 @@ fn check_action(action: PrimitiveAction, parent_hash: &B:: action, }; - let message = Slicable::encode(&primitive); + let message = Encode::encode(&primitive); if ed25519::verify_strong(&sig.signature, &message, &sig.signer) { Ok(()) } else { @@ -548,7 +592,7 @@ pub fn sign_message(message: Message, key: &ed25519::Pair, action, }; - let to_sign = Slicable::encode(&primitive); + let to_sign = Encode::encode(&primitive); LocalizedSignature { signer: signer.clone(), signature: key.sign(&to_sign), @@ -556,30 +600,30 @@ pub fn sign_message(message: Message, key: &ed25519::Pair, }; match message { - ::generic::Message::Propose(r, proposal) => { + ::rhododendron::Message::Propose(r, proposal) => { let header_hash = proposal.hash(); let action_header = PrimitiveAction::ProposeHeader(r as u32, header_hash.clone()); let action_propose = PrimitiveAction::Propose(r as u32, proposal.clone()); - ::generic::LocalizedMessage::Propose(::generic::LocalizedProposal { + ::rhododendron::LocalizedMessage::Propose(::rhododendron::LocalizedProposal { round_number: r, proposal, digest: header_hash, - sender: signer.0, + sender: signer.clone().into(), digest_signature: sign_action(action_header), full_signature: sign_action(action_propose), }) } - ::generic::Message::Vote(vote) => { + ::rhododendron::Message::Vote(vote) => { let action = match vote { - ::generic::Vote::Prepare(r, ref h) => PrimitiveAction::Prepare(r as u32, h.clone()), - ::generic::Vote::Commit(r, ref h) => PrimitiveAction::Commit(r as u32, h.clone()), - ::generic::Vote::AdvanceRound(r) => PrimitiveAction::AdvanceRound(r as u32), + ::rhododendron::Vote::Prepare(r, ref h) => PrimitiveAction::Prepare(r as u32, h.clone()), + ::rhododendron::Vote::Commit(r, ref h) => PrimitiveAction::Commit(r as u32, h.clone()), + ::rhododendron::Vote::AdvanceRound(r) => PrimitiveAction::AdvanceRound(r as u32), }; - ::generic::LocalizedMessage::Vote(::generic::LocalizedVote { + ::rhododendron::LocalizedMessage::Vote(::rhododendron::LocalizedVote { vote: vote, - sender: signer.0, + sender: signer.clone().into(), signature: sign_action(action), }) } @@ -592,13 +636,11 @@ mod tests { use std::collections::HashSet; use runtime_primitives::testing::{Block as GenericTestBlock, Header as TestHeader}; use primitives::H256; - use self::tokio_core::reactor::{Core}; use self::keyring::Keyring; use futures::stream; - use futures::future::Executor; + use tokio::executor::current_thread; extern crate substrate_keyring as keyring; - extern crate tokio_core; type TestBlock = GenericTestBlock<()>; @@ -608,7 +650,7 @@ mod tests { } impl BlockImport for FakeClient { - fn import_block(&self, block: TestBlock, _justification: Justification) { + fn import_block(&self, block: TestBlock, _justification: Justification, _authorities: &[AuthorityId]) { assert!(self.imported_heights.lock().insert(block.header.number)) } } @@ -638,12 +680,16 @@ mod tests { struct DummyFactory; struct DummyProposer(u64); - impl ProposerFactory for DummyFactory { + impl Environment for DummyFactory { type Proposer = DummyProposer; + type Input = stream::Empty, Error>; + type Output = Output; type Error = Error; - fn init(&self, parent_header: &TestHeader, _authorities: &[AuthorityId], _sign_with: Arc) -> Result { - Ok(DummyProposer(parent_header.number + 1)) + fn init(&self, parent_header: &TestHeader, _authorities: &[AuthorityId], _sign_with: Arc) + -> Result<(DummyProposer, Self::Input, Self::Output), Error> + { + Ok((DummyProposer(parent_header.number + 1), stream::empty(), Output(::std::marker::PhantomData))) } } @@ -677,16 +723,15 @@ mod tests { BftService { client: Arc::new(client), live_agreement: Mutex::new(None), - timer: Timer::default(), round_timeout_multiplier: 4, key: Arc::new(Keyring::One.into()), factory: DummyFactory } } - fn sign_vote(vote: ::generic::Vote, key: &ed25519::Pair, parent_hash: H256) -> LocalizedSignature { + fn sign_vote(vote: ::rhododendron::Vote, key: &ed25519::Pair, parent_hash: H256) -> LocalizedSignature { match sign_message::(vote.into(), key, parent_hash) { - ::generic::LocalizedMessage::Vote(vote) => vote.signature, + ::rhododendron::LocalizedMessage::Vote(vote) => vote.signature, _ => panic!("signing vote leads to signed vote"), } } @@ -705,16 +750,14 @@ mod tests { fn future_gets_preempted() { let client = FakeClient { authorities: vec![ - Keyring::One.to_raw_public(), - Keyring::Two.to_raw_public(), - Keyring::Alice.to_raw_public(), - Keyring::Eve.to_raw_public(), + Keyring::One.to_raw_public().into(), + Keyring::Two.to_raw_public().into(), + Keyring::Alice.to_raw_public().into(), + Keyring::Eve.to_raw_public().into(), ], imported_heights: Mutex::new(HashSet::new()), }; - let mut core = Core::new().unwrap(); - let service = make_service(client); let first = from_block_number(2); @@ -724,19 +767,21 @@ mod tests { second.parent_hash = first_hash; let second_hash = second.hash(); - let bft = service.build_upon(&first, stream::empty(), Output(Default::default())).unwrap(); + let bft = service.build_upon(&first).unwrap(); assert!(service.live_agreement.lock().as_ref().unwrap().0 == first_hash); + let mut core = current_thread::CurrentThread::new(); + // turn the core so the future gets polled and sends its task to the // service. otherwise it deadlocks. - core.handle().execute(bft.unwrap()).unwrap(); - core.turn(Some(::std::time::Duration::from_millis(100))); - let bft = service.build_upon(&second, stream::empty(), Output(Default::default())).unwrap(); + core.spawn(bft.unwrap()); + core.run_timeout(::std::time::Duration::from_millis(100)).unwrap(); + let bft = service.build_upon(&second).unwrap(); assert!(service.live_agreement.lock().as_ref().unwrap().0 != first_hash); assert!(service.live_agreement.lock().as_ref().unwrap().0 == second_hash); - core.handle().execute(bft.unwrap()).unwrap(); - core.turn(Some(::std::time::Duration::from_millis(100))); + core.spawn(bft.unwrap()); + core.run_timeout(::std::time::Duration::from_millis(100)).unwrap(); } #[test] @@ -755,10 +800,10 @@ mod tests { let hash = [0xff; 32].into(); let authorities = vec![ - Keyring::One.to_raw_public(), - Keyring::Two.to_raw_public(), - Keyring::Alice.to_raw_public(), - Keyring::Eve.to_raw_public(), + Keyring::One.to_raw_public().into(), + Keyring::Two.to_raw_public().into(), + Keyring::Alice.to_raw_public().into(), + Keyring::Eve.to_raw_public().into(), ]; let authorities_keys = vec![ @@ -768,45 +813,45 @@ mod tests { Keyring::Eve.into(), ]; - let unchecked = UncheckedJustification { + let unchecked = UncheckedJustification(rhododendron::UncheckedJustification { digest: hash, round_number: 1, signatures: authorities_keys.iter().take(3).map(|key| { - sign_vote(generic::Vote::Commit(1, hash).into(), key, parent_hash) + sign_vote(rhododendron::Vote::Commit(1, hash).into(), key, parent_hash) }).collect(), - }; + }); assert!(check_justification::(&authorities, parent_hash, unchecked).is_ok()); - let unchecked = UncheckedJustification { + let unchecked = UncheckedJustification(rhododendron::UncheckedJustification { digest: hash, round_number: 0, // wrong round number (vs. the signatures) signatures: authorities_keys.iter().take(3).map(|key| { - sign_vote(generic::Vote::Commit(1, hash).into(), key, parent_hash) + sign_vote(rhododendron::Vote::Commit(1, hash).into(), key, parent_hash) }).collect(), - }; + }); assert!(check_justification::(&authorities, parent_hash, unchecked).is_err()); // not enough signatures. - let unchecked = UncheckedJustification { + let unchecked = UncheckedJustification(rhododendron::UncheckedJustification { digest: hash, round_number: 1, signatures: authorities_keys.iter().take(2).map(|key| { - sign_vote(generic::Vote::Commit(1, hash).into(), key, parent_hash) + sign_vote(rhododendron::Vote::Commit(1, hash).into(), key, parent_hash) }).collect(), - }; + }); assert!(check_justification::(&authorities, parent_hash, unchecked).is_err()); // wrong hash. - let unchecked = UncheckedJustification { + let unchecked = UncheckedJustification(rhododendron::UncheckedJustification { digest: [0xfe; 32].into(), round_number: 1, signatures: authorities_keys.iter().take(3).map(|key| { - sign_vote(generic::Vote::Commit(1, hash).into(), key, parent_hash) + sign_vote(rhododendron::Vote::Commit(1, hash).into(), key, parent_hash) }).collect(), - }; + }); assert!(check_justification::(&authorities, parent_hash, unchecked).is_err()); } @@ -816,8 +861,8 @@ mod tests { let parent_hash = Default::default(); let authorities = vec![ - Keyring::Alice.to_raw_public(), - Keyring::Eve.to_raw_public(), + Keyring::Alice.to_raw_public().into(), + Keyring::Eve.to_raw_public().into(), ]; let block = TestBlock { @@ -825,8 +870,8 @@ mod tests { extrinsics: Default::default() }; - let proposal = sign_message(::generic::Message::Propose(1, block.clone()), &Keyring::Alice.pair(), parent_hash);; - if let ::generic::LocalizedMessage::Propose(proposal) = proposal { + let proposal = sign_message(::rhododendron::Message::Propose(1, block.clone()), &Keyring::Alice.pair(), parent_hash);; + if let ::rhododendron::LocalizedMessage::Propose(proposal) = proposal { assert!(check_proposal(&authorities, &parent_hash, &proposal).is_ok()); let mut invalid_round = proposal.clone(); invalid_round.round_number = 0; @@ -839,8 +884,8 @@ mod tests { } // Not an authority - let proposal = sign_message::(::generic::Message::Propose(1, block), &Keyring::Bob.pair(), parent_hash);; - if let ::generic::LocalizedMessage::Propose(proposal) = proposal { + let proposal = sign_message::(::rhododendron::Message::Propose(1, block), &Keyring::Bob.pair(), parent_hash);; + if let ::rhododendron::LocalizedMessage::Propose(proposal) = proposal { assert!(check_proposal(&authorities, &parent_hash, &proposal).is_err()); } else { assert!(false); @@ -853,12 +898,12 @@ mod tests { let hash: H256 = [0xff; 32].into(); let authorities = vec![ - Keyring::Alice.to_raw_public(), - Keyring::Eve.to_raw_public(), + Keyring::Alice.to_raw_public().into(), + Keyring::Eve.to_raw_public().into(), ]; - let vote = sign_message::(::generic::Message::Vote(::generic::Vote::Prepare(1, hash)), &Keyring::Alice.pair(), parent_hash);; - if let ::generic::LocalizedMessage::Vote(vote) = vote { + let vote = sign_message::(::rhododendron::Message::Vote(::rhododendron::Vote::Prepare(1, hash)), &Keyring::Alice.pair(), parent_hash);; + if let ::rhododendron::LocalizedMessage::Vote(vote) = vote { assert!(check_vote::(&authorities, &parent_hash, &vote).is_ok()); let mut invalid_sender = vote.clone(); invalid_sender.signature.signer = Keyring::Eve.into(); @@ -868,8 +913,8 @@ mod tests { } // Not an authority - let vote = sign_message::(::generic::Message::Vote(::generic::Vote::Prepare(1, hash)), &Keyring::Bob.pair(), parent_hash);; - if let ::generic::LocalizedMessage::Vote(vote) = vote { + let vote = sign_message::(::rhododendron::Message::Vote(::rhododendron::Vote::Prepare(1, hash)), &Keyring::Bob.pair(), parent_hash);; + if let ::rhododendron::LocalizedMessage::Vote(vote) = vote { assert!(check_vote::(&authorities, &parent_hash, &vote).is_err()); } else { assert!(false); diff --git a/substrate/cli/Cargo.toml b/substrate/cli/Cargo.toml new file mode 100644 index 0000000000000..3d240a3be615c --- /dev/null +++ b/substrate/cli/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "substrate-cli" +version = "0.3.0" +authors = ["Parity Technologies "] +description = "Substrate CLI interface." +build = "build.rs" + +[dependencies] +clap = { version = "~2.32", features = ["yaml"] } +backtrace = "0.3" +env_logger = "0.4" +error-chain = "0.12" +log = "0.3" +atty = "0.2" +regex = "1" +time = "0.1" +slog = "^2" +ansi_term = "0.10" +lazy_static = "1.0" +app_dirs = "1.2" +tokio = "0.1.7" +futures = "0.1.17" +fdlimit = "0.1" +exit-future = "0.1" +substrate-client = { path = "../../substrate/client" } +substrate-extrinsic-pool = { path = "../../substrate/extrinsic-pool" } +substrate-network = { path = "../../substrate/network" } +substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" } +substrate-service = { path = "../../substrate/service" } +substrate-telemetry = { path = "../../substrate/telemetry" } +names = "0.11.0" + +[build-dependencies] +clap = "~2.32" diff --git a/substrate/cli/README.adoc b/substrate/cli/README.adoc new file mode 100644 index 0000000000000..1ad1d01eb1330 --- /dev/null +++ b/substrate/cli/README.adoc @@ -0,0 +1,11 @@ + += Substrate CLI + +== Summary + +[source, toml] +---- +include::Cargo.toml[lines=2..5] +---- + +include::doc/shell-completion.adoc[] diff --git a/substrate/cli/build.rs b/substrate/cli/build.rs new file mode 100644 index 0000000000000..645e98d5e8a9c --- /dev/null +++ b/substrate/cli/build.rs @@ -0,0 +1,59 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +#[macro_use] +extern crate clap; + +use std::fs; +use std::env; +use clap::Shell; +use std::path::Path; + +fn main() { + build_shell_completion(); +} + +/// Build shell completion scripts for all known shells +/// Full list in https://github.com/kbknapp/clap-rs/blob/e9d0562a1dc5dfe731ed7c767e6cee0af08f0cf9/src/app/parser.rs#L123 +fn build_shell_completion() { + let shells = [Shell::Bash, Shell::Fish, Shell::Zsh, Shell::Elvish, Shell::PowerShell]; + for shell in shells.iter() { + build_completion(shell); + } +} + +/// Build the shell auto-completion for a given Shell +fn build_completion(shell: &Shell) { + let yml = load_yaml!("src/cli.yml"); + + let outdir = match env::var_os("OUT_DIR") { + None => return, + Some(dir) => dir, + }; + let path = Path::new(&outdir) + .parent().unwrap() + .parent().unwrap() + .parent().unwrap() + .join("completion-scripts"); + + fs::create_dir(&path).ok(); + + let mut app = clap::App::from_yaml(&yml); + app.gen_completions( + "polkadot", + *shell, + &path); +} diff --git a/substrate/cli/doc/shell-completion.adoc b/substrate/cli/doc/shell-completion.adoc new file mode 100644 index 0000000000000..8afbd37adb9f4 --- /dev/null +++ b/substrate/cli/doc/shell-completion.adoc @@ -0,0 +1,41 @@ + +== Shell completion + +The Substrate cli command supports shell auto-completion. For this to work, you will need to run the completion script matching you build and system. + +Assuming you built a release version using `cargo build --release` and use `bash` run the following: + +[source, shell] +source target/release/completion-scripts/substrate.bash + +You can find completion scripts for: +- bash +- fish +- zsh +- elvish +- powershell + +To make this change persistent, you can proceed as follow: + +.First install + +[source, shell] +---- +COMPL_DIR=$HOME/.completion +mkdir -p $COMPL_DIR +cp -f target/release/completion-scripts/substrate.bash $COMPL_DIR/ +echo "source $COMPL_DIR/substrate.bash" >> $HOME/.bash_profile +source $HOME/.bash_profile +---- + +.Update + +When you build a new version of Substrate, the following will ensure you auto-completion script matches the current binary: + +[source, shell] +---- +COMPL_DIR=$HOME/.completion +mkdir -p $COMPL_DIR +cp -f target/release/completion-scripts/substrate.bash $COMPL_DIR/ +source $HOME/.bash_profile +---- diff --git a/substrate/cli/src/cli.yml b/substrate/cli/src/cli.yml new file mode 100644 index 0000000000000..995f773400a71 --- /dev/null +++ b/substrate/cli/src/cli.yml @@ -0,0 +1,197 @@ +name: {name} +author: {author} +about: {description} +args: + - log: + short: l + long: log + value_name: LOG_PATTERN + help: Sets a custom logging filter + takes_value: true + - base-path: + long: base-path + short: d + value_name: PATH + help: Specify custom base path + takes_value: true + - keystore-path: + long: keystore-path + value_name: PATH + help: Specify custom keystore path + takes_value: true + - key: + long: key + value_name: STRING + help: Specify additional key seed + takes_value: true + - node-key: + long: node-key + value_name: KEY + help: Specify node secret key (64-character hex string) + takes_value: true + - validator: + long: validator + help: Enable validator mode + takes_value: false + - light: + long: light + help: Run in light client mode + takes_value: false + - dev: + long: dev + help: Run in development mode; implies --chain=dev --validator --key Alice + takes_value: false + - port: + long: port + value_name: PORT + help: Specify p2p protocol TCP port + takes_value: true + - rpc-port: + long: rpc-port + value_name: PORT + help: Specify HTTP RPC server TCP port + takes_value: true + - ws-port: + long: ws-port + value_name: PORT + help: Specify WebSockets RPC server TCP port + takes_value: true + - bootnodes: + long: bootnodes + value_name: URL + help: Specify a list of bootnodes + takes_value: true + multiple: true + - chain: + long: chain + value_name: CHAIN_SPEC + help: Specify the chain specification (one of krummelanke, dev, local or staging) + takes_value: true + - pruning: + long: pruning + value_name: PRUNING_MODE + help: Specify the pruning mode, a number of blocks to keep or "archive". Default is 256. + takes_value: true + - name: + long: name + value_name: NAME + help: The human-readable name for this node, as reported to the telemetry server, if enabled + takes_value: true + - telemetry: + short: t + long: telemetry + help: Should connect to the Polkadot telemetry server (telemetry is off by default on local chains) + takes_value: false + - no-telemetry: + long: no-telemetry + help: Should not connect to the Polkadot telemetry server (telemetry is on by default on global chains) + takes_value: false + - telemetry-url: + long: telemetry-url + value_name: TELEMETRY_URL + help: The URL of the telemetry server. Implies --telemetry + takes_value: true + - execution: + long: execution + value_name: STRATEGY + help: The means of execution used when calling into the runtime. Can be either wasm, native or both. + - min-heap-pages: + long: min-heap-pages + value_name: COUNT + help: The number of 64KB pages to allocate for Wasm execution initially. + - max-heap-pages: + long: max-heap-pages + value_name: COUNT + help: The maximum number of 64KB pages to ever allocate for Wasm execution. Don't alter this unless you know what you're doing. +subcommands: + - build-spec: + about: Build a spec.json file, outputing to stdout + args: + - raw: + long: raw + help: Force raw genesis storage output. + takes_value: false + - chain: + long: chain + value_name: CHAIN_SPEC + help: Specify the chain specification (one of krummelanke, dev, local or staging) + takes_value: true + - export-blocks: + about: Export blocks to a file + args: + - OUTPUT: + index: 1 + help: Output file name or stdout if unspecified. + required: false + - chain: + long: chain + value_name: CHAIN_SPEC + help: Specify the chain specification. + takes_value: true + - base-path: + long: base-path + short: d + value_name: PATH + help: Specify custom base path. + takes_value: true + - from: + long: from + value_name: BLOCK + help: Specify starting block number. 1 by default. + takes_value: true + - to: + long: to + value_name: BLOCK + help: Specify last block number. Best block by default. + takes_value: true + - json: + long: json + help: Use JSON output rather than binary. + takes_value: false + - import-blocks: + about: Import blocks from file. + args: + - INPUT: + index: 1 + help: Input file or stdin if unspecified. + required: false + - chain: + long: chain + value_name: CHAIN_SPEC + help: Specify the chain specification. + takes_value: true + - base-path: + long: base-path + short: d + value_name: PATH + help: Specify custom base path. + takes_value: true + - execution: + long: execution + value_name: STRATEGY + help: The means of execution used when calling into the runtime. Can be either wasm, native or both. + - min-heap-pages: + long: min-heap-pages + value_name: COUNT + help: The number of 64KB pages to allocate for Wasm execution initially. + - max-heap-pages: + long: max-heap-pages + value_name: COUNT + help: The maximum number of 64KB pages to ever allocate for Wasm execution. Don't alter this unless you know what you're doing. + - revert: + about: Revert chain to the previous state + args: + - NUM: + index: 1 + help: Number of blocks to revert. Default is 256. + - chain: + long: chain + value_name: CHAIN_SPEC + help: Specify the chain specification. + takes_value: true + - base-path: + long: base-path + short: d + value_name: PATH + help: Specify custom base path. + takes_value: true diff --git a/polkadot/cli/src/error.rs b/substrate/cli/src/error.rs similarity index 65% rename from polkadot/cli/src/error.rs rename to substrate/cli/src/error.rs index d7f6afca49b87..2c44083afe41a 100644 --- a/polkadot/cli/src/error.rs +++ b/substrate/cli/src/error.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. +// This file is part of Substrate. -// Polkadot is free software: you can redistribute it and/or modify +// Substrate 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. -// Polkadot is distributed in the hope that it will be useful, +// Substrate 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 Polkadot. If not, see . +// along with Substrate. If not, see . //! Initialization errors. @@ -22,11 +22,16 @@ error_chain! { foreign_links { Io(::std::io::Error) #[doc="IO error"]; Cli(::clap::Error) #[doc="CLI error"]; - Service(::service::Error) #[doc="Polkadot service error"]; + Service(::service::Error) #[doc="Substrate service error"]; } links { Client(client::error::Error, client::error::ErrorKind) #[doc="Client error"]; } errors { + /// Input error. + Input(m: String) { + description("Invalid input"), + display("{}", m), + } } } diff --git a/polkadot/cli/src/informant.rs b/substrate/cli/src/informant.rs similarity index 60% rename from polkadot/cli/src/informant.rs rename to substrate/cli/src/informant.rs index 26915da32e8e2..37eed5d3c2134 100644 --- a/polkadot/cli/src/informant.rs +++ b/substrate/cli/src/informant.rs @@ -1,44 +1,43 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. +// This file is part of Substrate. -// Polkadot is free software: you can redistribute it and/or modify +// Substrate 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. -// Polkadot is distributed in the hope that it will be useful, +// Substrate 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 Polkadot. If not, see . +// along with Substrate. If not, see . //! Console informant. Prints sync progress and block events. Runs on the calling thread. use std::time::{Duration, Instant}; -use futures::stream::Stream; +use futures::{Future, Stream}; use service::{Service, Components}; -use tokio_core::reactor; +use tokio::runtime::TaskExecutor; +use tokio::timer::Interval; use network::{SyncState, SyncProvider}; -use polkadot_primitives::Block; -use state_machine; -use client::{self, BlockchainEvents}; +use client::BlockchainEvents; +use runtime_primitives::traits::{Header, As}; +use substrate_extrinsic_pool::api::ExtrinsicPool; const TIMER_INTERVAL_MS: u64 = 5000; /// Spawn informant on the event loop -pub fn start(service: &Service, handle: reactor::Handle) +pub fn start(service: &Service, exit: ::exit_future::Exit, handle: TaskExecutor) where C: Components, - client::error::Error: From<<<::Backend as client::backend::Backend>::State as state_machine::Backend>::Error>, { - let interval = reactor::Interval::new_at(Instant::now(), Duration::from_millis(TIMER_INTERVAL_MS), &handle) - .expect("Error creating informant timer"); + let interval = Interval::new(Instant::now(), Duration::from_millis(TIMER_INTERVAL_MS)); let network = service.network(); let client = service.client(); - let txpool = service.transaction_pool(); + let txpool = service.extrinsic_pool(); let display_notifications = interval.map_err(|e| debug!("Timer error: {:?}", e)).for_each(move |_| { let sync_status = network.status(); @@ -52,8 +51,9 @@ pub fn start(service: &Service, handle: reactor::Handle) (SyncState::Downloading, Some(n)) => format!("Syncing, target=#{}", n), }; let txpool_status = txpool.light_status(); - info!(target: "polkadot", "{} ({} peers), best: #{} ({})", status, sync_status.num_peers, best_block.number, hash); - telemetry!("system.interval"; "status" => status, "peers" => num_peers, "height" => best_block.number, "best" => ?hash, "txcount" => txpool_status.transaction_count); + let best_number: u64 = best_block.number().as_(); + info!(target: "substrate", "{} ({} peers), best: #{} ({})", status, sync_status.num_peers, best_number, hash); + telemetry!("system.interval"; "status" => status, "peers" => num_peers, "height" => best_number, "best" => ?hash, "txcount" => txpool_status.transaction_count); } else { warn!("Error getting best block information"); } @@ -62,19 +62,18 @@ pub fn start(service: &Service, handle: reactor::Handle) let client = service.client(); let display_block_import = client.import_notification_stream().for_each(|n| { - info!(target: "polkadot", "Imported #{} ({})", n.header.number, n.hash); - telemetry!("block.import"; "height" => n.header.number, "best" => ?n.hash); + info!(target: "substrate", "Imported #{} ({})", n.header.number(), n.hash); Ok(()) }); - let txpool = service.transaction_pool(); + let txpool = service.extrinsic_pool(); let display_txpool_import = txpool.import_notification_stream().for_each(move |_| { let status = txpool.light_status(); telemetry!("txpool.import"; "mem_usage" => status.mem_usage, "count" => status.transaction_count, "sender" => status.senders); Ok(()) }); - handle.spawn(display_notifications); - handle.spawn(display_block_import); - handle.spawn(display_txpool_import); + + let informant_work = display_notifications.join3(display_block_import, display_txpool_import); + handle.spawn(exit.until(informant_work).map(|_| ())); } diff --git a/substrate/cli/src/lib.rs b/substrate/cli/src/lib.rs new file mode 100644 index 0000000000000..324121073eae6 --- /dev/null +++ b/substrate/cli/src/lib.rs @@ -0,0 +1,510 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +//! Substrate CLI library. + +#![warn(missing_docs)] +#![warn(unused_extern_crates)] + +extern crate app_dirs; +extern crate env_logger; +extern crate atty; +extern crate ansi_term; +extern crate regex; +extern crate time; +extern crate fdlimit; +extern crate futures; +extern crate tokio; +extern crate names; +extern crate backtrace; + +extern crate substrate_client as client; +extern crate substrate_network as network; +extern crate substrate_runtime_primitives as runtime_primitives; +extern crate substrate_extrinsic_pool; +extern crate substrate_service as service; +#[macro_use] +extern crate slog; // needed until we can reexport `slog_info` from `substrate_telemetry` +#[macro_use] +extern crate substrate_telemetry; +extern crate exit_future; + +#[macro_use] +extern crate lazy_static; +#[macro_use] +extern crate clap; +#[macro_use] +extern crate error_chain; +#[macro_use] +extern crate log; + +pub mod error; +pub mod informant; +mod panic_hook; + +use runtime_primitives::traits::As; +use service::{ + ServiceFactory, FactoryFullConfiguration, RuntimeGenesis, + FactoryGenesis, PruningMode, ChainSpec, +}; + +use std::io::{Write, Read, stdin, stdout}; +use std::fs::File; +use std::net::SocketAddr; +use std::path::{Path, PathBuf}; +use names::{Generator, Name}; +use regex::Regex; + +use futures::Future; + +/// Executable version. Used to pass version information from the root crate. +pub struct VersionInfo { + /// Implementation version. + pub version: &'static str, + /// SCM Commit hash. + pub commit: &'static str, + /// Executable file name. + pub executable_name: &'static str, + /// Executable file description. + pub description: &'static str, + /// Executable file author. + pub author: &'static str, +} + +/// CLI Action +pub enum Action { + /// Substrate handled the command. No need to do anything. + ExecutedInternally, + /// Service mode requested. Caller should start the service. + RunService((FactoryFullConfiguration, E)), +} + +/// Something that can be converted into an exit signal. +pub trait IntoExit { + /// Exit signal type. + type Exit: Future + Send + 'static; + /// Convert into exit signal. + fn into_exit(self) -> Self::Exit; +} + +fn load_spec(matches: &clap::ArgMatches, factory: F) -> Result, String> + where G: RuntimeGenesis, F: FnOnce(&str) -> Result>, String>, +{ + let chain_key = matches.value_of("chain").unwrap_or_else(|| if matches.is_present("dev") { "dev" } else { "" }); + let spec = match factory(chain_key)? { + Some(spec) => spec, + None => ChainSpec::from_json_file(PathBuf::from(chain_key))? + }; + Ok(spec) +} + +fn base_path(matches: &clap::ArgMatches) -> PathBuf { + matches.value_of("base-path") + .map(|x| Path::new(x).to_owned()) + .unwrap_or_else(default_base_path) +} + +/// Check whether a node name is considered as valid +fn is_node_name_valid(_name: &str) -> Result<(), &str> { + const MAX_NODE_NAME_LENGTH: usize = 32; + let name = _name.to_string(); + if name.chars().count() >= MAX_NODE_NAME_LENGTH { + return Err("Node name too long"); + } + + let invalid_chars = r"[\\.@]"; + let re = Regex::new(invalid_chars).unwrap(); + if re.is_match(&name) { + return Err("Node name should not contain invalid chars such as '.' and '@'"); + } + + let invalid_patterns = r"(https?:\\/+)?(www)+"; + let re = Regex::new(invalid_patterns).unwrap(); + if re.is_match(&name) { + return Err("Node name should not contain urls"); + } + + Ok(()) +} + +/// Parse command line arguments and execute commands or return service configuration. +/// +/// IANA unassigned port ranges that we could use: +/// 6717-6766 Unassigned +/// 8504-8553 Unassigned +/// 9556-9591 Unassigned +/// 9803-9874 Unassigned +/// 9926-9949 Unassigned +pub fn prepare_execution( + args: I, + exit: E, + version: VersionInfo, + spec_factory: S, + impl_name: &'static str, +) -> error::Result> +where + I: IntoIterator, + T: Into + Clone, + E: IntoExit, + F: ServiceFactory, + S: FnOnce(&str) -> Result>>, String>, +{ + panic_hook::set(); + + let yaml = format!(include_str!("./cli.yml"), + name = version.executable_name, + description = version.description, + author = version.author, + ); + let yaml = &clap::YamlLoader::load_from_str(&yaml).expect("Invalid yml file")[0]; + let matches = match clap::App::from_yaml(yaml) + .version(&(crate_version!().to_owned() + "\n")[..]) + .get_matches_from_safe(args) { + Ok(m) => m, + Err(e) => e.exit(), + }; + + // TODO [ToDr] Split parameters parsing from actual execution. + let log_pattern = matches.value_of("log").unwrap_or(""); + init_logger(log_pattern); + fdlimit::raise_fd_limit(); + + if let Some(matches) = matches.subcommand_matches("build-spec") { + let spec = load_spec(&matches, spec_factory)?; + build_spec::(matches, spec)?; + return Ok(Action::ExecutedInternally); + } + + if let Some(matches) = matches.subcommand_matches("export-blocks") { + let spec = load_spec(&matches, spec_factory)?; + export_blocks::(matches, spec, exit.into_exit())?; + return Ok(Action::ExecutedInternally); + } + + if let Some(matches) = matches.subcommand_matches("import-blocks") { + let spec = load_spec(&matches, spec_factory)?; + import_blocks::(matches, spec, exit.into_exit())?; + return Ok(Action::ExecutedInternally); + } + + if let Some(matches) = matches.subcommand_matches("revert") { + let spec = load_spec(&matches, spec_factory)?; + revert_chain::(matches, spec)?; + return Ok(Action::ExecutedInternally); + } + + let spec = load_spec(&matches, spec_factory)?; + let mut config = service::Configuration::default_with_spec(spec); + + config.impl_name = impl_name; + config.impl_commit = version.commit; + config.impl_version = version.version; + + config.name = match matches.value_of("name") { + None => Generator::with_naming(Name::Numbered).next().unwrap(), + Some(name) => name.into(), + }; + match is_node_name_valid(&config.name) { + Ok(_) => (), + Err(msg) => return Err(error::ErrorKind::Input( + format!("Invalid node name '{}'. Reason: {}. If unsure, use none.", config.name, msg)).into()) + } + + let base_path = base_path(&matches); + + config.keystore_path = matches.value_of("keystore") + .map(|x| Path::new(x).to_owned()) + .unwrap_or_else(|| keystore_path(&base_path, config.chain_spec.id())) + .to_string_lossy() + .into(); + + config.database_path = db_path(&base_path, config.chain_spec.id()).to_string_lossy().into(); + + config.pruning = match matches.value_of("pruning") { + Some("archive") => PruningMode::ArchiveAll, + None => PruningMode::default(), + Some(s) => PruningMode::keep_blocks(s.parse() + .map_err(|_| error::ErrorKind::Input("Invalid pruning mode specified".to_owned()))?), + }; + + let role = + if matches.is_present("light") { + config.execution_strategy = service::ExecutionStrategy::NativeWhenPossible; + service::Roles::LIGHT + } else if matches.is_present("validator") || matches.is_present("dev") { + config.execution_strategy = service::ExecutionStrategy::Both; + service::Roles::AUTHORITY + } else { + config.execution_strategy = service::ExecutionStrategy::NativeWhenPossible; + service::Roles::FULL + }; + + if let Some(v) = matches.value_of("min-heap-pages") { + config.min_heap_pages = v.parse().map_err(|_| "Invalid --min-heap-pages argument")?; + } + if let Some(v) = matches.value_of("max-heap-pages") { + config.max_heap_pages = v.parse().map_err(|_| "Invalid --max-heap-pages argument")?; + } + + if let Some(s) = matches.value_of("execution") { + config.execution_strategy = match s { + "both" => service::ExecutionStrategy::Both, + "native" => service::ExecutionStrategy::NativeWhenPossible, + "wasm" => service::ExecutionStrategy::AlwaysWasm, + _ => return Err(error::ErrorKind::Input("Invalid execution mode specified".to_owned()).into()), + }; + } + + config.roles = role; + { + config.network.boot_nodes.extend(matches + .values_of("bootnodes") + .map_or(Default::default(), |v| v.map(|n| n.to_owned()).collect::>())); + config.network.config_path = Some(network_path(&base_path, config.chain_spec.id()).to_string_lossy().into()); + config.network.net_config_path = config.network.config_path.clone(); + + let port = match matches.value_of("port") { + Some(port) => port.parse().map_err(|_| "Invalid p2p port value specified.")?, + None => 30333, + }; + + config.network.listen_address = Some(SocketAddr::new("0.0.0.0".parse().unwrap(), port)); + config.network.public_address = None; + config.network.client_version = config.client_id(); + config.network.use_secret = match matches.value_of("node-key").map(|s| s.parse()) { + Some(Ok(secret)) => Some(secret), + Some(Err(err)) => return Err(format!("Error parsing node key: {}", err).into()), + None => None, + }; + } + + config.keys = matches.values_of("key").unwrap_or_default().map(str::to_owned).collect(); + if matches.is_present("dev") { + config.keys.push("Alice".into()); + } + + config.rpc_http = Some(parse_address("127.0.0.1:9933", "rpc-port", &matches)?); + config.rpc_ws = Some(parse_address("127.0.0.1:9944", "ws-port", &matches)?); + + // Override telemetry + if matches.is_present("no-telemetry") { + config.telemetry_url = None; + } else if let Some(url) = matches.value_of("telemetry-url") { + config.telemetry_url = Some(url.to_owned()); + } + + Ok(Action::RunService((config, exit))) +} + +fn build_spec(matches: &clap::ArgMatches, spec: ChainSpec>) -> error::Result<()> + where F: ServiceFactory, +{ + info!("Building chain spec"); + let raw = matches.is_present("raw"); + let json = service::chain_ops::build_spec::>(spec, raw)?; + print!("{}", json); + Ok(()) +} + +fn export_blocks(matches: &clap::ArgMatches, spec: ChainSpec>, exit: E) -> error::Result<()> + where F: ServiceFactory, E: Future + Send + 'static, +{ + let base_path = base_path(matches); + let mut config = service::Configuration::default_with_spec(spec); + config.database_path = db_path(&base_path, config.chain_spec.id()).to_string_lossy().into(); + info!("DB path: {}", config.database_path); + let from: u64 = match matches.value_of("from") { + Some(v) => v.parse().map_err(|_| "Invalid --from argument")?, + None => 1, + }; + + let to: Option = match matches.value_of("to") { + Some(v) => Some(v.parse().map_err(|_| "Invalid --to argument")?), + None => None, + }; + let json = matches.is_present("json"); + + let file: Box = match matches.value_of("OUTPUT") { + Some(filename) => Box::new(File::create(filename)?), + None => Box::new(stdout()), + }; + + Ok(service::chain_ops::export_blocks::(config, exit, file, As::sa(from), to.map(As::sa), json)?) +} + +fn import_blocks(matches: &clap::ArgMatches, spec: ChainSpec>, exit: E) -> error::Result<()> + where F: ServiceFactory, E: Future + Send + 'static, +{ + let base_path = base_path(matches); + let mut config = service::Configuration::default_with_spec(spec); + config.database_path = db_path(&base_path, config.chain_spec.id()).to_string_lossy().into(); + + if let Some(v) = matches.value_of("min-heap-pages") { + config.min_heap_pages = v.parse().map_err(|_| "Invalid --min-heap-pages argument")?; + } + if let Some(v) = matches.value_of("max-heap-pages") { + config.max_heap_pages = v.parse().map_err(|_| "Invalid --max-heap-pages argument")?; + } + + if let Some(s) = matches.value_of("execution") { + config.execution_strategy = match s { + "both" => service::ExecutionStrategy::Both, + "native" => service::ExecutionStrategy::NativeWhenPossible, + "wasm" => service::ExecutionStrategy::AlwaysWasm, + _ => return Err(error::ErrorKind::Input("Invalid execution mode specified".to_owned()).into()), + }; + } + + let file: Box = match matches.value_of("INPUT") { + Some(filename) => Box::new(File::open(filename)?), + None => Box::new(stdin()), + }; + + Ok(service::chain_ops::import_blocks::(config, exit, file)?) +} + +fn revert_chain(matches: &clap::ArgMatches, spec: ChainSpec>) -> error::Result<()> + where F: ServiceFactory, +{ + let base_path = base_path(matches); + let mut config = service::Configuration::default_with_spec(spec); + config.database_path = db_path(&base_path, config.chain_spec.id()).to_string_lossy().into(); + + let blocks = match matches.value_of("NUM") { + Some(v) => v.parse().map_err(|_| "Invalid block count specified")?, + None => 256, + }; + + Ok(service::chain_ops::revert_chain::(config, As::sa(blocks))?) +} + +fn parse_address(default: &str, port_param: &str, matches: &clap::ArgMatches) -> Result { + let mut address: SocketAddr = default.parse().ok().ok_or_else(|| format!("Invalid address specified for --{}.", port_param))?; + if let Some(port) = matches.value_of(port_param) { + let port: u16 = port.parse().ok().ok_or_else(|| format!("Invalid port for --{} specified.", port_param))?; + address.set_port(port); + } + + Ok(address) +} + +fn keystore_path(base_path: &Path, chain_id: &str) -> PathBuf { + let mut path = base_path.to_owned(); + path.push("chains"); + path.push(chain_id); + path.push("keystore"); + path +} + +fn db_path(base_path: &Path, chain_id: &str) -> PathBuf { + let mut path = base_path.to_owned(); + path.push("chains"); + path.push(chain_id); + path.push("db"); + path +} + +fn network_path(base_path: &Path, chain_id: &str) -> PathBuf { + let mut path = base_path.to_owned(); + path.push("chains"); + path.push(chain_id); + path.push("network"); + path +} + +fn default_base_path() -> PathBuf { + use app_dirs::{AppInfo, AppDataType}; + + let app_info = AppInfo { + name: "Polkadot", + author: "Parity Technologies", + }; + + app_dirs::get_app_root( + AppDataType::UserData, + &app_info, + ).expect("app directories exist on all supported platforms; qed") +} + +fn init_logger(pattern: &str) { + use ansi_term::Colour; + + let mut builder = env_logger::LogBuilder::new(); + // Disable info logging by default for some modules: + builder.filter(Some("ws"), log::LogLevelFilter::Warn); + builder.filter(Some("hyper"), log::LogLevelFilter::Warn); + // Enable info for others. + builder.filter(None, log::LogLevelFilter::Info); + + if let Ok(lvl) = std::env::var("RUST_LOG") { + builder.parse(&lvl); + } + + builder.parse(pattern); + let isatty = atty::is(atty::Stream::Stderr); + let enable_color = isatty; + + let format = move |record: &log::LogRecord| { + let timestamp = time::strftime("%Y-%m-%d %H:%M:%S", &time::now()).expect("Error formatting log timestamp"); + + let mut output = if log::max_log_level() <= log::LogLevelFilter::Info { + format!("{} {}", Colour::Black.bold().paint(timestamp), record.args()) + } else { + let name = ::std::thread::current().name().map_or_else(Default::default, |x| format!("{}", Colour::Blue.bold().paint(x))); + format!("{} {} {} {} {}", Colour::Black.bold().paint(timestamp), name, record.level(), record.target(), record.args()) + }; + + if !enable_color { + output = kill_color(output.as_ref()); + } + + if !isatty && record.level() <= log::LogLevel::Info && atty::is(atty::Stream::Stdout) { + // duplicate INFO/WARN output to console + println!("{}", output); + } + output + }; + builder.format(format); + + builder.init().expect("Logger initialized only once."); +} + +fn kill_color(s: &str) -> String { + lazy_static! { + static ref RE: Regex = Regex::new("\x1b\\[[^m]+m").expect("Error initializing color regex"); + } + RE.replace_all(s, "").to_string() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn tests_node_name_good() { + assert!(is_node_name_valid("short name").is_ok()); + } + + #[test] + fn tests_node_name_bad() { + assert!(is_node_name_valid("long names are not very cool for the ui").is_err()); + assert!(is_node_name_valid("Dots.not.Ok").is_err()); + assert!(is_node_name_valid("http://visit.me").is_err()); + assert!(is_node_name_valid("https://visit.me").is_err()); + assert!(is_node_name_valid("www.visit.me").is_err()); + assert!(is_node_name_valid("email@domain").is_err()); + } +} diff --git a/substrate/cli/src/panic_hook.rs b/substrate/cli/src/panic_hook.rs new file mode 100644 index 0000000000000..c7cea5c8537b0 --- /dev/null +++ b/substrate/cli/src/panic_hook.rs @@ -0,0 +1,69 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +//! Custom panic hook with bug report link + +use backtrace::Backtrace; +use std::io::{self, Write}; +use std::panic::{self, PanicInfo}; +use std::thread; + +/// Set the panic hook +pub fn set() { + panic::set_hook(Box::new(panic_hook)); +} + +static ABOUT_PANIC: &str = " +This is a bug. Please report it at: + + https://github.com/paritytech/polkadot/issues/new +"; + +fn panic_hook(info: &PanicInfo) { + let location = info.location(); + let file = location.as_ref().map(|l| l.file()).unwrap_or(""); + let line = location.as_ref().map(|l| l.line()).unwrap_or(0); + + let msg = match info.payload().downcast_ref::<&'static str>() { + Some(s) => *s, + None => match info.payload().downcast_ref::() { + Some(s) => &s[..], + None => "Box", + } + }; + + let thread = thread::current(); + let name = thread.name().unwrap_or(""); + + let backtrace = Backtrace::new(); + + let mut stderr = io::stderr(); + + let _ = writeln!(stderr, ""); + let _ = writeln!(stderr, "===================="); + let _ = writeln!(stderr, ""); + let _ = writeln!(stderr, "{:?}", backtrace); + let _ = writeln!(stderr, ""); + let _ = writeln!( + stderr, + "Thread '{}' panicked at '{}', {}:{}", + name, msg, file, line + ); + + let _ = writeln!(stderr, "{}", ABOUT_PANIC); + ::std::process::exit(1); +} + diff --git a/substrate/client/Cargo.toml b/substrate/client/Cargo.toml index 7455c51942165..30ec72435d202 100644 --- a/substrate/client/Cargo.toml +++ b/substrate/client/Cargo.toml @@ -4,13 +4,14 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] -error-chain = "0.11" +error-chain = "0.12" log = "0.3" parking_lot = "0.4" triehash = "0.1" hex-literal = "0.1" futures = "0.1.17" ed25519 = { path = "../ed25519" } +slog = "^2" substrate-bft = { path = "../bft" } substrate-codec = { path = "../codec" } substrate-executor = { path = "../executor" } @@ -20,6 +21,7 @@ substrate-runtime-support = { path = "../runtime-support" } substrate-runtime-primitives = { path = "../runtime/primitives" } substrate-state-machine = { path = "../state-machine" } substrate-keyring = { path = "../../substrate/keyring" } +substrate-telemetry = { path = "../telemetry" } [dev-dependencies] substrate-test-client = { path = "../test-client" } diff --git a/substrate/client/db/Cargo.toml b/substrate/client/db/Cargo.toml index b299d838a0b33..5a26a7cdb8537 100644 --- a/substrate/client/db/Cargo.toml +++ b/substrate/client/db/Cargo.toml @@ -18,6 +18,8 @@ substrate-client = { path = "../../../substrate/client" } substrate-state-machine = { path = "../../../substrate/state-machine" } substrate-runtime-support = { path = "../../../substrate/runtime-support" } substrate-codec = { path = "../../../substrate/codec" } +substrate-executor = { path = "../../../substrate/executor" } +substrate-state-db = { path = "../../../substrate/state-db" } [dev-dependencies] kvdb-memorydb = { git = "https://github.com/paritytech/parity.git" } diff --git a/substrate/client/db/src/cache.rs b/substrate/client/db/src/cache.rs new file mode 100644 index 0000000000000..c808027d9fb39 --- /dev/null +++ b/substrate/client/db/src/cache.rs @@ -0,0 +1,447 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! DB-backed cache of blockchain data. + +use std::sync::Arc; +use parking_lot::RwLock; + +use kvdb::{KeyValueDB, DBTransaction}; + +use client::blockchain::Cache as BlockchainCache; +use client::error::Result as ClientResult; +use codec::{Codec, Encode, Decode, Input, Output}; +use primitives::AuthorityId; +use runtime_primitives::generic::BlockId; +use runtime_primitives::traits::{Block as BlockT, As, NumberFor}; +use utils::{COLUMN_META, BlockKey, db_err, meta_keys, read_id, db_key_to_number, number_to_db_key}; + +/// Database-backed cache of blockchain data. +pub struct DbCache { + db: Arc, + block_index_column: Option, + authorities_at: DbCacheList>, +} + +impl DbCache + where + Block: BlockT, + NumberFor: As, +{ + /// Create new cache. + pub fn new( + db: Arc, + block_index_column: Option, + authorities_column: Option + ) -> ClientResult { + Ok(DbCache { + db: db.clone(), + block_index_column, + authorities_at: DbCacheList::new(db, meta_keys::BEST_AUTHORITIES, authorities_column)?, + }) + } + + /// Get authorities_cache. + pub fn authorities_at_cache(&self) -> &DbCacheList> { + &self.authorities_at + } +} + +impl BlockchainCache for DbCache + where + Block: BlockT, + NumberFor: As, +{ + fn authorities_at(&self, at: BlockId) -> Option> { + let authorities_at = read_id(&*self.db, self.block_index_column, at).and_then(|at| match at { + Some(at) => self.authorities_at.value_at_key(at), + None => Ok(None), + }); + + match authorities_at { + Ok(authorities) => authorities, + Err(error) => { + warn!("Trying to read authorities from db cache has failed with: {}", error); + None + }, + } + } +} + +/// Database-backed blockchain cache which holds its entries as a list. +/// The meta column holds the pointer to the best known cache entry and +/// every entry points to the previous entry. +/// New entry appears when the set of authorities changes in block, so the +/// best entry here means the entry that is valid for the best block (and +/// probably for its ascendants). +pub struct DbCacheList { + db: Arc, + meta_key: &'static [u8], + column: Option, + /// Best entry at the moment. None means that cache has no entries at all. + best_entry: RwLock, T>>>, +} + +/// Single cache entry. +#[derive(Clone)] +#[cfg_attr(test, derive(Debug, PartialEq))] +pub struct Entry { + /// first block, when this value became actual + valid_from: N, + /// None means that we do not know the value starting from `valid_from` block + value: Option, +} + +/// Internal representation of the single cache entry. The entry points to the +/// previous entry in the cache, allowing us to traverse back in time in list-style. +#[cfg_attr(test, derive(Debug, PartialEq))] +struct StorageEntry { + /// None if valid from the beginning + prev_valid_from: Option, + /// None means that we do not know the value starting from `valid_from` block + value: Option, +} + +impl DbCacheList + where + Block: BlockT, + NumberFor: As, + T: Clone + PartialEq + Codec, +{ + /// Creates new cache list. + fn new(db: Arc, meta_key: &'static [u8], column: Option) -> ClientResult { + let best_entry = RwLock::new(db.get(COLUMN_META, meta_key) + .map_err(db_err) + .and_then(|block| match block { + Some(block) => { + let valid_from = db_key_to_number(&block)?; + read_storage_entry::(&*db, column, valid_from) + .map(|entry| Some(Entry { + valid_from, + value: entry + .expect("meta entry references the entry at the block; storage entry at block exists when referenced; qed") + .value, + })) + }, + None => Ok(None), + })?); + + Ok(DbCacheList { + db, + column, + meta_key, + best_entry, + }) + } + + /// Gets the best known entry. + pub fn best_entry(&self) -> Option, T>> { + self.best_entry.read().clone() + } + + /// Commits the new best pending value to the database. Returns Some if best entry must + /// be updated after transaction is committed. + pub fn commit_best_entry( + &self, + transaction: &mut DBTransaction, + valid_from: NumberFor, + pending_value: Option + ) -> Option, T>> { + let best_entry = self.best_entry(); + let update_best_entry = match ( + best_entry.as_ref().and_then(|a| a.value.as_ref()), + pending_value.as_ref() + ) { + (Some(best_value), Some(pending_value)) => best_value != pending_value, + (None, Some(_)) | (Some(_), None) => true, + (None, None) => false, + }; + if !update_best_entry { + return None; + } + + let valid_from_key = number_to_db_key(valid_from); + transaction.put(COLUMN_META, self.meta_key, &valid_from_key); + transaction.put(self.column, &valid_from_key, &StorageEntry { + prev_valid_from: best_entry.map(|b| b.valid_from), + value: pending_value.clone(), + }.encode()); + + Some(Entry { + valid_from, + value: pending_value, + }) + } + + /// Updates the best in-memory cache entry. Must be called after transaction with changes + /// from commit_best_entry has been committed. + pub fn update_best_entry(&self, best_entry: Option, T>>) { + *self.best_entry.write() = best_entry; + } + + /// Prune all entries from the beginning up to the block (including entry at the number). Returns + /// the number of pruned entries. Pruning never deletes the latest entry in the cache. + pub fn prune_entries( + &self, + transaction: &mut DBTransaction, + last_to_prune: NumberFor + ) -> ClientResult { + // find the last entry we want to keep + let mut last_entry_to_keep = match self.best_entry() { + Some(best_entry) => best_entry.valid_from, + None => return Ok(0), + }; + let mut first_entry_to_remove = last_entry_to_keep; + while first_entry_to_remove > last_to_prune { + last_entry_to_keep = first_entry_to_remove; + + let entry = read_storage_entry::(&*self.db, self.column, first_entry_to_remove)? + .expect("entry referenced from the next entry; entry exists when referenced; qed"); + // if we have reached the first list entry + // AND all list entries are for blocks that are later than last_to_prune + // => nothing to prune + first_entry_to_remove = match entry.prev_valid_from { + Some(prev_valid_from) => prev_valid_from, + None => return Ok(0), + } + } + + // remove all entries, starting from entry_to_remove + let mut pruned = 0; + let mut entry_to_remove = Some(first_entry_to_remove); + while let Some(current_entry) = entry_to_remove { + let entry = read_storage_entry::(&*self.db, self.column, current_entry)? + .expect("referenced entry exists; entry_to_remove is a reference to the entry; qed"); + + if current_entry != last_entry_to_keep { + transaction.delete(self.column, &number_to_db_key(current_entry)); + pruned += 1; + } + entry_to_remove = entry.prev_valid_from; + } + + let mut entry = read_storage_entry::(&*self.db, self.column, last_entry_to_keep)? + .expect("last_entry_to_keep >= first_entry_to_remove; that means that we're leaving this entry in the db; qed"); + entry.prev_valid_from = None; + transaction.put(self.column, &number_to_db_key(last_entry_to_keep), &entry.encode()); + + Ok(pruned) + } + + /// Reads the cached value, actual at given block. Returns None if the value was not cached + /// or if it has been pruned. + fn value_at_key(&self, key: BlockKey) -> ClientResult> { + let at = db_key_to_number::>(&key)?; + let best_valid_from = match self.best_entry() { + // there are entries in cache + Some(best_entry) => { + // we're looking for the best value + if at >= best_entry.valid_from { + return Ok(best_entry.value); + } + + // we're looking for the value of older blocks + best_entry.valid_from + }, + // there are no entries in the cache + None => return Ok(None), + }; + + let mut entry = read_storage_entry::(&*self.db, self.column, best_valid_from)? + .expect("self.best_entry().is_some() if there's entry for best_valid_from; qed"); + loop { + let prev_valid_from = match entry.prev_valid_from { + Some(prev_valid_from) => prev_valid_from, + None => return Ok(None), + }; + + let prev_entry = read_storage_entry::(&*self.db, self.column, prev_valid_from)? + .expect("entry referenced from the next entry; entry exists when referenced; qed"); + if at >= prev_valid_from { + return Ok(prev_entry.value); + } + + entry = prev_entry; + } + } +} + +/// Reads the entry at the block with given number. +fn read_storage_entry( + db: &KeyValueDB, + column: Option, + number: NumberFor +) -> ClientResult, T>>> + where + Block: BlockT, + NumberFor: As, + T: Codec, +{ + db.get(column, &number_to_db_key(number)) + .and_then(|entry| match entry { + Some(entry) => Ok(StorageEntry::, T>::decode(&mut &entry[..])), + None => Ok(None), + }) + .map_err(db_err) +} + +impl Encode for StorageEntry { + fn encode_to(&self, dest: &mut O) { + dest.push(&self.prev_valid_from); + dest.push(&self.value); + } +} + +impl Decode for StorageEntry { + fn decode(input: &mut I) -> Option { + Some(StorageEntry { + prev_valid_from: Decode::decode(input)?, + value: Decode::decode(input)?, + }) + } +} + +#[cfg(test)] +mod tests { + use runtime_primitives::testing::Block as RawBlock; + use light::{AUTHORITIES_ENTRIES_TO_KEEP, columns, LightStorage}; + use light::tests::insert_block; + use super::*; + + type Block = RawBlock; + + #[test] + fn authorities_storage_entry_serialized() { + let test_cases: Vec>> = vec![ + StorageEntry { prev_valid_from: Some(42), value: Some(vec![[1u8; 32].into()]) }, + StorageEntry { prev_valid_from: None, value: Some(vec![[1u8; 32].into(), [2u8; 32].into()]) }, + StorageEntry { prev_valid_from: None, value: None }, + ]; + + for expected in test_cases { + let serialized = expected.encode(); + let deserialized = StorageEntry::decode(&mut &serialized[..]).unwrap(); + assert_eq!(expected, deserialized); + } + } + + #[test] + fn best_authorities_are_updated() { + let db = LightStorage::new_test(); + let authorities_at: Vec<(usize, Option>>)> = vec![ + (0, None), + (0, None), + (1, Some(Entry { valid_from: 1, value: Some(vec![[2u8; 32].into()]) })), + (1, Some(Entry { valid_from: 1, value: Some(vec![[2u8; 32].into()]) })), + (2, Some(Entry { valid_from: 3, value: Some(vec![[4u8; 32].into()]) })), + (2, Some(Entry { valid_from: 3, value: Some(vec![[4u8; 32].into()]) })), + (3, Some(Entry { valid_from: 5, value: None })), + (3, Some(Entry { valid_from: 5, value: None })), + ]; + + // before any block, there are no entries in cache + assert!(db.cache().authorities_at_cache().best_entry().is_none()); + assert_eq!(db.db().iter(columns::AUTHORITIES).count(), 0); + + // insert blocks and check that best_authorities() returns correct result + let mut prev_hash = Default::default(); + for number in 0..authorities_at.len() { + let authorities_at_number = authorities_at[number].1.clone().and_then(|e| e.value); + prev_hash = insert_block(&db, &prev_hash, number as u64, authorities_at_number); + assert_eq!(db.cache().authorities_at_cache().best_entry(), authorities_at[number].1); + assert_eq!(db.db().iter(columns::AUTHORITIES).count(), authorities_at[number].0); + } + + // check that authorities_at() returns correct results for all retrospective blocks + for number in 1..authorities_at.len() + 1 { + assert_eq!(db.cache().authorities_at(BlockId::Number(number as u64)), + authorities_at.get(number + 1) + .or_else(|| authorities_at.last()) + .unwrap().1.clone().and_then(|e| e.value)); + } + + // now check that cache entries are pruned when new blocks are inserted + let mut current_entries_count = authorities_at.last().unwrap().0; + let pruning_starts_at = AUTHORITIES_ENTRIES_TO_KEEP as usize; + for number in authorities_at.len()..authorities_at.len() + pruning_starts_at { + prev_hash = insert_block(&db, &prev_hash, number as u64, None); + if number > pruning_starts_at { + let prev_entries_count = authorities_at[number - pruning_starts_at].0; + let entries_count = authorities_at.get(number - pruning_starts_at + 1).map(|e| e.0) + .unwrap_or_else(|| authorities_at.last().unwrap().0); + current_entries_count -= entries_count - prev_entries_count; + } + + // there's always at least 1 entry in the cache (after first insertion) + assert_eq!(db.db().iter(columns::AUTHORITIES).count(), ::std::cmp::max(current_entries_count, 1)); + } + } + + #[test] + fn best_authorities_are_pruned() { + let db = LightStorage::::new_test(); + let mut transaction = DBTransaction::new(); + + // insert first entry at block#100 + db.cache().authorities_at_cache().update_best_entry( + db.cache().authorities_at_cache().commit_best_entry(&mut transaction, 100, Some(vec![[1u8; 32].into()]))); + db.db().write(transaction).unwrap(); + + // no entries are pruned, since there's only one entry in the cache + let mut transaction = DBTransaction::new(); + assert_eq!(db.cache().authorities_at_cache().prune_entries(&mut transaction, 50).unwrap(), 0); + assert_eq!(db.cache().authorities_at_cache().prune_entries(&mut transaction, 100).unwrap(), 0); + assert_eq!(db.cache().authorities_at_cache().prune_entries(&mut transaction, 150).unwrap(), 0); + + // insert second entry at block#200 + let mut transaction = DBTransaction::new(); + db.cache().authorities_at_cache().update_best_entry( + db.cache().authorities_at_cache().commit_best_entry(&mut transaction, 200, Some(vec![[2u8; 32].into()]))); + db.db().write(transaction).unwrap(); + + let mut transaction = DBTransaction::new(); + assert_eq!(db.cache().authorities_at_cache().prune_entries(&mut transaction, 50).unwrap(), 0); + assert_eq!(db.cache().authorities_at_cache().prune_entries(&mut transaction, 100).unwrap(), 1); + assert_eq!(db.cache().authorities_at_cache().prune_entries(&mut transaction, 150).unwrap(), 1); + // still only 1 entry is removed since pruning never deletes the last entry + assert_eq!(db.cache().authorities_at_cache().prune_entries(&mut transaction, 200).unwrap(), 1); + assert_eq!(db.cache().authorities_at_cache().prune_entries(&mut transaction, 250).unwrap(), 1); + + // physically remove entry for block#100 from db + let mut transaction = DBTransaction::new(); + assert_eq!(db.cache().authorities_at_cache().prune_entries(&mut transaction, 150).unwrap(), 1); + db.db().write(transaction).unwrap(); + + assert_eq!(db.cache().authorities_at_cache().best_entry().unwrap().value, Some(vec![[2u8; 32].into()])); + assert_eq!(db.cache().authorities_at(BlockId::Number(50)), None); + assert_eq!(db.cache().authorities_at(BlockId::Number(100)), None); + assert_eq!(db.cache().authorities_at(BlockId::Number(150)), None); + assert_eq!(db.cache().authorities_at(BlockId::Number(200)), Some(vec![[2u8; 32].into()])); + assert_eq!(db.cache().authorities_at(BlockId::Number(250)), Some(vec![[2u8; 32].into()])); + + // try to delete last entry => failure (no entries are removed) + let mut transaction = DBTransaction::new(); + assert_eq!(db.cache().authorities_at_cache().prune_entries(&mut transaction, 300).unwrap(), 0); + db.db().write(transaction).unwrap(); + + assert_eq!(db.cache().authorities_at_cache().best_entry().unwrap().value, Some(vec![[2u8; 32].into()])); + assert_eq!(db.cache().authorities_at(BlockId::Number(50)), None); + assert_eq!(db.cache().authorities_at(BlockId::Number(100)), None); + assert_eq!(db.cache().authorities_at(BlockId::Number(150)), None); + assert_eq!(db.cache().authorities_at(BlockId::Number(200)), Some(vec![[2u8; 32].into()])); + assert_eq!(db.cache().authorities_at(BlockId::Number(250)), Some(vec![[2u8; 32].into()])); + } +} diff --git a/substrate/client/db/src/lib.rs b/substrate/client/db/src/lib.rs index f222df681fc03..b297341fa19f4 100644 --- a/substrate/client/db/src/lib.rs +++ b/substrate/client/db/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! Client backend that uses RocksDB database as storage. State is still kept in memory. +//! Client backend that uses RocksDB database as storage. extern crate substrate_client as client; extern crate kvdb_rocksdb; @@ -27,6 +27,8 @@ extern crate substrate_primitives as primitives; extern crate substrate_runtime_support as runtime_support; extern crate substrate_runtime_primitives as runtime_primitives; extern crate substrate_codec as codec; +extern crate substrate_executor as executor; +extern crate substrate_state_db as state_db; #[macro_use] extern crate log; @@ -34,21 +36,31 @@ extern crate log; #[cfg(test)] extern crate kvdb_memorydb; +pub mod light; + +mod cache; +mod utils; + use std::sync::Arc; use std::path::PathBuf; -use codec::Slicable; -use hashdb::DBValue; -use kvdb_rocksdb::{Database, DatabaseConfig}; +use codec::{Decode, Encode}; use kvdb::{KeyValueDB, DBTransaction}; use memorydb::MemoryDB; use parking_lot::RwLock; +use primitives::{H256, AuthorityId}; use runtime_primitives::generic::BlockId; use runtime_primitives::bft::Justification; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, Hashing, HashingFor, Zero}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, Hash, HashFor, NumberFor, Zero}; use runtime_primitives::BuildStorage; use state_machine::backend::Backend as StateBackend; -use state_machine::CodeExecutor; +use executor::RuntimeInfo; +use state_machine::{CodeExecutor, TrieH256, DBValue, ExecutionStrategy}; +use utils::{Meta, db_err, meta_keys, number_to_db_key, open_database, read_db, read_id, read_meta}; +use state_db::StateDb; +pub use state_db::PruningMode; + +const FINALIZATION_WINDOW: u64 = 32; /// DB-backed patricia trie state, transaction type is an overlay of changes to commit. pub type DbState = state_machine::TrieBackend; @@ -59,6 +71,8 @@ pub struct DatabaseSettings { pub cache_size: Option, /// Path to the database. pub path: PathBuf, + /// Pruning mode. + pub pruning: PruningMode, } /// Create an instance of db-backed client. @@ -66,31 +80,26 @@ pub fn new_client( settings: DatabaseSettings, executor: E, genesis_storage: S, + execution_strategy: ExecutionStrategy, ) -> Result, client::LocalCallExecutor, E>, Block>, client::error::Error> where Block: BlockT, - ::Number: As, - Block::Hash: Into<[u8; 32]>, // TODO: remove when patricia_trie generic. - E: CodeExecutor, + E: CodeExecutor + RuntimeInfo, S: BuildStorage, { - let backend = Arc::new(Backend::new(&settings)?); + let backend = Arc::new(Backend::new(settings, FINALIZATION_WINDOW)?); let executor = client::LocalCallExecutor::new(backend.clone(), executor); - Ok(client::Client::new(backend, executor, genesis_storage)?) + Ok(client::Client::new(backend, executor, genesis_storage, execution_strategy)?) } mod columns { pub const META: Option = Some(0); pub const STATE: Option = Some(1); - pub const BLOCK_INDEX: Option = Some(2); - pub const HEADER: Option = Some(3); - pub const BODY: Option = Some(4); - pub const JUSTIFICATION: Option = Some(5); - pub const NUM_COLUMNS: u32 = 6; -} - -mod meta { - pub const BEST_BLOCK: &[u8; 4] = b"best"; + pub const STATE_META: Option = Some(2); + pub const BLOCK_INDEX: Option = Some(3); + pub const HEADER: Option = Some(4); + pub const BODY: Option = Some(5); + pub const JUSTIFICATION: Option = Some(6); } struct PendingBlock { @@ -100,34 +109,14 @@ struct PendingBlock { is_best: bool, } -#[derive(Clone)] -struct Meta { - best_hash: H, - best_number: N, - genesis_hash: H, -} - -type BlockKey = [u8; 4]; +// wrapper that implements trait required for state_db +struct StateMetaDb<'a>(&'a KeyValueDB); -// Little endian -fn number_to_db_key(n: N) -> BlockKey where N: As { - let n: u32 = n.as_(); +impl<'a> state_db::MetaDb for StateMetaDb<'a> { + type Error = kvdb::Error; - [ - (n >> 24) as u8, - ((n >> 16) & 0xff) as u8, - ((n >> 8) & 0xff) as u8, - (n & 0xff) as u8 - ] -} - -// Maps database error to client error -fn db_err(err: kvdb::Error) -> client::error::Error { - use std::error::Error; - match err.kind() { - &kvdb::ErrorKind::Io(ref err) => client::error::ErrorKind::Backend(err.description().into()).into(), - &kvdb::ErrorKind::Msg(ref m) => client::error::ErrorKind::Backend(m.clone()).into(), - _ => client::error::ErrorKind::Backend("Unknown backend error".into()).into(), + fn get_meta(&self, key: &[u8]) -> Result>, Self::Error> { + self.0.get(columns::STATE_META, key).map(|r| r.map(|v| v.to_vec())) } } @@ -137,60 +126,15 @@ pub struct BlockchainDb { meta: RwLock::Number, Block::Hash>>, } -impl BlockchainDb where ::Number: As { - fn id(&self, id: BlockId) -> Result, client::error::Error> { - match id { - BlockId::Hash(h) => { - { - let meta = self.meta.read(); - if meta.best_hash == h { - return Ok(Some(number_to_db_key(meta.best_number))); - } - } - self.db.get(columns::BLOCK_INDEX, h.as_ref()).map(|v| v.map(|v| { - let mut key: [u8; 4] = [0; 4]; - key.copy_from_slice(&v); - key - })).map_err(db_err) - }, - BlockId::Number(n) => Ok(Some(number_to_db_key(n))), - } - } - +impl BlockchainDb { fn new(db: Arc) -> Result { - let (best_hash, best_number) = if let Some(Some(header)) = db.get(columns::META, meta::BEST_BLOCK).and_then(|id| - match id { - Some(id) => db.get(columns::HEADER, &id).map(|h| h.map(|b| Block::Header::decode(&mut &b[..]))), - None => Ok(None), - }).map_err(db_err)? - { - let hash = header.hash(); - debug!("DB Opened blockchain db, best {:?} ({})", hash, header.number()); - (hash, header.number().clone()) - } else { - (Default::default(), Zero::zero()) - }; - let genesis_hash = db.get(columns::HEADER, &number_to_db_key(::Number::zero())).map_err(db_err)? - .map(|b| HashingFor::::hash(&b)).unwrap_or_default().into(); - + let meta = read_meta::(&*db, columns::HEADER)?; Ok(BlockchainDb { db, - meta: RwLock::new(Meta { - best_hash, - best_number, - genesis_hash, - }) + meta: RwLock::new(meta) }) } - fn read_db(&self, id: BlockId, column: Option) -> Result, client::error::Error> { - self.id(id).and_then(|key| - match key { - Some(key) => self.db.get(column, &key).map_err(db_err), - None => Ok(None), - }) - } - fn update_meta(&self, hash: Block::Hash, number: ::Number, is_best: bool) { if is_best { let mut meta = self.meta.write(); @@ -203,9 +147,9 @@ impl BlockchainDb where ::Number } } -impl client::blockchain::Backend for BlockchainDb where ::Number: As { +impl client::blockchain::HeaderBackend for BlockchainDb { fn header(&self, id: BlockId) -> Result, client::error::Error> { - match self.read_db(id, columns::HEADER)? { + match read_db(&*self.db, columns::BLOCK_INDEX, columns::HEADER, id)? { Some(header) => match Block::Header::decode(&mut &header[..]) { Some(header) => Ok(Some(header)), None => return Err(client::error::ErrorKind::Backend("Error decoding header".into()).into()), @@ -214,26 +158,6 @@ impl client::blockchain::Backend for BlockchainDb w } } - fn body(&self, id: BlockId) -> Result>, client::error::Error> { - match self.read_db(id, columns::BODY)? { - Some(body) => match Slicable::decode(&mut &body[..]) { - Some(body) => Ok(Some(body)), - None => return Err(client::error::ErrorKind::Backend("Error decoding body".into()).into()), - } - None => Ok(None), - } - } - - fn justification(&self, id: BlockId) -> Result>, client::error::Error> { - match self.read_db(id, columns::JUSTIFICATION)? { - Some(justification) => match Slicable::decode(&mut &justification[..]) { - Some(justification) => Ok(Some(justification)), - None => return Err(client::error::ErrorKind::Backend("Error decoding justification".into()).into()), - } - None => Ok(None), - } - } - fn info(&self) -> Result, client::error::Error> { let meta = self.meta.read(); Ok(client::blockchain::Info { @@ -245,7 +169,7 @@ impl client::blockchain::Backend for BlockchainDb w fn status(&self, id: BlockId) -> Result { let exists = match id { - BlockId::Hash(_) => self.id(id)?.is_some(), + BlockId::Hash(_) => read_id(&*self.db, columns::BLOCK_INDEX, id)?.is_some(), BlockId::Number(n) => n <= self.meta.read().best_number, }; match exists { @@ -255,12 +179,38 @@ impl client::blockchain::Backend for BlockchainDb w } fn hash(&self, number: ::Number) -> Result, client::error::Error> { - self.read_db(BlockId::Number(number), columns::HEADER).map(|x| - x.map(|raw| HashingFor::::hash(&raw[..])).map(Into::into) + read_db::(&*self.db, columns::BLOCK_INDEX, columns::HEADER, BlockId::Number(number)).map(|x| + x.map(|raw| HashFor::::hash(&raw[..])).map(Into::into) ) } } +impl client::blockchain::Backend for BlockchainDb { + fn body(&self, id: BlockId) -> Result>, client::error::Error> { + match read_db(&*self.db, columns::BLOCK_INDEX, columns::BODY, id)? { + Some(body) => match Decode::decode(&mut &body[..]) { + Some(body) => Ok(Some(body)), + None => return Err(client::error::ErrorKind::Backend("Error decoding body".into()).into()), + } + None => Ok(None), + } + } + + fn justification(&self, id: BlockId) -> Result>, client::error::Error> { + match read_db(&*self.db, columns::BLOCK_INDEX, columns::JUSTIFICATION, id)? { + Some(justification) => match Decode::decode(&mut &justification[..]) { + Some(justification) => Ok(Some(justification)), + None => return Err(client::error::ErrorKind::Backend("Error decoding justification".into()).into()), + } + None => Ok(None), + } + } + + fn cache(&self) -> Option<&client::blockchain::Cache> { + None + } +} + /// Database transaction pub struct BlockImportOperation { old_state: DbState, @@ -286,6 +236,10 @@ impl client::backend::BlockImportOperation for BlockImport Ok(()) } + fn update_authorities(&mut self, _authorities: Vec) { + // currently authorities are not cached on full nodes + } + fn update_storage(&mut self, update: MemoryDB) -> Result<(), client::error::Error> { self.updates = update; Ok(()) @@ -299,48 +253,86 @@ impl client::backend::BlockImportOperation for BlockImport } } +struct StorageDb { + pub db: Arc, + pub state_db: StateDb, +} + +impl state_machine::Storage for StorageDb { + fn get(&self, key: &TrieH256) -> Result, String> { + self.state_db.get(&key.0.into(), self).map(|r| r.map(|v| DBValue::from_slice(&v))) + .map_err(|e| format!("Database backend error: {:?}", e)) + } +} + +impl state_db::HashDb for StorageDb { + type Error = kvdb::Error; + type Hash = H256; + + fn get(&self, key: &H256) -> Result>, Self::Error> { + self.db.get(columns::STATE, &key[..]).map(|r| r.map(|v| v.to_vec())) + } +} + + /// Disk backend. Keeps data in a key-value store. In archive mode, trie nodes are kept from all blocks. /// Otherwise, trie nodes are kept only from the most recent block. pub struct Backend { - db: Arc, + storage: Arc>, blockchain: BlockchainDb, - archive: bool, + finalization_window: u64, } -impl Backend where ::Number: As { +impl Backend { /// Create a new instance of database backend. - pub fn new(config: &DatabaseSettings) -> Result { - let mut db_config = DatabaseConfig::with_columns(Some(columns::NUM_COLUMNS)); - db_config.memory_budget = config.cache_size; - db_config.wal = true; - let path = config.path.to_str().ok_or_else(|| client::error::ErrorKind::Backend("Invalid database path".into()))?; - let db = Arc::new(Database::open(&db_config, &path).map_err(db_err)?); + pub fn new(config: DatabaseSettings, finalization_window: u64) -> Result { + let db = open_database(&config, "full")?; - Backend::from_kvdb(db as Arc<_>, true) + Backend::from_kvdb(db as Arc<_>, config.pruning, finalization_window) } #[cfg(test)] fn new_test() -> Self { - let db = Arc::new(::kvdb_memorydb::create(columns::NUM_COLUMNS)); + use utils::NUM_COLUMNS; - Backend::from_kvdb(db as Arc<_>, false).expect("failed to create test-db") + let db = Arc::new(::kvdb_memorydb::create(NUM_COLUMNS)); + + Backend::from_kvdb(db as Arc<_>, PruningMode::keep_blocks(0), 0).expect("failed to create test-db") } - fn from_kvdb(db: Arc, archive: bool) -> Result { + fn from_kvdb(db: Arc, pruning: PruningMode, finalization_window: u64) -> Result { let blockchain = BlockchainDb::new(db.clone())?; + let map_e = |e: state_db::Error| ::client::error::Error::from(format!("State database error: {:?}", e)); + let state_db: StateDb = StateDb::new(pruning, &StateMetaDb(&*db)).map_err(map_e)?; + let storage_db = StorageDb { + db, + state_db, + }; Ok(Backend { - db, + storage: Arc::new(storage_db), blockchain, - archive + finalization_window, }) } } -impl client::backend::Backend for Backend where - ::Number: As, - Block::Hash: Into<[u8; 32]>, // TODO: remove when patricia_trie generic. -{ +fn apply_state_commit(transaction: &mut DBTransaction, commit: state_db::CommitSet) { + for (key, val) in commit.data.inserted.into_iter() { + transaction.put(columns::STATE, &key[..], &val); + } + for key in commit.data.deleted.into_iter() { + transaction.delete(columns::STATE, &key[..]); + } + for (key, val) in commit.meta.inserted.into_iter() { + transaction.put(columns::STATE_META, &key[..], &val); + } + for key in commit.meta.deleted.into_iter() { + transaction.delete(columns::STATE_META, &key[..]); + } +} + +impl client::backend::Backend for Backend { type BlockImportOperation = BlockImportOperation; type Blockchain = BlockchainDb; type State = DbState; @@ -355,11 +347,12 @@ impl client::backend::Backend for Backend where } fn commit_operation(&self, mut operation: Self::BlockImportOperation) -> Result<(), client::error::Error> { + use client::blockchain::HeaderBackend; let mut transaction = DBTransaction::new(); if let Some(pending_block) = operation.pending_block { let hash = pending_block.header.hash(); let number = pending_block.header.number().clone(); - let key = number_to_db_key(pending_block.header.number().clone()); + let key = number_to_db_key(number.clone()); transaction.put(columns::HEADER, &key, &pending_block.header.encode()); if let Some(body) = pending_block.body { transaction.put(columns::BODY, &key, &body.encode()); @@ -369,46 +362,98 @@ impl client::backend::Backend for Backend where } transaction.put(columns::BLOCK_INDEX, hash.as_ref(), &key); if pending_block.is_best { - transaction.put(columns::META, meta::BEST_BLOCK, &key); + transaction.put(columns::META, meta_keys::BEST_BLOCK, &key); } + let mut changeset: state_db::ChangeSet = state_db::ChangeSet::default(); for (key, (val, rc)) in operation.updates.drain() { if rc > 0 { - transaction.put(columns::STATE, &key.0[..], &val); - } else if rc < 0 && !self.archive { - transaction.delete(columns::STATE, &key.0[..]); + changeset.inserted.push((key.0.into(), val.to_vec())); + } else if rc < 0 { + changeset.deleted.push(key.0.into()); + } + } + let number_u64 = number.as_().into(); + let commit = self.storage.state_db.insert_block(&hash, number_u64, &pending_block.header.parent_hash(), changeset); + apply_state_commit(&mut transaction, commit); + + //finalize an older block + if number_u64 > self.finalization_window { + let finalizing_hash = if self.finalization_window == 0 { + Some(hash) + } else { + let finalizing = number_u64 - self.finalization_window; + if finalizing > self.storage.state_db.best_finalized() { + self.blockchain.hash(As::sa(finalizing))? + } else { + None + } + }; + if let Some(finalizing_hash) = finalizing_hash { + trace!("Finalizing block #{} ({:?})", number_u64 - self.finalization_window, finalizing_hash); + let commit = self.storage.state_db.finalize_block(&finalizing_hash); + apply_state_commit(&mut transaction, commit); } } - debug!("DB Commit {:?} ({})", hash, number); - self.db.write(transaction).map_err(db_err)?; + + debug!("DB Commit {:?} ({}), best = {}", hash, number, pending_block.is_best); + self.storage.db.write(transaction).map_err(db_err)?; self.blockchain.update_meta(hash, number, pending_block.is_best); } Ok(()) } + fn revert(&self, n: NumberFor) -> Result, client::error::Error> { + use client::blockchain::HeaderBackend; + let mut best = self.blockchain.info()?.best_number; + for c in 0 .. n.as_() { + if best == As::sa(0) { + return Ok(As::sa(c)) + } + let mut transaction = DBTransaction::new(); + match self.storage.state_db.revert_one() { + Some(commit) => { + apply_state_commit(&mut transaction, commit); + let removed = self.blockchain.hash(best)?.ok_or_else( + || client::error::ErrorKind::UnknownBlock( + format!("Error reverting to {}. Block hash not found.", best)))?; + best -= As::sa(1); + let key = number_to_db_key(best.clone()); + let hash = self.blockchain.hash(best)?.ok_or_else( + || client::error::ErrorKind::UnknownBlock( + format!("Error reverting to {}. Block hash not found.", best)))?; + transaction.put(columns::META, meta_keys::BEST_BLOCK, &key); + transaction.delete(columns::BLOCK_INDEX, removed.as_ref()); + self.storage.db.write(transaction).map_err(db_err)?; + self.blockchain.update_meta(hash, best, true); + } + None => return Ok(As::sa(c)) + } + } + Ok(n) + } + fn blockchain(&self) -> &BlockchainDb { &self.blockchain } fn state_at(&self, block: BlockId) -> Result { - use client::blockchain::Backend as BcBackend; + use client::blockchain::HeaderBackend as BcHeaderBackend; // special case for genesis initialization match block { BlockId::Hash(h) if h == Default::default() => - return Ok(DbState::with_kvdb_for_genesis(self.db.clone(), ::columns::STATE)), + return Ok(DbState::with_storage_for_genesis(self.storage.clone())), _ => {} } self.blockchain.header(block).and_then(|maybe_hdr| maybe_hdr.map(|hdr| { - let root: [u8; 32] = hdr.state_root().clone().into(); - DbState::with_kvdb(self.db.clone(), ::columns::STATE, root.into()) + let root: TrieH256 = TrieH256::from_slice(hdr.state_root().as_ref()); + DbState::with_storage(self.storage.clone(), root) }).ok_or_else(|| client::error::ErrorKind::UnknownBlock(format!("{:?}", block)).into())) } } -impl client::backend::LocalBackend for Backend where - ::Number: As, - Block::Hash: Into<[u8; 32]>, // TODO: remove when patricia_trie generic. +impl client::backend::LocalBackend for Backend {} #[cfg(test)] @@ -417,7 +462,7 @@ mod tests { use super::*; use client::backend::Backend as BTrait; use client::backend::BlockImportOperation as Op; - use client::blockchain::Backend as BCTrait; + use client::blockchain::HeaderBackend as BlockchainHeaderBackend; use runtime_primitives::testing::{Header, Block as RawBlock}; type Block = RawBlock; @@ -438,7 +483,11 @@ mod tests { let mut op = db.begin_operation(id).unwrap(); let header = Header { number: i, - parent_hash: Default::default(), + parent_hash: if i == 0 { + Default::default() + } else { + db.blockchain.hash(i - 1).unwrap().unwrap() + }, state_root: Default::default(), digest: Default::default(), extrinsics_root: Default::default(), @@ -538,10 +587,10 @@ mod tests { #[test] fn delete_only_when_negative_rc() { let key; - let db = Backend::::new_test(); + let backend = Backend::::new_test(); - { - let mut op = db.begin_operation(BlockId::Hash(Default::default())).unwrap(); + let hash = { + let mut op = backend.begin_operation(BlockId::Hash(Default::default())).unwrap(); let mut header = Header { number: 0, parent_hash: Default::default(), @@ -557,6 +606,7 @@ mod tests { .cloned() .map(|(x, y)| (x, Some(y))) ).0.into(); + let hash = header.hash(); op.reset_storage(storage.iter().cloned()).unwrap(); @@ -568,16 +618,17 @@ mod tests { true ).unwrap(); - db.commit_operation(op).unwrap(); + backend.commit_operation(op).unwrap(); - assert_eq!(db.db.get(::columns::STATE, &key.0[..]).unwrap().unwrap(), &b"hello"[..]); - } + assert_eq!(backend.storage.db.get(::columns::STATE, &key.0[..]).unwrap().unwrap(), &b"hello"[..]); + hash + }; - { - let mut op = db.begin_operation(BlockId::Number(0)).unwrap(); + let hash = { + let mut op = backend.begin_operation(BlockId::Number(0)).unwrap(); let mut header = Header { number: 1, - parent_hash: Default::default(), + parent_hash: hash, state_root: Default::default(), digest: Default::default(), extrinsics_root: Default::default(), @@ -590,6 +641,7 @@ mod tests { .cloned() .map(|(x, y)| (x, Some(y))) ).0.into(); + let hash = header.hash(); op.updates.insert(b"hello"); op.updates.remove(&key); @@ -600,16 +652,17 @@ mod tests { true ).unwrap(); - db.commit_operation(op).unwrap(); + backend.commit_operation(op).unwrap(); - assert_eq!(db.db.get(::columns::STATE, &key.0[..]).unwrap().unwrap(), &b"hello"[..]); - } + assert_eq!(backend.storage.db.get(::columns::STATE, &key.0[..]).unwrap().unwrap(), &b"hello"[..]); + hash + }; { - let mut op = db.begin_operation(BlockId::Number(1)).unwrap(); + let mut op = backend.begin_operation(BlockId::Number(1)).unwrap(); let mut header = Header { - number: 1, - parent_hash: Default::default(), + number: 2, + parent_hash: hash, state_root: Default::default(), digest: Default::default(), extrinsics_root: Default::default(), @@ -631,9 +684,9 @@ mod tests { true ).unwrap(); - db.commit_operation(op).unwrap(); + backend.commit_operation(op).unwrap(); - assert!(db.db.get(::columns::STATE, &key.0[..]).unwrap().is_none()); + assert!(backend.storage.db.get(::columns::STATE, &key.0[..]).unwrap().is_none()); } } } diff --git a/substrate/client/db/src/light.rs b/substrate/client/db/src/light.rs new file mode 100644 index 0000000000000..a7e74a75711e3 --- /dev/null +++ b/substrate/client/db/src/light.rs @@ -0,0 +1,292 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! RocksDB-based light client blockchain storage. + +use std::sync::Arc; +use parking_lot::RwLock; + +use kvdb::{KeyValueDB, DBTransaction}; + +use client::blockchain::{BlockStatus, Cache as BlockchainCache, + HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo}; +use client::error::{ErrorKind as ClientErrorKind, Result as ClientResult}; +use client::light::blockchain::Storage as LightBlockchainStorage; +use codec::{Decode, Encode}; +use primitives::AuthorityId; +use runtime_primitives::generic::BlockId; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hash, HashFor, Zero, As}; +use cache::DbCache; +use utils::{meta_keys, Meta, db_err, number_to_db_key, open_database, read_db, read_id, read_meta}; +use DatabaseSettings; + +pub(crate) mod columns { + pub const META: Option = ::utils::COLUMN_META; + pub const BLOCK_INDEX: Option = Some(1); + pub const HEADER: Option = Some(2); + pub const AUTHORITIES: Option = Some(3); +} + +/// Keep authorities for last 'AUTHORITIES_ENTRIES_TO_KEEP' blocks. +pub(crate) const AUTHORITIES_ENTRIES_TO_KEEP: u64 = 2048; + +/// Light blockchain storage. Stores most recent headers + CHTs for older headers. +pub struct LightStorage { + db: Arc, + meta: RwLock::Header as HeaderT>::Number, Block::Hash>>, + cache: DbCache, +} + +#[derive(Clone, PartialEq, Debug)] +struct BestAuthorities { + /// first block, when this set became actual + valid_from: N, + /// None means that we do not know the set starting from `valid_from` block + authorities: Option>, +} + +impl LightStorage + where + Block: BlockT, +{ + /// Create new storage with given settings. + pub fn new(config: DatabaseSettings) -> ClientResult { + let db = open_database(&config, "light")?; + + Self::from_kvdb(db as Arc<_>) + } + + #[cfg(test)] + pub(crate) fn new_test() -> Self { + use utils::NUM_COLUMNS; + + let db = Arc::new(::kvdb_memorydb::create(NUM_COLUMNS)); + + Self::from_kvdb(db as Arc<_>).expect("failed to create test-db") + } + + fn from_kvdb(db: Arc) -> ClientResult { + let cache = DbCache::new(db.clone(), columns::BLOCK_INDEX, columns::AUTHORITIES)?; + let meta = RwLock::new(read_meta::(&*db, columns::HEADER)?); + + Ok(LightStorage { + db, + meta, + cache, + }) + } + + #[cfg(test)] + pub(crate) fn db(&self) -> &Arc { + &self.db + } + + #[cfg(test)] + pub(crate) fn cache(&self) -> &DbCache { + &self.cache + } + + fn update_meta(&self, hash: Block::Hash, number: <::Header as HeaderT>::Number, is_best: bool) { + if is_best { + let mut meta = self.meta.write(); + if number == <::Header as HeaderT>::Number::zero() { + meta.genesis_hash = hash; + } + + meta.best_number = number; + meta.best_hash = hash; + } + } +} + +impl BlockchainHeaderBackend for LightStorage + where + Block: BlockT, +{ + fn header(&self, id: BlockId) -> ClientResult> { + match read_db(&*self.db, columns::BLOCK_INDEX, columns::HEADER, id)? { + Some(header) => match Block::Header::decode(&mut &header[..]) { + Some(header) => Ok(Some(header)), + None => return Err(ClientErrorKind::Backend("Error decoding header".into()).into()), + } + None => Ok(None), + } + } + + fn info(&self) -> ClientResult> { + let meta = self.meta.read(); + Ok(BlockchainInfo { + best_hash: meta.best_hash, + best_number: meta.best_number, + genesis_hash: meta.genesis_hash, + }) + } + + fn status(&self, id: BlockId) -> ClientResult { + let exists = match id { + BlockId::Hash(_) => read_id(&*self.db, columns::BLOCK_INDEX, id)?.is_some(), + BlockId::Number(n) => n <= self.meta.read().best_number, + }; + match exists { + true => Ok(BlockStatus::InChain), + false => Ok(BlockStatus::Unknown), + } + } + + fn hash(&self, number: <::Header as HeaderT>::Number) -> ClientResult> { + read_db::(&*self.db, columns::BLOCK_INDEX, columns::HEADER, BlockId::Number(number)).map(|x| + x.map(|raw| HashFor::::hash(&raw[..])).map(Into::into) + ) + } +} + +impl LightBlockchainStorage for LightStorage + where + Block: BlockT, +{ + fn import_header(&self, is_new_best: bool, header: Block::Header, authorities: Option>) -> ClientResult<()> { + let mut transaction = DBTransaction::new(); + + let hash = header.hash(); + let number = *header.number(); + let key = number_to_db_key(number); + + transaction.put(columns::HEADER, &key, &header.encode()); + transaction.put(columns::BLOCK_INDEX, hash.as_ref(), &key); + + let best_authorities = if is_new_best { + transaction.put(columns::META, meta_keys::BEST_BLOCK, &key); + + // cache authorities for previous block + let number: u64 = number.as_(); + let previous_number = number.checked_sub(1); + let best_authorities = previous_number + .and_then(|previous_number| self.cache.authorities_at_cache() + .commit_best_entry(&mut transaction, As::sa(previous_number), authorities)); + + // prune authorities from 'ancient' blocks + if let Some(ancient_number) = number.checked_sub(AUTHORITIES_ENTRIES_TO_KEEP) { + self.cache.authorities_at_cache().prune_entries(&mut transaction, As::sa(ancient_number))?; + } + + best_authorities + } else { + None + }; + + debug!("Light DB Commit {:?} ({})", hash, number); + self.db.write(transaction).map_err(db_err)?; + self.update_meta(hash, number, is_new_best); + if let Some(best_authorities) = best_authorities { + self.cache.authorities_at_cache().update_best_entry(Some(best_authorities)); + } + + Ok(()) + } + + fn cache(&self) -> Option<&BlockchainCache> { + Some(&self.cache) + } +} + +#[cfg(test)] +pub(crate) mod tests { + use runtime_primitives::testing::{H256 as Hash, Header, Block as RawBlock}; + use super::*; + + type Block = RawBlock; + + pub fn insert_block( + db: &LightStorage, + parent: &Hash, + number: u64, + authorities: Option> + ) -> Hash { + let header = Header { + number: number.into(), + parent_hash: *parent, + state_root: Default::default(), + digest: Default::default(), + extrinsics_root: Default::default(), + }; + + let hash = header.hash(); + db.import_header(true, header, authorities).unwrap(); + hash + } + + #[test] + fn returns_known_header() { + let db = LightStorage::new_test(); + let known_hash = insert_block(&db, &Default::default(), 0, None); + let header_by_hash = db.header(BlockId::Hash(known_hash)).unwrap().unwrap(); + let header_by_number = db.header(BlockId::Number(0)).unwrap().unwrap(); + assert_eq!(header_by_hash, header_by_number); + } + + #[test] + fn does_not_return_unknown_header() { + let db = LightStorage::::new_test(); + assert!(db.header(BlockId::Hash(1.into())).unwrap().is_none()); + assert!(db.header(BlockId::Number(0)).unwrap().is_none()); + } + + #[test] + fn returns_info() { + let db = LightStorage::new_test(); + let genesis_hash = insert_block(&db, &Default::default(), 0, None); + let info = db.info().unwrap(); + assert_eq!(info.best_hash, genesis_hash); + assert_eq!(info.best_number, 0); + assert_eq!(info.genesis_hash, genesis_hash); + let best_hash = insert_block(&db, &genesis_hash, 1, None); + let info = db.info().unwrap(); + assert_eq!(info.best_hash, best_hash); + assert_eq!(info.best_number, 1); + assert_eq!(info.genesis_hash, genesis_hash); + } + + #[test] + fn returns_block_status() { + let db = LightStorage::new_test(); + let genesis_hash = insert_block(&db, &Default::default(), 0, None); + assert_eq!(db.status(BlockId::Hash(genesis_hash)).unwrap(), BlockStatus::InChain); + assert_eq!(db.status(BlockId::Number(0)).unwrap(), BlockStatus::InChain); + assert_eq!(db.status(BlockId::Hash(1.into())).unwrap(), BlockStatus::Unknown); + assert_eq!(db.status(BlockId::Number(1)).unwrap(), BlockStatus::Unknown); + } + + #[test] + fn returns_block_hash() { + let db = LightStorage::new_test(); + let genesis_hash = insert_block(&db, &Default::default(), 0, None); + assert_eq!(db.hash(0).unwrap(), Some(genesis_hash)); + assert_eq!(db.hash(1).unwrap(), None); + } + + #[test] + fn import_header_works() { + let db = LightStorage::new_test(); + + let genesis_hash = insert_block(&db, &Default::default(), 0, None); + assert_eq!(db.db.iter(columns::HEADER).count(), 1); + assert_eq!(db.db.iter(columns::BLOCK_INDEX).count(), 1); + + let _ = insert_block(&db, &genesis_hash, 1, None); + assert_eq!(db.db.iter(columns::HEADER).count(), 2); + assert_eq!(db.db.iter(columns::BLOCK_INDEX).count(), 2); + } +} diff --git a/substrate/client/db/src/utils.rs b/substrate/client/db/src/utils.rs new file mode 100644 index 0000000000000..75c86ae06e151 --- /dev/null +++ b/substrate/client/db/src/utils.rs @@ -0,0 +1,178 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Db-based backend utility structures and functions, used by both +//! full and light storages. + +use std::sync::Arc; + +use kvdb::{self, KeyValueDB, DBTransaction}; +use kvdb_rocksdb::{Database, DatabaseConfig}; + +use client; +use codec::Decode; +use hashdb::DBValue; +use runtime_primitives::generic::BlockId; +use runtime_primitives::traits::{As, Block as BlockT, Header as HeaderT, Hash, HashFor, Zero}; +use DatabaseSettings; + +/// Number of columns in the db. Must be the same for both full && light dbs. +/// Otherwise RocksDb will fail to open database && check its type. +pub const NUM_COLUMNS: u32 = 7; +/// Meta column. Thes set of keys in the column is shared by full && light storages. +pub const COLUMN_META: Option = Some(0); + +/// Keys of entries in COLUMN_META. +pub mod meta_keys { + /// Type of storage (full or light). + pub const TYPE: &[u8; 4] = b"type"; + /// Best block key. + pub const BEST_BLOCK: &[u8; 4] = b"best"; + /// Best authorities block key. + pub const BEST_AUTHORITIES: &[u8; 4] = b"auth"; +} + +/// Database metadata. +pub struct Meta { + /// Hash of the best known block. + pub best_hash: H, + /// Number of the best known block. + pub best_number: N, + /// Hash of the genesis block. + pub genesis_hash: H, +} + +/// Type of block key in the database (LE block number). +pub type BlockKey = [u8; 4]; + +/// Convert block number into key (LE representation). +pub fn number_to_db_key(n: N) -> BlockKey where N: As { + let n: u64 = n.as_(); + assert!(n & 0xffffffff00000000 == 0); + + [ + (n >> 24) as u8, + ((n >> 16) & 0xff) as u8, + ((n >> 8) & 0xff) as u8, + (n & 0xff) as u8 + ] +} + +/// Convert block key into block number. +pub fn db_key_to_number(key: &[u8]) -> client::error::Result where N: As { + match key.len() { + 4 => Ok((key[0] as u64) << 24 + | (key[1] as u64) << 16 + | (key[2] as u64) << 8 + | (key[3] as u64)).map(As::sa), + _ => Err(client::error::ErrorKind::Backend("Invalid block key".into()).into()), + } +} + +/// Maps database error to client error +pub fn db_err(err: kvdb::Error) -> client::error::Error { + use std::error::Error; + match err.kind() { + &kvdb::ErrorKind::Io(ref err) => client::error::ErrorKind::Backend(err.description().into()).into(), + &kvdb::ErrorKind::Msg(ref m) => client::error::ErrorKind::Backend(m.clone()).into(), + _ => client::error::ErrorKind::Backend("Unknown backend error".into()).into(), + } +} + +/// Open RocksDB database. +pub fn open_database(config: &DatabaseSettings, db_type: &str) -> client::error::Result> { + let mut db_config = DatabaseConfig::with_columns(Some(NUM_COLUMNS)); + db_config.memory_budget = config.cache_size; + db_config.wal = true; + let path = config.path.to_str().ok_or_else(|| client::error::ErrorKind::Backend("Invalid database path".into()))?; + let db = Database::open(&db_config, &path).map_err(db_err)?; + + // check database type + match db.get(COLUMN_META, meta_keys::TYPE).map_err(db_err)? { + Some(stored_type) => { + if db_type.as_bytes() != &*stored_type { + return Err(client::error::ErrorKind::Backend( + format!("Unexpected database type. Expected: {}", db_type)).into()); + } + }, + None => { + let mut transaction = DBTransaction::new(); + transaction.put(COLUMN_META, meta_keys::TYPE, db_type.as_bytes()); + db.write(transaction).map_err(db_err)?; + }, + } + + Ok(Arc::new(db)) +} + +/// Convert block id to block key, reading number from db if required. +pub fn read_id(db: &KeyValueDB, col_index: Option, id: BlockId) -> Result, client::error::Error> + where + Block: BlockT, +{ + match id { + BlockId::Hash(h) => db.get(col_index, h.as_ref()) + .map(|v| v.map(|v| { + let mut key: [u8; 4] = [0; 4]; + key.copy_from_slice(&v); + key + })).map_err(db_err), + BlockId::Number(n) => Ok(Some(number_to_db_key(n))), + } +} + +/// Read database column entry for the given block. +pub fn read_db(db: &KeyValueDB, col_index: Option, col: Option, id: BlockId) -> client::error::Result> + where + Block: BlockT, +{ + read_id(db, col_index, id).and_then(|key| match key { + Some(key) => db.get(col, &key).map_err(db_err), + None => Ok(None), + }) +} + +/// Read meta from the database. +pub fn read_meta(db: &KeyValueDB, col_header: Option) -> Result::Header as HeaderT>::Number, Block::Hash>, client::error::Error> + where + Block: BlockT, +{ + let genesis_number = <::Header as HeaderT>::Number::zero(); + let (best_hash, best_number) = if let Some(Some(header)) = db.get(COLUMN_META, meta_keys::BEST_BLOCK).and_then(|id| + match id { + Some(id) => db.get(col_header, &id).map(|h| h.map(|b| Block::Header::decode(&mut &b[..]))), + None => Ok(None), + }).map_err(db_err)? + { + let hash = header.hash(); + debug!("DB Opened blockchain db, best {:?} ({})", hash, header.number()); + (hash, *header.number()) + } else { + (Default::default(), genesis_number) + }; + + let genesis_hash = db.get(col_header, &number_to_db_key(genesis_number)) + .map_err(db_err)? + .map(|raw| HashFor::::hash(&raw[..])) + .unwrap_or_default() + .into(); + + Ok(Meta { + best_hash, + best_number, + genesis_hash, + }) +} diff --git a/substrate/client/src/backend.rs b/substrate/client/src/backend.rs index 64f4a1d57f59e..0686e1e47aadd 100644 --- a/substrate/client/src/backend.rs +++ b/substrate/client/src/backend.rs @@ -18,8 +18,9 @@ use state_machine::backend::Backend as StateBackend; use error; +use primitives::AuthorityId; use runtime_primitives::bft::Justification; -use runtime_primitives::traits::Block as BlockT; +use runtime_primitives::traits::{Block as BlockT, NumberFor}; use runtime_primitives::generic::BlockId; /// Block insertion operation. Keeps hold if the inserted block state and data. @@ -38,6 +39,9 @@ pub trait BlockImportOperation { is_new_best: bool ) -> error::Result<()>; + /// Append authorities set to the transaction. This is a set of parent block (set which + /// has been used to check justification of this block). + fn update_authorities(&mut self, authorities: Vec); /// Inject storage data into the database. fn update_storage(&mut self, update: ::Transaction) -> error::Result<()>; /// Inject storage data into the database replacing any existing data. @@ -69,6 +73,9 @@ pub trait Backend: Send + Sync { fn blockchain(&self) -> &Self::Blockchain; /// Returns state backend with post-state of given block. fn state_at(&self, block: BlockId) -> error::Result; + /// Attempts to revert the chain by `n` blocks. Returns the number of blocks that were + /// successfully reverted. + fn revert(&self, n: NumberFor) -> error::Result>; } /// Mark for all Backend implementations, that are making use of state data, stored locally. diff --git a/substrate/client/src/block_builder.rs b/substrate/client/src/block_builder.rs index 5443759f170b2..bc5c29a37f86d 100644 --- a/substrate/client/src/block_builder.rs +++ b/substrate/client/src/block_builder.rs @@ -17,18 +17,18 @@ //! Utility struct to build a block. use std::vec::Vec; -use codec::Slicable; -use state_machine; -use runtime_primitives::traits::{Header as HeaderT, Hashing as HashingT, Block as BlockT, One, HashingFor}; +use codec::{Decode, Encode}; +use state_machine::{self, native_when_possible}; +use runtime_primitives::traits::{Header as HeaderT, Hash, Block as BlockT, One, HashFor}; use runtime_primitives::generic::BlockId; use {backend, error, Client, CallExecutor}; +use runtime_primitives::{ApplyResult, ApplyOutcome}; /// Utility for building new (valid) blocks from a stream of extrinsics. pub struct BlockBuilder where B: backend::Backend, E: CallExecutor + Clone, Block: BlockT, - error::Error: From<<>::State as state_machine::backend::Backend>::Error>, { header: ::Header, extrinsics: Vec<::Extrinsic>, @@ -41,7 +41,6 @@ impl BlockBuilder where B: backend::Backend, E: CallExecutor + Clone, Block: BlockT, - error::Error: From<<>::State as state_machine::backend::Backend>::Error>, { /// Create a new instance of builder from the given client, building on the latest block. pub fn new(client: &Client) -> error::Result { @@ -69,7 +68,8 @@ impl BlockBuilder where Default::default() ); - executor.call_at_state(&state, &mut changes, "initialise_block", &header.encode())?; + executor.call_at_state(&state, &mut changes, "initialise_block", &header.encode(), native_when_possible())?; + changes.commit_prospective(); Ok(BlockBuilder { header, @@ -84,10 +84,23 @@ impl BlockBuilder where /// can be validly executed (by executing it); if it is invalid, it'll be returned along with /// the error. Otherwise, it will return a mutable reference to self (in order to chain). pub fn push(&mut self, xt: ::Extrinsic) -> error::Result<()> { - match self.executor.call_at_state(&self.state, &mut self.changes, "apply_extrinsic", &xt.encode()) { - Ok(_) => { - self.extrinsics.push(xt); - Ok(()) + match self.executor.call_at_state(&self.state, &mut self.changes, "apply_extrinsic", &xt.encode(), native_when_possible()) { + Ok((result, _)) => { + match ApplyResult::decode(&mut result.as_slice()) { + Some(Ok(ApplyOutcome::Success)) | Some(Ok(ApplyOutcome::Fail)) => { + self.extrinsics.push(xt); + self.changes.commit_prospective(); + Ok(()) + } + Some(Err(e)) => { + self.changes.discard_prospective(); + Err(error::ErrorKind::ApplyExtinsicFailed(e).into()) + } + None => { + self.changes.discard_prospective(); + Err(error::ErrorKind::CallResultDecode("apply_extrinsic").into()) + } + } } Err(e) => { self.changes.discard_prospective(); @@ -103,13 +116,14 @@ impl BlockBuilder where &mut self.changes, "finalise_block", &[], + native_when_possible(), )?; - self.header = <::Header as Slicable>::decode(&mut &output[..]) + self.header = <::Header as Decode>::decode(&mut &output[..]) .expect("Header came straight out of runtime so must be valid"); debug_assert_eq!( self.header.extrinsics_root().clone(), - HashingFor::::ordered_trie_root(self.extrinsics.iter().map(Slicable::encode)), + HashFor::::ordered_trie_root(self.extrinsics.iter().map(Encode::encode)), ); Ok(::new(self.header, self.extrinsics)) diff --git a/substrate/client/src/blockchain.rs b/substrate/client/src/blockchain.rs index 73c7107b30ee2..333bc8f72e156 100644 --- a/substrate/client/src/blockchain.rs +++ b/substrate/client/src/blockchain.rs @@ -16,20 +16,17 @@ //! Polkadot blockchain trait +use primitives::AuthorityId; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; use runtime_primitives::generic::BlockId; use runtime_primitives::bft::Justification; use error::Result; -/// Blockchain database backend. Does not perform any validation. -pub trait Backend: Send + Sync { +/// Blockchain database header backend. Does not perform any validation. +pub trait HeaderBackend: Send + Sync { /// Get block header. Returns `None` if block is not found. fn header(&self, id: BlockId) -> Result::Header>>; - /// Get block body. Returns `None` if block is not found. - fn body(&self, id: BlockId) -> Result::Extrinsic>>>; - /// Get block justification. Returns `None` if justification does not exist. - fn justification(&self, id: BlockId) -> Result>>; /// Get blockchain info. fn info(&self) -> Result>; /// Get block status. @@ -38,6 +35,23 @@ pub trait Backend: Send + Sync { fn hash(&self, number: <::Header as HeaderT>::Number) -> Result::Header as HeaderT>::Hash>>; } +/// Blockchain database backend. Does not perform any validation. +pub trait Backend: HeaderBackend { + /// Get block body. Returns `None` if block is not found. + fn body(&self, id: BlockId) -> Result::Extrinsic>>>; + /// Get block justification. Returns `None` if justification does not exist. + fn justification(&self, id: BlockId) -> Result>>; + + /// Returns data cache reference, if it is enabled on this backend. + fn cache(&self) -> Option<&Cache>; +} + +/// Blockchain optional data cache. +pub trait Cache: Send + Sync { + /// Returns the set of authorities, that was active at given block or None if there's no entry in the cache. + fn authorities_at(&self, block: BlockId) -> Option>; +} + /// Block import outcome pub enum ImportResult { /// Imported successfully. diff --git a/substrate/client/src/call_executor.rs b/substrate/client/src/call_executor.rs index cd67ec4d97722..ac561b5a549a3 100644 --- a/substrate/client/src/call_executor.rs +++ b/substrate/client/src/call_executor.rs @@ -15,18 +15,18 @@ // along with Polkadot. If not, see . use std::sync::Arc; -use futures::{IntoFuture, Future}; use runtime_primitives::generic::BlockId; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; -use state_machine::{self, OverlayedChanges, Backend as StateBackend, CodeExecutor}; +use runtime_primitives::traits::Block as BlockT; +use state_machine::{self, OverlayedChanges, Ext, + CodeExecutor, ExecutionManager, native_when_possible}; +use runtime_io::Externalities; +use executor::{RuntimeVersion, RuntimeInfo}; use backend; -use blockchain::Backend as ChainBackend; use error; -use light::{Fetcher, RemoteCallRequest}; /// Information regarding the result of a call. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct CallResult { /// The data that was returned from the call. pub return_data: Vec, @@ -42,17 +42,43 @@ pub trait CallExecutor { /// Execute a call to a contract on top of state in a block of given hash. /// /// No changes are made. - fn call(&self, id: &BlockId, method: &str, call_data: &[u8]) -> Result; + fn call(&self, + id: &BlockId, + method: &str, + call_data: &[u8], + ) -> Result; + + /// Extract RuntimeVersion of given block + /// + /// No changes are made. + fn runtime_version(&self, id: &BlockId) -> Result; /// Execute a call to a contract on top of given state. /// /// No changes are made. - fn call_at_state(&self, state: &S, overlay: &mut OverlayedChanges, method: &str, call_data: &[u8]) -> Result<(Vec, S::Transaction), error::Error>; + fn call_at_state< + S: state_machine::Backend, + F: FnOnce(Result, Self::Error>, Result, Self::Error>) -> Result, Self::Error>, + >(&self, + state: &S, + overlay: &mut OverlayedChanges, + method: &str, + call_data: &[u8], + manager: ExecutionManager + ) -> Result<(Vec, S::Transaction), error::Error>; /// Execute a call to a contract on top of given state, gathering execution proof. /// /// No changes are made. - fn prove_at_state(&self, state: S, overlay: &mut OverlayedChanges, method: &str, call_data: &[u8]) -> Result<(Vec, Vec>), error::Error>; + fn prove_at_state(&self, + state: S, + overlay: &mut OverlayedChanges, + method: &str, + call_data: &[u8] + ) -> Result<(Vec, Vec>), error::Error>; + + /// Get runtime version if supported. + fn native_runtime_version(&self) -> Option; } /// Call executor that executes methods locally, querying all required @@ -62,13 +88,6 @@ pub struct LocalCallExecutor { executor: E, } -/// Call executor that executes methods on remote node, querying execution proof -/// and checking proof by re-executing locally. -pub struct RemoteCallExecutor { - backend: Arc, - fetcher: Arc, -} - impl LocalCallExecutor { /// Creates new instance of local call executor. pub fn new(backend: Arc, executor: E) -> Self { @@ -88,30 +107,65 @@ impl Clone for LocalCallExecutor where E: Clone { impl CallExecutor for LocalCallExecutor where B: backend::LocalBackend, - E: CodeExecutor, + E: CodeExecutor + RuntimeInfo, Block: BlockT, - error::Error: From<<>::State as StateBackend>::Error>, { type Error = E::Error; - fn call(&self, id: &BlockId, method: &str, call_data: &[u8]) -> error::Result { + fn call(&self, + id: &BlockId, + method: &str, + call_data: &[u8], + ) -> error::Result { let mut changes = OverlayedChanges::default(); - let (return_data, _) = self.call_at_state(&self.backend.state_at(*id)?, &mut changes, method, call_data)?; + let (return_data, _) = self.call_at_state( + &self.backend.state_at(*id)?, + &mut changes, + method, + call_data, + native_when_possible(), + )?; Ok(CallResult{ return_data, changes }) } - fn call_at_state(&self, state: &S, changes: &mut OverlayedChanges, method: &str, call_data: &[u8]) -> error::Result<(Vec, S::Transaction)> { - state_machine::execute( + fn runtime_version(&self, id: &BlockId) -> error::Result { + let mut overlay = OverlayedChanges::default(); + let state = self.backend.state_at(*id)?; + let mut externalities = Ext::new(&mut overlay, &state); + let code = externalities.storage(b":code").ok_or(error::ErrorKind::VersionInvalid)? + .to_vec(); + + self.executor.runtime_version(&mut externalities, &code) + .ok_or(error::ErrorKind::VersionInvalid.into()) + } + + fn call_at_state< + S: state_machine::Backend, + F: FnOnce(Result, Self::Error>, Result, Self::Error>) -> Result, Self::Error>, + >(&self, + state: &S, + changes: &mut OverlayedChanges, + method: &str, + call_data: &[u8], + manager: ExecutionManager, + ) -> error::Result<(Vec, S::Transaction)> { + state_machine::execute_using_consensus_failure_handler( state, changes, &self.executor, method, call_data, + manager, ).map_err(Into::into) } - fn prove_at_state(&self, state: S, changes: &mut OverlayedChanges, method: &str, call_data: &[u8]) -> Result<(Vec, Vec>), error::Error> { - state_machine::prove( + fn prove_at_state(&self, + state: S, + changes: &mut OverlayedChanges, + method: &str, + call_data: &[u8] + ) -> Result<(Vec, Vec>), error::Error> { + state_machine::prove_execution( state, changes, &self.executor, @@ -121,105 +175,8 @@ impl CallExecutor for LocalCallExecutor .map(|(result, proof, _)| (result, proof)) .map_err(Into::into) } -} - -impl RemoteCallExecutor { - /// Creates new instance of remote call executor. - pub fn new(backend: Arc, fetcher: Arc) -> Self { - RemoteCallExecutor { backend, fetcher } - } -} - -impl CallExecutor for RemoteCallExecutor - where - B: backend::RemoteBackend, - F: Fetcher, - Block: BlockT, - error::Error: From<<>::State as StateBackend>::Error>, -{ - type Error = error::Error; - - fn call(&self, id: &BlockId, method: &str, call_data: &[u8]) -> error::Result { - let block_hash = match *id { - BlockId::Hash(hash) => hash, - BlockId::Number(number) => self.backend.blockchain().hash(number)? - .ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{}", number)))?, - }; - - self.fetcher.remote_call(RemoteCallRequest { - block: block_hash, - method: method.into(), - call_data: call_data.to_vec(), - }).into_future().wait() - } - - fn call_at_state(&self, _state: &S, _changes: &mut OverlayedChanges, _method: &str, _call_data: &[u8]) -> error::Result<(Vec, S::Transaction)> { - Err(error::ErrorKind::NotAvailableOnLightClient.into()) - } - - fn prove_at_state(&self, _state: S, _changes: &mut OverlayedChanges, _method: &str, _call_data: &[u8]) -> Result<(Vec, Vec>), error::Error> { - Err(error::ErrorKind::NotAvailableOnLightClient.into()) - } -} - -/// Check remote execution proof using given backend. -pub fn check_execution_proof(backend: &B, executor: &E, request: &RemoteCallRequest, remote_proof: Vec>) -> Result - where - B: backend::RemoteBackend, - E: CodeExecutor, - Block: BlockT, - <::Header as HeaderT>::Hash: Into<[u8; 32]>, // TODO: remove when patricia_trie generic. - error::Error: From<<>::State as StateBackend>::Error>, -{ - let local_header = backend.blockchain().header(BlockId::Hash(request.block))?; - let local_header = local_header.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{}", request.block)))?; - let local_state_root = local_header.state_root().clone(); - do_check_execution_proof(local_state_root, executor, request, remote_proof) -} - -/// Check remote execution proof using given state root. -fn do_check_execution_proof(local_state_root: H, executor: &E, request: &RemoteCallRequest, remote_proof: Vec>) -> Result - where - E: CodeExecutor, - H: Into<[u8; 32]>, // TODO: remove when patricia_trie generic. -{ - let mut changes = OverlayedChanges::default(); - let (local_result, _) = state_machine::proof_check( - local_state_root.into(), - remote_proof, - &mut changes, - executor, - &request.method, - &request.call_data)?; - - Ok(CallResult { return_data: local_result, changes }) -} -#[cfg(test)] -mod tests { - use runtime_primitives::generic::BlockId; - use state_machine::Backend; - use test_client; - use light::RemoteCallRequest; - use super::do_check_execution_proof; - - #[test] - fn execution_proof_is_generated_and_checked() { - // prepare remote client - let remote_client = test_client::new(); - let remote_block_id = BlockId::Number(0); - let remote_block_storage_root = remote_client.state_at(&remote_block_id) - .unwrap().storage_root(::std::iter::empty()).0; - - // 'fetch' execution proof from remote node - let remote_execution_proof = remote_client.execution_proof(&remote_block_id, "authorities", &[]).unwrap().1; - - // check remote execution proof locally - let local_executor = test_client::NativeExecutor::new(); - do_check_execution_proof(remote_block_storage_root, &local_executor, &RemoteCallRequest { - block: Default::default(), - method: "authorities".into(), - call_data: vec![], - }, remote_execution_proof).unwrap(); + fn native_runtime_version(&self) -> Option { + ::NATIVE_VERSION } } diff --git a/substrate/client/src/client.rs b/substrate/client/src/client.rs index 6604b3225dbee..781f3aaab0147 100644 --- a/substrate/client/src/client.rs +++ b/substrate/client/src/client.rs @@ -20,28 +20,33 @@ use std::sync::Arc; use futures::sync::mpsc; use parking_lot::{Mutex, RwLock}; use primitives::AuthorityId; -use runtime_primitives::{bft::Justification, generic::BlockId}; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, One}; +use runtime_primitives::{bft::Justification, generic::{BlockId, SignedBlock, Block as RuntimeBlock}}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, One, As, NumberFor}; use runtime_primitives::BuildStorage; use primitives::storage::{StorageKey, StorageData}; -use codec::Slicable; -use state_machine::{self, Ext, OverlayedChanges, Backend as StateBackend, CodeExecutor}; +use codec::Decode; +use state_machine::{ + Ext, OverlayedChanges, Backend as StateBackend, CodeExecutor, + ExecutionStrategy, ExecutionManager, prove_read +}; use backend::{self, BlockImportOperation}; -use blockchain::{self, Info as ChainInfo, Backend as ChainBackend}; +use blockchain::{self, Info as ChainInfo, Backend as ChainBackend, HeaderBackend as ChainHeaderBackend}; use call_executor::{CallExecutor, LocalCallExecutor}; +use executor::{RuntimeVersion, RuntimeInfo}; use {error, in_mem, block_builder, runtime_io, bft, genesis}; /// Type that implements `futures::Stream` of block import events. pub type BlockchainEventStream = mpsc::UnboundedReceiver>; -/// Polkadot Client +/// Substrate Client pub struct Client where Block: BlockT { backend: Arc, executor: E, import_notification_sinks: Mutex>>>, import_lock: Mutex<()>, importing_block: RwLock>, // holds the block hash currently being imported. TODO: replace this with block queue + execution_strategy: ExecutionStrategy, } /// A source of blockchain evenets. @@ -97,7 +102,7 @@ pub enum BlockStatus { } /// Block data origin. -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum BlockOrigin { /// Genesis block built into the client. Genesis, @@ -131,44 +136,45 @@ pub struct BlockImportNotification { pub struct JustifiedHeader { header: ::Header, justification: ::bft::Justification, + authorities: Vec, } impl JustifiedHeader { /// Deconstruct the justified header into parts. - pub fn into_inner(self) -> (::Header, ::bft::Justification) { - (self.header, self.justification) + pub fn into_inner(self) -> (::Header, ::bft::Justification, Vec) { + (self.header, self.justification, self.authorities) } } /// Create an instance of in-memory client. pub fn new_in_mem( executor: E, - genesis_storage: S + genesis_storage: S, ) -> error::Result, LocalCallExecutor, E>, Block>> where - E: CodeExecutor, + E: CodeExecutor + RuntimeInfo, S: BuildStorage, Block: BlockT, { let backend = Arc::new(in_mem::Backend::new()); let executor = LocalCallExecutor::new(backend.clone(), executor); - Client::new(backend, executor, genesis_storage) + Client::new(backend, executor, genesis_storage, ExecutionStrategy::NativeWhenPossible) } -impl Client where +impl Client where B: backend::Backend, E: CallExecutor, Block: BlockT, - error::Error: From<<>::State as StateBackend>::Error>, { - /// Creates new Polkadot Client with given blockchain and code executor. + /// Creates new Substrate Client with given blockchain and code executor. pub fn new( backend: Arc, executor: E, build_genesis_storage: S, + execution_strategy: ExecutionStrategy, ) -> error::Result { if backend.blockchain().header(BlockId::Number(Zero::zero()))?.is_none() { - let genesis_storage = build_genesis_storage.build_storage(); + let genesis_storage = build_genesis_storage.build_storage()?; let genesis_block = genesis::construct_genesis_block::(&genesis_storage); info!("Initialising Genesis block/state (state: {}, header-hash: {})", genesis_block.header().state_root(), genesis_block.header().hash()); let mut op = backend.begin_operation(BlockId::Hash(Default::default()))?; @@ -182,6 +188,7 @@ impl Client where import_notification_sinks: Mutex::new(Vec::new()), import_lock: Mutex::new(()), importing_block: RwLock::new(None), + execution_strategy, }) } @@ -198,7 +205,7 @@ impl Client where /// Return single storage entry of contract under given address in state in a block of given hash. pub fn storage(&self, id: &BlockId, key: &StorageKey) -> error::Result { Ok(StorageData(self.state_at(id)? - .storage(&key.0)? + .storage(&key.0).map_err(|e| error::Error::from_state(Box::new(e)))? .ok_or_else(|| error::ErrorKind::NoValueForKey(key.0.clone()))? .to_vec())) } @@ -210,9 +217,18 @@ impl Client where /// Get the set of authorities at a given block. pub fn authorities_at(&self, id: &BlockId) -> error::Result> { - self.executor.call(id, "authorities",&[]) - .and_then(|r| Vec::::decode(&mut &r.return_data[..]) - .ok_or(error::ErrorKind::AuthLenInvalid.into())) + match self.backend.blockchain().cache().and_then(|cache| cache.authorities_at(*id)) { + Some(cached_value) => Ok(cached_value), + None => self.executor.call(id, "authorities",&[]) + .and_then(|r| Vec::::decode(&mut &r.return_data[..]) + .ok_or(error::ErrorKind::AuthLenInvalid.into())) + } + } + + /// Get the RuntimeVersion at a given block. + pub fn runtime_version_at(&self, id: &BlockId) -> error::Result { + // TODO: Post Poc-2 return an error if version is missing + self.executor.runtime_version(id) } /// Get call executor reference. @@ -220,6 +236,14 @@ impl Client where &self.executor } + /// Reads storage value at a given block + key, returning read proof. + pub fn read_proof(&self, id: &BlockId, key: &[u8]) -> error::Result>> { + self.state_at(id) + .and_then(|state| prove_read(state, key) + .map(|(_, proof)| proof) + .map_err(Into::into)) + } + /// Execute a call to a contract on top of state in a block of given hash /// AND returning execution proof. /// @@ -272,6 +296,7 @@ impl Client where Ok(JustifiedHeader { header, justification: just, + authorities, }) } @@ -282,7 +307,7 @@ impl Client where header: JustifiedHeader, body: Option::Extrinsic>>, ) -> error::Result { - let (header, justification) = header.into_inner(); + let (header, justification, authorities) = header.into_inner(); let parent_hash = header.parent_hash().clone(); match self.backend.blockchain().status(BlockId::Hash(parent_hash))? { blockchain::BlockStatus::InChain => {}, @@ -290,9 +315,15 @@ impl Client where } let hash = header.hash(); let _import_lock = self.import_lock.lock(); + let height: u64 = header.number().as_(); *self.importing_block.write() = Some(hash); - let result = self.execute_and_import_block(origin, hash, header, justification, body); + let result = self.execute_and_import_block(origin, hash, header, justification, body, authorities); *self.importing_block.write() = None; + telemetry!("block.import"; + "height" => height, + "best" => ?hash, + "origin" => ?origin + ); result } @@ -303,6 +334,7 @@ impl Client where header: Block::Header, justification: bft::Justification, body: Option>, + authorities: Vec, ) -> error::Result { let parent_hash = header.parent_hash().clone(); match self.backend.blockchain().status(BlockId::Hash(hash))? { @@ -314,13 +346,30 @@ impl Client where let storage_update = match transaction.state()? { Some(transaction_state) => { let mut overlay = Default::default(); - let (_, storage_update) = self.executor.call_at_state( + let mut r = self.executor.call_at_state( transaction_state, &mut overlay, "execute_block", - &::new(header.clone(), body.clone().unwrap_or_default()).encode() - )?; - + &::new(header.clone(), body.clone().unwrap_or_default()).encode(), + match (origin, self.execution_strategy) { + (BlockOrigin::NetworkInitialSync, _) | (_, ExecutionStrategy::NativeWhenPossible) => + ExecutionManager::NativeWhenPossible, + (_, ExecutionStrategy::AlwaysWasm) => ExecutionManager::AlwaysWasm, + _ => ExecutionManager::Both(|wasm_result, native_result| { + warn!("Consensus error between wasm and native block execution at block {}", hash); + warn!(" Header {:?}", header); + warn!(" Native result {:?}", native_result); + warn!(" Wasm result {:?}", wasm_result); + telemetry!("block.execute.consensus_failure"; + "hash" => ?hash, + "origin" => ?origin, + "header" => ?header + ); + wasm_result + }), + }, + ); + let (_, storage_update) = r?; Some(storage_update) }, None => None, @@ -328,7 +377,9 @@ impl Client where let is_new_best = header.number() == &(self.backend.blockchain().info()?.best_number + One::one()); trace!("Imported {}, (#{}), best={}, origin={:?}", hash, header.number(), is_new_best, origin); - transaction.set_block_data(header.clone(), body, Some(justification.uncheck().into()), is_new_best)?; + let unchecked: bft::UncheckedJustification<_> = justification.uncheck().into(); + transaction.set_block_data(header.clone(), body, Some(unchecked.into()), is_new_best)?; + transaction.update_authorities(authorities); if let Some(storage_update) = storage_update { transaction.update_storage(storage_update)?; } @@ -346,6 +397,12 @@ impl Client where Ok(ImportResult::Queued) } + /// Attempts to revert the chain by `n` blocks. Returns the number of blocks that were + /// successfully reverted. + pub fn revert(&self, n: NumberFor) -> error::Result> { + Ok(self.backend.revert(n)?) + } + /// Get blockchain info. pub fn info(&self) -> error::Result> { let info = self.backend.blockchain().info().map_err(|e| error::Error::from_blockchain(Box::new(e)))?; @@ -406,6 +463,15 @@ impl Client where self.backend.blockchain().justification(*id) } + /// Get full block by id. + pub fn block(&self, id: &BlockId) -> error::Result>> { + Ok(match (self.header(id)?, self.body(id)?, self.justification(id)?) { + (Some(header), Some(extrinsics), Some(justification)) => + Some(SignedBlock { block: RuntimeBlock { header, extrinsics }, justification }), + _ => None, + }) + } + /// Get best block header. pub fn best_block_header(&self) -> error::Result<::Header> { let info = self.backend.blockchain().info().map_err(|e| error::Error::from_blockchain(Box::new(e)))?; @@ -418,13 +484,18 @@ impl bft::BlockImport for Client B: backend::Backend, E: CallExecutor, Block: BlockT, - error::Error: From<::Error> { - fn import_block(&self, block: Block, justification: ::bft::Justification) { + fn import_block( + &self, + block: Block, + justification: ::bft::Justification, + authorities: &[AuthorityId] + ) { let (header, extrinsics) = block.deconstruct(); let justified_header = JustifiedHeader { header: header, justification, + authorities: authorities.to_vec(), }; let _ = self.import_block(BlockOrigin::ConsensusBroadcast, justified_header, Some(extrinsics)); @@ -436,9 +507,17 @@ impl bft::Authorities for Client B: backend::Backend, E: CallExecutor, Block: BlockT, - error::Error: From<::Error>, { fn authorities(&self, at: &BlockId) -> Result, bft::Error> { + let on_chain_version: Result<_, bft::Error> = self.runtime_version_at(at) + .map_err(|e| { trace!("Error getting runtime version {:?}", e); bft::ErrorKind::RuntimeVersionMissing.into() }); + let on_chain_version = on_chain_version?; + let native_version: Result<_, bft::Error> = self.executor.native_runtime_version() + .ok_or_else(|| bft::ErrorKind::NativeRuntimeMissing.into()); + let native_version = native_version?; + if !on_chain_version.can_author_with(&native_version) { + return Err(bft::ErrorKind::IncompatibleAuthoringRuntime(on_chain_version, native_version).into()) + } self.authorities_at(at).map_err(|_| { let descriptor = format!("{:?}", at); bft::ErrorKind::StateUnavailable(descriptor).into() @@ -451,7 +530,6 @@ impl BlockchainEvents for Client B: backend::Backend, E: CallExecutor, Block: BlockT, - error::Error: From<::Error> { /// Get block import event stream. fn import_notification_stream(&self) -> mpsc::UnboundedReceiver> { @@ -466,7 +544,6 @@ impl ChainHead for Client B: backend::Backend, E: CallExecutor, Block: BlockT, - error::Error: From<::Error> { fn best_block_header(&self) -> error::Result<::Header> { Client::best_block_header(self) @@ -476,17 +553,17 @@ impl ChainHead for Client #[cfg(test)] mod tests { use super::*; - use codec::Slicable; + use codec::Encode; use keyring::Keyring; use test_client::{self, TestClient}; use test_client::client::BlockOrigin; + use test_client::client::backend::Backend as TestBackend; use test_client::runtime as test_runtime; use test_client::runtime::{Transfer, Extrinsic}; #[test] fn client_initialises_from_genesis_ok() { let client = test_client::new(); - let _genesis_hash = client.block_hash(0).unwrap().unwrap(); assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Alice.to_raw_public().into())).unwrap(), 1000); assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Ferdie.to_raw_public().into())).unwrap(), 0); @@ -498,9 +575,9 @@ mod tests { assert_eq!(client.info().unwrap().chain.best_number, 0); assert_eq!(client.authorities_at(&BlockId::Number(0)).unwrap(), vec![ - Keyring::Alice.to_raw_public(), - Keyring::Bob.to_raw_public(), - Keyring::Charlie.to_raw_public() + Keyring::Alice.to_raw_public().into(), + Keyring::Bob.to_raw_public().into(), + Keyring::Charlie.to_raw_public().into() ]); } @@ -540,4 +617,43 @@ mod tests { assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Alice.to_raw_public().into())).unwrap(), 958); assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Ferdie.to_raw_public().into())).unwrap(), 42); } + + #[test] + fn client_uses_authorities_from_blockchain_cache() { + let client = test_client::new(); + test_client::client::in_mem::cache_authorities_at( + client.backend().blockchain(), + Default::default(), + Some(vec![[1u8; 32].into()])); + assert_eq!(client.authorities_at( + &BlockId::Hash(Default::default())).unwrap(), + vec![[1u8; 32].into()]); + } + + #[test] + fn block_builder_does_not_include_invalid() { + let client = test_client::new(); + + let mut builder = client.new_block().unwrap(); + + builder.push(sign_tx(Transfer { + from: Keyring::Alice.to_raw_public().into(), + to: Keyring::Ferdie.to_raw_public().into(), + amount: 42, + nonce: 0, + })).unwrap(); + + assert!(builder.push(sign_tx(Transfer { + from: Keyring::Eve.to_raw_public().into(), + to: Keyring::Alice.to_raw_public().into(), + amount: 42, + nonce: 0, + })).is_err()); + + client.justify_and_import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); + + assert_eq!(client.info().unwrap().chain.best_number, 1); + assert!(client.state_at(&BlockId::Number(1)).unwrap() != client.state_at(&BlockId::Number(0)).unwrap()); + assert_eq!(client.body(&BlockId::Number(1)).unwrap().unwrap().len(), 1) + } } diff --git a/substrate/client/src/error.rs b/substrate/client/src/error.rs index 7db181deae670..26964334f3d87 100644 --- a/substrate/client/src/error.rs +++ b/substrate/client/src/error.rs @@ -19,6 +19,7 @@ use std; use state_machine; use primitives::hexdisplay::HexDisplay; +use runtime_primitives::ApplyError; error_chain! { errors { @@ -34,6 +35,12 @@ error_chain! { display("UnknownBlock: {}", &*h), } + /// Applying extrinsic error. + ApplyExtinsicFailed(e: ApplyError) { + description("Extrinsic error"), + display("Extrinsic error: {:?}", e), + } + /// Execution error. Execution(e: Box) { description("execution error"), @@ -70,6 +77,12 @@ error_chain! { display("Current state of blockchain has invalid authority count value"), } + /// Cound not get runtime version. + VersionInvalid { + description("Runtime version error"), + display("On-chain runtime does not specify version"), + } + /// Invalid state data. AuthInvalid(i: u32) { description("authority value state error"), @@ -88,17 +101,29 @@ error_chain! { display("This method is not currently available when running in light client mode"), } - /// Invalid remote proof. + /// Invalid remote execution proof. InvalidExecutionProof { description("invalid execution proof"), display("Remote node has responded with invalid execution proof"), } - /// Invalid remote proof. + /// Remote fetch has been cancelled. RemoteFetchCancelled { description("remote fetch cancelled"), display("Remote data fetch has been cancelled"), } + + /// Remote fetch has been failed. + RemoteFetchFailed { + description("remote fetch failed"), + display("Remote data fetch has been failed"), + } + + /// Error decoding call result. + CallResultDecode(method: &'static str) { + description("Error decoding call result") + display("Error decoding call result of {}", method) + } } } @@ -120,4 +145,11 @@ impl Error { pub fn from_blockchain(e: Box) -> Self { ErrorKind::Blockchain(e).into() } + + /// Chain a state error. + pub fn from_state(e: Box) -> Self { + ErrorKind::Execution(e).into() + } } + +impl state_machine::Error for Error {} diff --git a/substrate/client/src/genesis.rs b/substrate/client/src/genesis.rs index b742ced5fa1de..c24b506e16d3b 100644 --- a/substrate/client/src/genesis.rs +++ b/substrate/client/src/genesis.rs @@ -16,7 +16,7 @@ //! Tool for creating the genesis block. -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hashing as HashingT, Zero}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, Zero}; use runtime_primitives::StorageMap; /// Create a genesis block, given the initial storage. @@ -25,8 +25,8 @@ pub fn construct_genesis_block< > ( storage: &StorageMap ) -> Block { - let state_root = <<::Header as HeaderT>::Hashing as HashingT>::trie_root(storage.clone().into_iter()); - let extrinsics_root = <<::Header as HeaderT>::Hashing as HashingT>::trie_root(::std::iter::empty::<(&[u8], &[u8])>()); + let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root(storage.clone().into_iter()); + let extrinsics_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root(::std::iter::empty::<(&[u8], &[u8])>()); Block::new( <::Header as HeaderT>::new( Zero::zero(), @@ -42,17 +42,21 @@ pub fn construct_genesis_block< #[cfg(test)] mod tests { use super::*; - use codec::{Slicable, Joiner}; + use codec::{Encode, Decode, Joiner}; use keyring::Keyring; - use executor::WasmExecutor; - use state_machine::{execute, OverlayedChanges}; + use executor::{WasmExecutor, NativeExecutionDispatch}; + use state_machine::{execute, OverlayedChanges, ExecutionStrategy}; use state_machine::backend::InMemory; use test_client; use test_client::runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}; use test_client::runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest, Extrinsic}; use ed25519::{Public, Pair}; - native_executor_instance!(Executor, test_client::runtime::api::dispatch, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm")); + native_executor_instance!(Executor, test_client::runtime::api::dispatch, test_client::runtime::VERSION, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm")); + + fn executor() -> ::executor::NativeExecutor { + NativeExecutionDispatch::with_heap_pages(8, 8) + } fn construct_block(backend: &InMemory, number: BlockNumber, parent_hash: Hash, state_root: Hash, txs: Vec) -> (Vec, Hash) { use triehash::ordered_trie_root; @@ -64,7 +68,7 @@ mod tests { Extrinsic { transfer: tx, signature } }).collect::>(); - let extrinsics_root = ordered_trie_root(transactions.iter().map(Slicable::encode)).0.into(); + let extrinsics_root = ordered_trie_root(transactions.iter().map(Encode::encode)).0.into(); println!("root before: {:?}", extrinsics_root); let mut header = Header { @@ -80,27 +84,30 @@ mod tests { execute( backend, &mut overlay, - &Executor::new(), + &executor(), "initialise_block", &header.encode(), + ExecutionStrategy::NativeWhenPossible, ).unwrap(); for tx in transactions.iter() { execute( backend, &mut overlay, - &Executor::new(), + &executor(), "apply_extrinsic", &tx.encode(), + ExecutionStrategy::NativeWhenPossible, ).unwrap(); } let (ret_data, _) = execute( backend, &mut overlay, - &Executor::new(), + &executor(), "finalise_block", - &[] + &[], + ExecutionStrategy::NativeWhenPossible, ).unwrap(); header = Header::decode(&mut &ret_data[..]).unwrap(); println!("root after: {:?}", header.extrinsics_root); @@ -126,7 +133,7 @@ mod tests { #[test] fn construct_genesis_should_work_with_native() { let mut storage = GenesisConfig::new_simple( - vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 1000 + vec![Keyring::One.to_raw_public().into(), Keyring::Two.to_raw_public().into()], 1000 ).genesis_map(); let block = construct_genesis_block::(&storage); let genesis_hash = block.header.hash(); @@ -139,16 +146,17 @@ mod tests { let _ = execute( &backend, &mut overlay, - &Executor::new(), + &executor(), "execute_block", - &b1data + &b1data, + ExecutionStrategy::NativeWhenPossible, ).unwrap(); } #[test] fn construct_genesis_should_work_with_wasm() { let mut storage = GenesisConfig::new_simple( - vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 1000 + vec![Keyring::One.to_raw_public().into(), Keyring::Two.to_raw_public().into()], 1000 ).genesis_map(); let block = construct_genesis_block::(&storage); let genesis_hash = block.header.hash(); @@ -161,9 +169,10 @@ mod tests { let _ = execute( &backend, &mut overlay, - &WasmExecutor, + &WasmExecutor::new(8, 8), "execute_block", - &b1data + &b1data, + ExecutionStrategy::NativeWhenPossible, ).unwrap(); } @@ -171,7 +180,7 @@ mod tests { #[should_panic] fn construct_genesis_with_bad_transaction_should_panic() { let mut storage = GenesisConfig::new_simple( - vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 68 + vec![Keyring::One.to_raw_public().into(), Keyring::Two.to_raw_public().into()], 68 ).genesis_map(); let block = construct_genesis_block::(&storage); let genesis_hash = block.header.hash(); @@ -184,9 +193,10 @@ mod tests { let _ = execute( &backend, &mut overlay, - &Executor::new(), + &Executor::with_heap_pages(8, 8), "execute_block", - &b1data + &b1data, + ExecutionStrategy::NativeWhenPossible, ).unwrap(); } } diff --git a/substrate/client/src/in_mem.rs b/substrate/client/src/in_mem.rs index 9bbcf01b6e905..a12323610a723 100644 --- a/substrate/client/src/in_mem.rs +++ b/substrate/client/src/in_mem.rs @@ -17,11 +17,14 @@ //! In memory client backend use std::collections::HashMap; +use std::sync::Arc; use parking_lot::RwLock; use error; use backend; +use light; +use primitives::AuthorityId; use runtime_primitives::generic::BlockId; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, NumberFor, As}; use runtime_primitives::bft::Justification; use blockchain::{self, BlockStatus}; use state_machine::backend::{Backend as StateBackend, InMemory}; @@ -87,13 +90,24 @@ struct BlockchainStorage { /// In-memory blockchain. Supports concurrent reads. pub struct Blockchain { - storage: RwLock>, + storage: Arc>>, + cache: Cache, +} + +struct Cache { + storage: Arc>>, + authorities_at: RwLock>>>, } impl Clone for Blockchain { fn clone(&self) -> Self { + let storage = Arc::new(RwLock::new(self.storage.read().clone())); Blockchain { - storage: RwLock::new(self.storage.read().clone()), + storage: storage.clone(), + cache: Cache { + storage, + authorities_at: RwLock::new(self.cache.authorities_at.read().clone()), + }, } } } @@ -108,16 +122,21 @@ impl Blockchain { } /// Create new in-memory blockchain storage. - pub fn new() -> Self { + pub fn new() -> Blockchain { + let storage = Arc::new(RwLock::new( + BlockchainStorage { + blocks: HashMap::new(), + hashes: HashMap::new(), + best_hash: Default::default(), + best_number: Zero::zero(), + genesis_hash: Default::default(), + })); Blockchain { - storage: RwLock::new( - BlockchainStorage { - blocks: HashMap::new(), - hashes: HashMap::new(), - best_hash: Default::default(), - best_number: Zero::zero(), - genesis_hash: Default::default(), - }) + storage: storage.clone(), + cache: Cache { + storage: storage, + authorities_at: Default::default(), + }, } } @@ -159,26 +178,13 @@ impl Blockchain { } } -impl blockchain::Backend for Blockchain { +impl blockchain::HeaderBackend for Blockchain { fn header(&self, id: BlockId) -> error::Result::Header>> { Ok(self.id(id).and_then(|hash| { self.storage.read().blocks.get(&hash).map(|b| b.header().clone()) })) } - fn body(&self, id: BlockId) -> error::Result::Extrinsic>>> { - Ok(self.id(id).and_then(|hash| { - self.storage.read().blocks.get(&hash) - .and_then(|b| b.extrinsics().map(|x| x.to_vec())) - })) - } - - fn justification(&self, id: BlockId) -> error::Result>> { - Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).and_then(|b| - b.justification().map(|x| x.clone())) - )) - } - fn info(&self) -> error::Result> { let storage = self.storage.read(); Ok(blockchain::Info { @@ -200,9 +206,51 @@ impl blockchain::Backend for Blockchain { } } + +impl blockchain::Backend for Blockchain { + fn body(&self, id: BlockId) -> error::Result::Extrinsic>>> { + Ok(self.id(id).and_then(|hash| { + self.storage.read().blocks.get(&hash) + .and_then(|b| b.extrinsics().map(|x| x.to_vec())) + })) + } + + fn justification(&self, id: BlockId) -> error::Result>> { + Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).and_then(|b| + b.justification().map(|x| x.clone())) + )) + } + + fn cache(&self) -> Option<&blockchain::Cache> { + Some(&self.cache) + } +} + +impl light::blockchain::Storage for Blockchain { + fn import_header( + &self, + is_new_best: bool, + header: Block::Header, + authorities: Option> + ) -> error::Result<()> { + let hash = header.hash(); + let parent_hash = *header.parent_hash(); + self.insert(hash, header, None, None, is_new_best); + if is_new_best { + self.cache.insert(parent_hash, authorities); + } + Ok(()) + } + + fn cache(&self) -> Option<&blockchain::Cache> { + Some(&self.cache) + } +} + /// In-memory operation. pub struct BlockImportOperation { pending_block: Option>, + pending_authorities: Option>, old_state: InMemory, new_state: Option, } @@ -229,6 +277,10 @@ impl backend::BlockImportOperation for BlockImportOperatio Ok(()) } + fn update_authorities(&mut self, authorities: Vec) { + self.pending_authorities = Some(authorities); + } + fn update_storage(&mut self, update: ::Transaction) -> error::Result<()> { self.new_state = Some(self.old_state.update(update)); Ok(()) @@ -275,6 +327,7 @@ impl backend::Backend for Backend where Ok(BlockImportOperation { pending_block: None, + pending_authorities: None, old_state: state, new_state: None, }) @@ -285,9 +338,14 @@ impl backend::Backend for Backend where let old_state = &operation.old_state; let (header, body, justification) = pending_block.block.into_inner(); let hash = header.hash(); + let parent_hash = *header.parent_hash(); self.states.write().insert(hash, operation.new_state.unwrap_or_else(|| old_state.clone())); self.blockchain.insert(hash, header, justification, body, pending_block.is_best); + // dumb implementation - store value for each block + if pending_block.is_best { + self.blockchain.cache.insert(parent_hash, operation.pending_authorities); + } } Ok(()) } @@ -302,6 +360,36 @@ impl backend::Backend for Backend where None => Err(error::ErrorKind::UnknownBlock(format!("{}", block)).into()), } } + + fn revert(&self, _n: NumberFor) -> error::Result> { + Ok(As::sa(0)) + } } impl backend::LocalBackend for Backend {} + +impl Cache { + fn insert(&self, at: Block::Hash, authorities: Option>) { + self.authorities_at.write().insert(at, authorities); + } +} + +impl blockchain::Cache for Cache { + fn authorities_at(&self, block: BlockId) -> Option> { + let hash = match block { + BlockId::Hash(hash) => hash, + BlockId::Number(number) => self.storage.read().hashes.get(&number).cloned()?, + }; + + self.authorities_at.read().get(&hash).cloned().unwrap_or(None) + } +} + +/// Insert authorities entry into in-memory blockchain cache. Extracted as a separate function to use it in tests. +pub fn cache_authorities_at( + blockchain: &Blockchain, + at: Block::Hash, + authorities: Option> +) { + blockchain.cache.insert(at, authorities); +} diff --git a/substrate/client/src/lib.rs b/substrate/client/src/lib.rs index 1e69b2faa869b..329d5a5ac02df 100644 --- a/substrate/client/src/lib.rs +++ b/substrate/client/src/lib.rs @@ -28,6 +28,8 @@ extern crate substrate_runtime_primitives as runtime_primitives; extern crate substrate_state_machine as state_machine; #[cfg(test)] extern crate substrate_keyring as keyring; #[cfg(test)] extern crate substrate_test_client as test_client; +#[macro_use] extern crate substrate_telemetry; +#[macro_use] extern crate slog; // needed until we can reexport `slog_info` from `substrate_telemetry` extern crate ed25519; extern crate futures; @@ -36,7 +38,7 @@ extern crate triehash; #[macro_use] extern crate error_chain; #[macro_use] extern crate log; -#[cfg(test)] #[macro_use] extern crate substrate_executor as executor; +#[cfg_attr(test, macro_use)] extern crate substrate_executor as executor; #[cfg(test)] #[macro_use] extern crate hex_literal; pub mod error; @@ -53,9 +55,8 @@ pub use client::{ new_in_mem, BlockStatus, BlockOrigin, BlockchainEventStream, BlockchainEvents, Client, ClientInfo, ChainHead, - ImportResult, + ImportResult, JustifiedHeader, }; pub use blockchain::Info as ChainInfo; -pub use call_executor::{ - CallResult, CallExecutor, LocalCallExecutor, RemoteCallExecutor, -}; +pub use call_executor::{CallResult, CallExecutor, LocalCallExecutor}; +pub use state_machine::ExecutionStrategy; diff --git a/substrate/client/src/light.rs b/substrate/client/src/light.rs deleted file mode 100644 index 3055d7c163606..0000000000000 --- a/substrate/client/src/light.rs +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Light client backend. Only stores headers and justifications of blocks. -//! Everything else is requested from full nodes on demand. - -use std::sync::Arc; -use futures::future::IntoFuture; -use state_machine::{CodeExecutor, TryIntoTrieBackend as TryIntoStateTrieBackend, - TrieBackend as StateTrieBackend}; -use state_machine::backend::Backend as StateBackend; -use runtime_primitives::generic::BlockId; -use runtime_primitives::bft::Justification; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; -use runtime_primitives::BuildStorage; -use blockchain::{self, BlockStatus}; -use backend; -use call_executor::{CallResult, RemoteCallExecutor, check_execution_proof}; -use client::Client; -use error; -use in_mem::Blockchain as InMemBlockchain; - -/// Remote call request. -pub struct RemoteCallRequest { - /// Call at state of block referenced by given header hash. - pub block: H, - /// Method to call. - pub method: String, - /// Call data. - pub call_data: Vec, -} - -/// Light client data fetcher. Implementations of this trait must check if remote data -/// is correct (see FetchedDataChecker) and return already checked data. -pub trait Fetcher: Send + Sync { - /// Remote call result future. - type RemoteCallResult: IntoFuture; - - /// Fetch remote call result. - fn remote_call(&self, request: RemoteCallRequest) -> Self::RemoteCallResult; -} - -/// Light client remote data checker. -pub trait FetchChecker: Send + Sync { - /// Check remote method execution proof. - fn check_execution_proof(&self, request: &RemoteCallRequest, remote_proof: Vec>) -> error::Result; -} - -/// Light client backend. -pub struct Backend { - blockchain: Blockchain, -} - -/// Light client blockchain. -pub struct Blockchain { - storage: InMemBlockchain, -} - -/// Block (header and justification) import operation. -pub struct BlockImportOperation { - pending_block: Option>, -} - -/// On-demand state. -#[derive(Clone)] -pub struct OnDemandState { - /// Hash of the block, state is valid for. - _block: H, -} - -/// Remote data checker. -pub struct LightDataChecker { - /// Backend reference. - backend: Arc>, - /// Executor. - executor: E, -} - -struct PendingBlock { - header: B::Header, - justification: Option>, - is_best: bool, -} - -impl backend::Backend for Backend { - type BlockImportOperation = BlockImportOperation; - type Blockchain = Blockchain; - type State = OnDemandState; - - fn begin_operation(&self, _block: BlockId) -> error::Result { - Ok(BlockImportOperation { - pending_block: None, - }) - } - - fn commit_operation(&self, operation: Self::BlockImportOperation) -> error::Result<()> { - if let Some(pending_block) = operation.pending_block { - let hash = pending_block.header.hash(); - self.blockchain.storage.insert(hash, pending_block.header, pending_block.justification, None, pending_block.is_best); - } - Ok(()) - } - - fn blockchain(&self) -> &Blockchain { - &self.blockchain - } - - fn state_at(&self, block: BlockId) -> error::Result { - Ok(OnDemandState { - _block: self.blockchain.storage.id(block).ok_or(error::ErrorKind::UnknownBlock(format!("{:?}", block)))?, - }) - } -} - -impl backend::RemoteBackend for Backend {} - -impl backend::BlockImportOperation for BlockImportOperation { - type State = OnDemandState; - - fn state(&self) -> error::Result> { - // None means 'locally-stateless' backend - Ok(None) - } - - fn set_block_data(&mut self, header: B::Header, _body: Option>, justification: Option>, is_new_best: bool) -> error::Result<()> { - assert!(self.pending_block.is_none(), "Only one block per operation is allowed"); - self.pending_block = Some(PendingBlock { - header, - justification, - is_best: is_new_best, - }); - Ok(()) - } - - fn update_storage(&mut self, _update: ::Transaction) -> error::Result<()> { - // we're not storing anything locally => ignore changes - Ok(()) - } - - fn reset_storage, Vec)>>(&mut self, _iter: I) -> error::Result<()> { - // we're not storing anything locally => ignore changes - Ok(()) - } -} - -impl blockchain::Backend for Blockchain { - fn header(&self, id: BlockId) -> error::Result> { - self.storage.header(id) - } - - fn body(&self, _id: BlockId) -> error::Result>> { - // TODO [light]: fetch from remote node - Ok(None) - } - - fn justification(&self, id: BlockId) -> error::Result>> { - self.storage.justification(id) - } - - fn info(&self) -> error::Result> { - self.storage.info() - } - - fn status(&self, id: BlockId) -> error::Result { - self.storage.status(id) - } - - fn hash(&self, number: ::Number) -> error::Result> { - self.storage.hash(number) - } -} - -impl StateBackend for OnDemandState { - type Error = error::Error; - type Transaction = (); - - fn storage(&self, _key: &[u8]) -> Result>, Self::Error> { - // TODO [light]: fetch from remote node - Err(error::ErrorKind::NotAvailableOnLightClient.into()) - } - - fn storage_root(&self, _delta: I) -> ([u8; 32], Self::Transaction) - where I: IntoIterator, Option>)> - { - ([0; 32], ()) - } - - fn pairs(&self) -> Vec<(Vec, Vec)> { - // whole state is not available on light node - Vec::new() - } -} - -impl TryIntoStateTrieBackend for OnDemandState { - fn try_into_trie_backend(self) -> Option { - None - } -} - -impl FetchChecker for LightDataChecker - where - E: CodeExecutor, - B: BlockT, - <::Header as HeaderT>::Hash: Into<[u8; 32]>, // TODO: remove when patricia_trie generic. -{ - fn check_execution_proof(&self, request: &RemoteCallRequest, remote_proof: Vec>) -> error::Result { - check_execution_proof(&*self.backend, &self.executor, request, remote_proof) - } -} - -/// Create an instance of light client backend. -pub fn new_light_backend() -> Arc> { - let storage = InMemBlockchain::new(); - let blockchain = Blockchain { storage }; - Arc::new(Backend { blockchain }) -} - -/// Create an instance of light client. -pub fn new_light( - backend: Arc>, - fetcher: Arc, - genesis_storage: S, -) -> error::Result, RemoteCallExecutor, F>, Block>> - where - F: Fetcher, - S: BuildStorage, - Block: BlockT, -{ - let executor = RemoteCallExecutor::new(backend.clone(), fetcher); - Client::new(backend, executor, genesis_storage) -} - -/// Create an instance of fetch data checker. -pub fn new_fetch_checker( - backend: Arc>, - executor: E, -) -> LightDataChecker - where - E: CodeExecutor, - Block: BlockT, -{ - LightDataChecker { backend, executor } -} diff --git a/substrate/client/src/light/backend.rs b/substrate/client/src/light/backend.rs new file mode 100644 index 0000000000000..6851b54d1a62b --- /dev/null +++ b/substrate/client/src/light/backend.rs @@ -0,0 +1,241 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Light client backend. Only stores headers and justifications of blocks. +//! Everything else is requested from full nodes on demand. + +use std::sync::{Arc, Weak}; +use futures::{Future, IntoFuture}; + +use primitives::AuthorityId; +use runtime_primitives::{bft::Justification, generic::BlockId}; +use runtime_primitives::traits::{Block as BlockT, NumberFor}; +use state_machine::{Backend as StateBackend, TrieBackend as StateTrieBackend, + TryIntoTrieBackend as TryIntoStateTrieBackend}; + +use backend::{Backend as ClientBackend, BlockImportOperation, RemoteBackend}; +use blockchain::HeaderBackend as BlockchainHeaderBackend; +use error::{Error as ClientError, ErrorKind as ClientErrorKind, Result as ClientResult}; +use light::blockchain::{Blockchain, Storage as BlockchainStorage}; +use light::fetcher::{Fetcher, RemoteReadRequest}; + +/// Light client backend. +pub struct Backend { + blockchain: Arc>, +} + +/// Light block (header and justification) import operation. +pub struct ImportOperation { + is_new_best: bool, + header: Option, + authorities: Option>, + _phantom: ::std::marker::PhantomData, +} + +/// On-demand state. +pub struct OnDemandState { + fetcher: Weak, + block: Block::Hash, +} + +impl Backend { + /// Create new light backend. + pub fn new(blockchain: Arc>) -> Self { + Self { blockchain } + } + + /// Get shared blockchain reference. + pub fn blockchain(&self) -> &Arc> { + &self.blockchain + } +} + +impl ClientBackend for Backend where Block: BlockT, S: BlockchainStorage, F: Fetcher { + type BlockImportOperation = ImportOperation; + type Blockchain = Blockchain; + type State = OnDemandState; + + fn begin_operation(&self, _block: BlockId) -> ClientResult { + Ok(ImportOperation { + is_new_best: false, + header: None, + authorities: None, + _phantom: Default::default(), + }) + } + + fn commit_operation(&self, operation: Self::BlockImportOperation) -> ClientResult<()> { + let header = operation.header.expect("commit is called after set_block_data; set_block_data sets header; qed"); + self.blockchain.storage().import_header(operation.is_new_best, header, operation.authorities) + } + + fn blockchain(&self) -> &Blockchain { + &self.blockchain + } + + fn state_at(&self, block: BlockId) -> ClientResult { + let block_hash = match block { + BlockId::Hash(h) => Some(h), + BlockId::Number(n) => self.blockchain.hash(n).unwrap_or_default(), + }; + + Ok(OnDemandState { + block: block_hash.ok_or_else(|| ClientErrorKind::UnknownBlock(format!("{}", block)))?, + fetcher: self.blockchain.fetcher(), + }) + } + + fn revert(&self, _n: NumberFor) -> ClientResult> { + unimplemented!() + } +} + +impl RemoteBackend for Backend where Block: BlockT, S: BlockchainStorage, F: Fetcher {} + +impl BlockImportOperation for ImportOperation where Block: BlockT, F: Fetcher { + type State = OnDemandState; + + fn state(&self) -> ClientResult> { + // None means 'locally-stateless' backend + Ok(None) + } + + fn set_block_data( + &mut self, + header: Block::Header, + _body: Option>, + _justification: Option>, + is_new_best: bool + ) -> ClientResult<()> { + self.is_new_best = is_new_best; + self.header = Some(header); + Ok(()) + } + + fn update_authorities(&mut self, authorities: Vec) { + self.authorities = Some(authorities); + } + + fn update_storage(&mut self, _update: ::Transaction) -> ClientResult<()> { + // we're not storing anything locally => ignore changes + Ok(()) + } + + fn reset_storage, Vec)>>(&mut self, _iter: I) -> ClientResult<()> { + // we're not storing anything locally => ignore changes + Ok(()) + } +} + +impl Clone for OnDemandState { + fn clone(&self) -> Self { + OnDemandState { + fetcher: self.fetcher.clone(), + block: self.block, + } + } +} + +impl StateBackend for OnDemandState where Block: BlockT, F: Fetcher { + type Error = ClientError; + type Transaction = (); + + fn storage(&self, key: &[u8]) -> ClientResult>> { + self.fetcher.upgrade().ok_or(ClientErrorKind::NotAvailableOnLightClient)? + .remote_read(RemoteReadRequest { + block: self.block, + key: key.to_vec(), + }) + .into_future().wait() + } + + fn for_keys_with_prefix(&self, _prefix: &[u8], _action: A) { + // whole state is not available on light node + } + + fn storage_root(&self, _delta: I) -> ([u8; 32], Self::Transaction) + where I: IntoIterator, Option>)> { + ([0; 32], ()) + } + + fn pairs(&self) -> Vec<(Vec, Vec)> { + // whole state is not available on light node + Vec::new() + } +} + +impl TryIntoStateTrieBackend for OnDemandState where Block: BlockT, F: Fetcher { + fn try_into_trie_backend(self) -> Option { + None + } +} + +#[cfg(test)] +pub mod tests { + use futures::future::{ok, err, FutureResult}; + use parking_lot::Mutex; + use call_executor::CallResult; + use executor::{self, NativeExecutionDispatch}; + use error::Error as ClientError; + use test_client::{self, runtime::{Hash, Block}}; + use in_mem::{Blockchain as InMemoryBlockchain}; + use light::{new_fetch_checker, new_light_blockchain}; + use light::fetcher::{Fetcher, FetchChecker, LightDataChecker, RemoteCallRequest}; + use super::*; + + pub type OkCallFetcher = Mutex; + + impl Fetcher for OkCallFetcher { + type RemoteReadResult = FutureResult>, ClientError>; + type RemoteCallResult = FutureResult; + + fn remote_read(&self, _request: RemoteReadRequest) -> Self::RemoteReadResult { + err("Not implemented on test node".into()) + } + + fn remote_call(&self, _request: RemoteCallRequest) -> Self::RemoteCallResult { + ok((*self.lock()).clone()) + } + } + + #[test] + fn storage_read_proof_is_generated_and_checked() { + // prepare remote client + let remote_client = test_client::new(); + let remote_block_id = BlockId::Number(0); + let remote_block_hash = remote_client.block_hash(0).unwrap().unwrap(); + let mut remote_block_header = remote_client.header(&remote_block_id).unwrap().unwrap(); + remote_block_header.state_root = remote_client.state_at(&remote_block_id).unwrap().storage_root(::std::iter::empty()).0.into(); + + // 'fetch' read proof from remote node + let authorities_len = remote_client.authorities_at(&remote_block_id).unwrap().len(); + let remote_read_proof = remote_client.read_proof(&remote_block_id, b":auth:len").unwrap(); + + // check remote read proof locally + let local_storage = InMemoryBlockchain::::new(); + local_storage.insert(remote_block_hash, remote_block_header, None, None, true); + let local_executor = test_client::LocalExecutor::with_heap_pages(8, 8); + let local_checker: LightDataChecker< + InMemoryBlockchain, + executor::NativeExecutor, + OkCallFetcher + > = new_fetch_checker(new_light_blockchain(local_storage), local_executor); + assert_eq!(local_checker.check_read_proof(&RemoteReadRequest { + block: remote_block_hash, + key: b":auth:len".to_vec(), + }, remote_read_proof).unwrap().unwrap()[0], authorities_len as u8); + } +} diff --git a/substrate/client/src/light/blockchain.rs b/substrate/client/src/light/blockchain.rs new file mode 100644 index 0000000000000..4d9e7ca38dca7 --- /dev/null +++ b/substrate/client/src/light/blockchain.rs @@ -0,0 +1,108 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Light client blockchin backend. Only stores headers and justifications of recent +//! blocks. CHT roots are stored for headers of ancient blocks. + +use std::sync::Weak; +use parking_lot::Mutex; + +use primitives::AuthorityId; +use runtime_primitives::{bft::Justification, generic::BlockId}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; + +use blockchain::{Backend as BlockchainBackend, BlockStatus, Cache as BlockchainCache, + HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo}; +use error::Result as ClientResult; +use light::fetcher::Fetcher; + +/// Light client blockchain storage. +pub trait Storage: BlockchainHeaderBackend { + /// Store new header. + fn import_header( + &self, + is_new_best: bool, + header: Block::Header, + authorities: Option> + ) -> ClientResult<()>; + + /// Get storage cache. + fn cache(&self) -> Option<&BlockchainCache>; +} + +/// Light client blockchain. +pub struct Blockchain { + fetcher: Mutex>, + storage: S, +} + +impl Blockchain { + /// Create new light blockchain backed with given storage. + pub fn new(storage: S) -> Self { + Self { + fetcher: Mutex::new(Default::default()), + storage, + } + } + + /// Sets fetcher reference. + pub fn set_fetcher(&self, fetcher: Weak) { + *self.fetcher.lock() = fetcher; + } + + /// Get fetcher weak reference. + pub fn fetcher(&self) -> Weak { + self.fetcher.lock().clone() + } + + /// Get storage reference. + pub fn storage(&self) -> &S { + &self.storage + } +} + +impl BlockchainHeaderBackend for Blockchain where Block: BlockT, S: Storage, F: Fetcher { + fn header(&self, id: BlockId) -> ClientResult> { + self.storage.header(id) + } + + fn info(&self) -> ClientResult> { + self.storage.info() + } + + fn status(&self, id: BlockId) -> ClientResult { + self.storage.status(id) + } + + fn hash(&self, number: <::Header as HeaderT>::Number) -> ClientResult> { + self.storage.hash(number) + } +} + +impl BlockchainBackend for Blockchain where Block: BlockT, S: Storage, F: Fetcher { + fn body(&self, _id: BlockId) -> ClientResult>> { + // TODO [light]: fetch from remote node + Ok(None) + } + + fn justification(&self, _id: BlockId) -> ClientResult>> { + Ok(None) + } + + fn cache(&self) -> Option<&BlockchainCache> { + self.storage.cache() + } +} diff --git a/substrate/client/src/light/call_executor.rs b/substrate/client/src/light/call_executor.rs new file mode 100644 index 0000000000000..40d8665510100 --- /dev/null +++ b/substrate/client/src/light/call_executor.rs @@ -0,0 +1,165 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Light client call exector. Executes methods on remote full nodes, fetching +//! execution proof and checking it locally. + +use std::sync::Arc; +use futures::{IntoFuture, Future}; + +use runtime_primitives::generic::BlockId; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; +use state_machine::{Backend as StateBackend, CodeExecutor, OverlayedChanges, + execution_proof_check, TrieH256, ExecutionManager}; + +use blockchain::Backend as ChainBackend; +use call_executor::{CallExecutor, CallResult}; +use error::{Error as ClientError, ErrorKind as ClientErrorKind, Result as ClientResult}; +use light::fetcher::{Fetcher, RemoteCallRequest}; +use executor::RuntimeVersion; +use codec::Decode; + +/// Call executor that executes methods on remote node, querying execution proof +/// and checking proof by re-executing locally. +pub struct RemoteCallExecutor { + blockchain: Arc, + fetcher: Arc, +} + +impl RemoteCallExecutor { + /// Creates new instance of remote call executor. + pub fn new(blockchain: Arc, fetcher: Arc) -> Self { + RemoteCallExecutor { blockchain, fetcher } + } +} + +impl CallExecutor for RemoteCallExecutor + where + Block: BlockT, + B: ChainBackend, + F: Fetcher, +{ + type Error = ClientError; + + fn call(&self, id: &BlockId, method: &str, call_data: &[u8]) -> ClientResult { + let block_hash = match *id { + BlockId::Hash(hash) => hash, + BlockId::Number(number) => self.blockchain.hash(number)? + .ok_or_else(|| ClientErrorKind::UnknownBlock(format!("{}", number)))?, + }; + + self.fetcher.remote_call(RemoteCallRequest { + block: block_hash.clone(), + method: method.into(), + call_data: call_data.to_vec(), + }).into_future().wait() + } + + fn runtime_version(&self, id: &BlockId) -> ClientResult { + let call_result = self.call(id, "version", &[])?; + RuntimeVersion::decode(&mut call_result.return_data.as_slice()) + .ok_or_else(|| ClientErrorKind::VersionInvalid.into()) + } + + fn call_at_state< + S: StateBackend, + H: FnOnce(Result, Self::Error>, Result, Self::Error>) -> Result, Self::Error> + >(&self, + _state: &S, + _changes: &mut OverlayedChanges, + _method: &str, + _call_data: &[u8], + _m: ExecutionManager + ) -> ClientResult<(Vec, S::Transaction)> { + Err(ClientErrorKind::NotAvailableOnLightClient.into()) + } + + fn prove_at_state(&self, _state: S, _changes: &mut OverlayedChanges, _method: &str, _call_data: &[u8]) -> ClientResult<(Vec, Vec>)> { + Err(ClientErrorKind::NotAvailableOnLightClient.into()) + } + + fn native_runtime_version(&self) -> Option { + None + } +} + +/// Check remote execution proof using given backend. +pub fn check_execution_proof( + blockchain: &B, + executor: &E, + request: &RemoteCallRequest, + remote_proof: Vec> +) -> ClientResult + where + Block: BlockT, + B: ChainBackend, + E: CodeExecutor, +{ + let local_header = blockchain.header(BlockId::Hash(request.block))?; + let local_header = local_header.ok_or_else(|| ClientErrorKind::UnknownBlock(format!("{}", request.block)))?; + let local_state_root = *local_header.state_root(); + do_check_execution_proof(local_state_root.into(), executor, request, remote_proof) +} + +/// Check remote execution proof using given state root. +fn do_check_execution_proof( + local_state_root: Hash, + executor: &E, + request: &RemoteCallRequest, + remote_proof: Vec>, +) -> ClientResult + where + Hash: ::std::fmt::Display + ::std::convert::AsRef<[u8]>, + E: CodeExecutor, +{ + let mut changes = OverlayedChanges::default(); + let (local_result, _) = execution_proof_check( + TrieH256::from_slice(local_state_root.as_ref()).into(), + remote_proof, + &mut changes, + executor, + &request.method, + &request.call_data)?; + + Ok(CallResult { return_data: local_result, changes }) +} + +#[cfg(test)] +mod tests { + use test_client; + use executor::NativeExecutionDispatch; + use super::*; + + #[test] + fn execution_proof_is_generated_and_checked() { + // prepare remote client + let remote_client = test_client::new(); + let remote_block_id = BlockId::Number(0); + let remote_block_storage_root = remote_client.state_at(&remote_block_id) + .unwrap().storage_root(::std::iter::empty()).0; + + // 'fetch' execution proof from remote node + let remote_execution_proof = remote_client.execution_proof(&remote_block_id, "authorities", &[]).unwrap().1; + + // check remote execution proof locally + let local_executor = test_client::LocalExecutor::with_heap_pages(8, 8); + do_check_execution_proof(remote_block_storage_root.into(), &local_executor, &RemoteCallRequest { + block: test_client::runtime::Hash::default(), + method: "authorities".into(), + call_data: vec![], + }, remote_execution_proof).unwrap(); + } +} diff --git a/substrate/client/src/light/fetcher.rs b/substrate/client/src/light/fetcher.rs new file mode 100644 index 0000000000000..5cda7d766e8f2 --- /dev/null +++ b/substrate/client/src/light/fetcher.rs @@ -0,0 +1,129 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Light client data fetcher. Fetches requested data from remote full nodes. + +use std::sync::Arc; +use futures::IntoFuture; + +use runtime_primitives::generic::BlockId; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; +use state_machine::{CodeExecutor, read_proof_check}; + +use call_executor::CallResult; +use error::{Error as ClientError, ErrorKind as ClientErrorKind, Result as ClientResult}; +use light::blockchain::{Blockchain, Storage as BlockchainStorage}; +use light::call_executor::check_execution_proof; +use blockchain::HeaderBackend as BlockchainHeaderBackend; + +/// Remote call request. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct RemoteCallRequest { + /// Call at state of given block. + pub block: Hash, + /// Method to call. + pub method: String, + /// Call data. + pub call_data: Vec, +} + +/// Remote storage read request. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct RemoteReadRequest { + /// Read at state of given block. + pub block: Hash, + /// Storage key to read. + pub key: Vec, +} + +/// Light client data fetcher. Implementations of this trait must check if remote data +/// is correct (see FetchedDataChecker) and return already checked data. +pub trait Fetcher: Send + Sync { + /// Remote storage read future. + type RemoteReadResult: IntoFuture>, Error=ClientError>; + /// Remote call result future. + type RemoteCallResult: IntoFuture; + + /// Fetch remote storage value. + fn remote_read(&self, request: RemoteReadRequest) -> Self::RemoteReadResult; + /// Fetch remote call result. + fn remote_call(&self, request: RemoteCallRequest) -> Self::RemoteCallResult; +} + +/// Light client remote data checker. +pub trait FetchChecker: Send + Sync { + /// Check remote storage read proof. + fn check_read_proof( + &self, + request: &RemoteReadRequest, + remote_proof: Vec> + ) -> ClientResult>>; + /// Check remote method execution proof. + fn check_execution_proof( + &self, + request: &RemoteCallRequest, + remote_proof: Vec> + ) -> ClientResult; +} + +/// Remote data checker. +pub struct LightDataChecker { + blockchain: Arc>, + executor: E, +} + +impl LightDataChecker { + /// Create new light data checker. + pub fn new(blockchain: Arc>, executor: E) -> Self { + Self { + blockchain, + executor, + } + } + + /// Get blockchain reference. + pub fn blockchain(&self) -> &Arc> { + &self.blockchain + } +} + +impl FetchChecker for LightDataChecker + where + Block: BlockT, + Block::Hash: Into<[u8; 32]>, + S: BlockchainStorage, + E: CodeExecutor, + F: Fetcher, +{ + fn check_read_proof( + &self, + request: &RemoteReadRequest, + remote_proof: Vec> + ) -> ClientResult>> { + let local_header = self.blockchain.header(BlockId::Hash(request.block))?; + let local_header = local_header.ok_or_else(|| ClientErrorKind::UnknownBlock(format!("{}", request.block)))?; + let local_state_root = *local_header.state_root(); + read_proof_check(local_state_root.into(), remote_proof, &request.key).map_err(Into::into) + } + + fn check_execution_proof( + &self, + request: &RemoteCallRequest, + remote_proof: Vec> + ) -> ClientResult { + check_execution_proof(&*self.blockchain, &self.executor, request, remote_proof) + } +} diff --git a/substrate/client/src/light/mod.rs b/substrate/client/src/light/mod.rs new file mode 100644 index 0000000000000..40b54cdd634ce --- /dev/null +++ b/substrate/client/src/light/mod.rs @@ -0,0 +1,75 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Light client components. + +pub mod backend; +pub mod blockchain; +pub mod call_executor; +pub mod fetcher; + +use std::sync::Arc; + +use runtime_primitives::BuildStorage; +use runtime_primitives::traits::Block as BlockT; +use state_machine::{CodeExecutor, ExecutionStrategy}; + +use client::Client; +use error::Result as ClientResult; +use light::backend::Backend; +use light::blockchain::{Blockchain, Storage as BlockchainStorage}; +use light::call_executor::RemoteCallExecutor; +use light::fetcher::{Fetcher, LightDataChecker}; + +/// Create an instance of light client blockchain backend. +pub fn new_light_blockchain, F>(storage: S) -> Arc> { + Arc::new(Blockchain::new(storage)) +} + +/// Create an instance of light client backend. +pub fn new_light_backend, F: Fetcher>(blockchain: Arc>, fetcher: Arc) -> Arc> { + blockchain.set_fetcher(Arc::downgrade(&fetcher)); + Arc::new(Backend::new(blockchain)) +} + +/// Create an instance of light client. +pub fn new_light( + backend: Arc>, + fetcher: Arc, + genesis_storage: GS, +) -> ClientResult, RemoteCallExecutor, F>, B>> + where + B: BlockT, + S: BlockchainStorage, + F: Fetcher, + GS: BuildStorage, +{ + let executor = RemoteCallExecutor::new(backend.blockchain().clone(), fetcher); + Client::new(backend, executor, genesis_storage, ExecutionStrategy::NativeWhenPossible) +} + +/// Create an instance of fetch data checker. +pub fn new_fetch_checker( + blockchain: Arc>, + executor: E, +) -> LightDataChecker + where + B: BlockT, + S: BlockchainStorage, + E: CodeExecutor, +{ + LightDataChecker::new(blockchain, executor) +} diff --git a/substrate/codec/src/slicable.rs b/substrate/codec/src/codec.rs similarity index 69% rename from substrate/codec/src/slicable.rs rename to substrate/codec/src/codec.rs index 8d66b896faf6d..beee49ba3d8a4 100644 --- a/substrate/codec/src/slicable.rs +++ b/substrate/codec/src/codec.rs @@ -19,9 +19,7 @@ use alloc::vec::Vec; use alloc::boxed::Box; use core::{mem, slice}; -use super::joiner::Joiner; use arrayvec::ArrayVec; - /// Trait that allows reading of data into a slice. pub trait Input { /// Read into the provided input slice. Returns the number of bytes read. @@ -38,6 +36,7 @@ pub trait Input { } } +#[cfg(not(feature = "std"))] impl<'a> Input for &'a [u8] { fn read(&mut self, into: &mut [u8]) -> usize { let len = ::core::cmp::min(into.len(), self.len()); @@ -47,14 +46,57 @@ impl<'a> Input for &'a [u8] { } } -/// Trait that allows zero-copy read/write of value-references to/from slices in LE format. -pub trait Slicable: Sized { - /// Attempt to deserialise the value from input. - fn decode(value: &mut I) -> Option; +#[cfg(feature = "std")] +impl Input for R { + fn read(&mut self, into: &mut [u8]) -> usize { + match (self as &mut ::std::io::Read).read_exact(into) { + Ok(()) => into.len(), + Err(_) => 0, + } + } +} + +/// Trait that allows writing of data. +pub trait Output: Sized { + /// Write to the output. + fn write(&mut self, bytes: &[u8]); + + fn push_byte(&mut self, byte: u8) { + self.write(&[byte]); + } + + fn push(&mut self, value: &V) { + value.encode_to(self); + } +} + +#[cfg(not(feature = "std"))] +impl Output for Vec { + fn write(&mut self, bytes: &[u8]) { + self.extend(bytes); + } +} + +#[cfg(feature = "std")] +impl Output for W { + fn write(&mut self, bytes: &[u8]) { + (self as &mut ::std::io::Write).write(bytes).expect("Codec outputs are infallible"); + } +} + +/// Trait that allows zero-copy write of value-references to slices in LE format. +/// Implementations should override `using_encoded` for value types and `encode_to` for allocating types. +pub trait Encode { + /// Convert self to a slice and append it to the destination. + fn encode_to(&self, dest: &mut T) { + self.using_encoded(|buf| dest.write(buf)); + } /// Convert self to an owned vector. fn encode(&self) -> Vec { - self.using_encoded(|s| s.to_vec()) + let mut r = Vec::new(); + self.encode_to(&mut r); + r } /// Convert self to a slice and then invoke the given closure with it. @@ -63,44 +105,45 @@ pub trait Slicable: Sized { } } -impl Slicable for Result { - fn decode(input: &mut I) -> Option { - match input.read_byte()? { - 0 => Some(Ok(T::decode(input)?)), - 1 => Some(Err(E::decode(input)?)), - _ => None, - } - } +/// Trait that allows zero-copy read of value-references from slices in LE format. +pub trait Decode: Sized { + /// Attempt to deserialise the value from input. + fn decode(value: &mut I) -> Option; +} - fn encode(&self) -> Vec { - let mut v = Vec::new(); +/// Trait that allows zero-copy read/write of value-references to/from slices in LE format. +pub trait Codec: Decode + Encode {} +impl Codec for S {} + +impl Encode for Result { + fn encode_to(&self, dest: &mut W) { match *self { Ok(ref t) => { - v.push(0); - t.using_encoded(|s| v.extend(s)); + dest.push_byte(0); + t.encode_to(dest); } Err(ref e) => { - v.push(1); - e.using_encoded(|s| v.extend(s)); + dest.push_byte(1); + e.encode_to(dest); } } - v } } -/// Shim type because we can't do a specialised implementation for `Option` directly. -pub struct OptionBool(pub Option); - -impl Slicable for OptionBool { +impl Decode for Result { fn decode(input: &mut I) -> Option { match input.read_byte()? { - 0 => Some(OptionBool(None)), - 1 => Some(OptionBool(Some(true))), - 2 => Some(OptionBool(Some(false))), + 0 => Some(Ok(T::decode(input)?)), + 1 => Some(Err(E::decode(input)?)), _ => None, } } +} + +/// Shim type because we can't do a specialised implementation for `Option` directly. +pub struct OptionBool(pub Option); +impl Encode for OptionBool { fn using_encoded R>(&self, f: F) -> R { f(&[match *self { OptionBool(None) => 0u8, @@ -110,31 +153,50 @@ impl Slicable for OptionBool { } } -impl Slicable for Option { +impl Decode for OptionBool { fn decode(input: &mut I) -> Option { match input.read_byte()? { - 0 => Some(None), - 1 => Some(Some(T::decode(input)?)), + 0 => Some(OptionBool(None)), + 1 => Some(OptionBool(Some(true))), + 2 => Some(OptionBool(Some(false))), _ => None, } } +} - fn encode(&self) -> Vec { - let mut v = Vec::new(); +impl Encode for Option { + fn encode_to(&self, dest: &mut W) { match *self { Some(ref t) => { - v.push(1); - t.using_encoded(|s| v.extend(s)); + dest.push_byte(1); + t.encode_to(dest); } - None => v.push(0), + None => dest.push_byte(0), + } + } +} + +impl Decode for Option { + fn decode(input: &mut I) -> Option { + match input.read_byte()? { + 0 => Some(None), + 1 => Some(Some(T::decode(input)?)), + _ => None, } - v } } macro_rules! impl_array { ( $( $n:expr )* ) => { $( - impl Slicable for [T; $n] { + impl Encode for [T; $n] { + fn encode_to(&self, dest: &mut W) { + for item in self.iter() { + item.encode_to(dest); + } + } + } + + impl Decode for [T; $n] { fn decode(input: &mut I) -> Option { let mut r = ArrayVec::new(); for _ in 0..$n { @@ -142,15 +204,6 @@ macro_rules! impl_array { } r.into_inner().ok() } - - fn encode(&self) -> Vec { - use core::iter::Extend; - let mut r = Vec::new(); - for item in self.iter() { - item.using_encoded(|e| r.extend(e)); - } - r - } } )* } } @@ -158,17 +211,34 @@ macro_rules! impl_array { impl_array!(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 40 48 56 64 72 96 128 160 192 224 256); -impl Slicable for Box { +impl Encode for Box { + fn encode_to(&self, dest: &mut W) { + self.as_ref().encode_to(dest) + } +} + +impl Decode for Box { fn decode(input: &mut I) -> Option { Some(Box::new(T::decode(input)?)) } +} - fn using_encoded R>(&self, f: F) -> R { - self.as_ref().using_encoded(f) +impl Encode for [u8] { + fn encode_to(&self, dest: &mut W) { + let len = self.len(); + assert!(len <= u32::max_value() as usize, "Attempted to serialize a collection with too many elements."); + (len as u32).encode_to(dest); + dest.write(self) + } +} + +impl Encode for Vec { + fn encode_to(&self, dest: &mut W) { + self.as_slice().encode_to(dest) } } -impl Slicable for Vec { +impl Decode for Vec { fn decode(input: &mut I) -> Option { u32::decode(input).and_then(move |len| { let len = len as usize; @@ -180,18 +250,26 @@ impl Slicable for Vec { } }) } +} - fn encode(&self) -> Vec { +impl Encode for [T] { + fn encode_to(&self, dest: &mut W) { let len = self.len(); - assert!(len <= u32::max_value() as usize, "Attempted to serialize vec with too many elements."); + assert!(len <= u32::max_value() as usize, "Attempted to serialize a collection with too many elements."); + (len as u32).encode_to(dest); + for item in self { + item.encode_to(dest); + } + } +} - let mut r: Vec = Vec::new().and(&(len as u32)); - r.extend_from_slice(self); - r +impl Encode for Vec { + fn encode_to(&self, dest: &mut W) { + self.as_slice().encode_to(dest) } } -impl Slicable for Vec { +impl Decode for Vec { fn decode(input: &mut I) -> Option { u32::decode(input).and_then(move |len| { let mut r = Vec::with_capacity(len as usize); @@ -201,24 +279,10 @@ impl Slicable for Vec { Some(r) }) } - - fn encode(&self) -> Vec { - use core::iter::Extend; - - let len = self.len(); - assert!(len <= u32::max_value() as usize, "Attempted to serialize vec with too many elements."); - - let mut r: Vec = Vec::new().and(&(len as u32)); - for item in self { - item.using_encoded(|e| r.extend(e)) - } - r - } } -impl Slicable for () { - fn decode(_: &mut I) -> Option<()> { - Some(()) +impl Encode for () { + fn encode_to(&self, _dest: &mut T) { } fn using_encoded R>(&self, f: F) -> R { @@ -230,26 +294,46 @@ impl Slicable for () { } } +impl Decode for () { + fn decode(_: &mut I) -> Option<()> { + Some(()) + } +} + macro_rules! tuple_impl { ($one:ident,) => { - impl<$one: Slicable> Slicable for ($one,) { + impl<$one: Encode> Encode for ($one,) { + fn encode_to(&self, dest: &mut T) { + self.0.encode_to(dest); + } + } + + impl<$one: Decode> Decode for ($one,) { fn decode(input: &mut I) -> Option { match $one::decode(input) { None => None, Some($one) => Some(($one,)), } } + } + }; + ($first:ident, $($rest:ident,)+) => { + impl<$first: Encode, $($rest: Encode),+> + Encode for + ($first, $($rest),+) { + fn encode_to(&self, dest: &mut T) { + let ( + ref $first, + $(ref $rest),+ + ) = *self; - fn using_encoded R>(&self, f: F) -> R { - self.0.using_encoded(f) + $first.encode_to(dest); + $($rest.encode_to(dest);)+ } } - - }; - ($first:ident, $($rest:ident,)+) => { - impl<$first: Slicable, $($rest: Slicable),+> - Slicable for + impl<$first: Decode, $($rest: Decode),+> + Decode for ($first, $($rest),+) { fn decode(input: &mut INPUT) -> Option { Some(( @@ -263,22 +347,6 @@ macro_rules! tuple_impl { },)+ )) } - - fn using_encoded(&self, f: PROCESS) -> RETURN - where PROCESS: FnOnce(&[u8]) -> RETURN - { - let mut v = Vec::new(); - - let ( - ref $first, - $(ref $rest),+ - ) = *self; - - $first.using_encoded(|s| v.extend(s)); - $($rest.using_encoded(|s| v.extend(s));)+ - - f(v.as_slice()) - } } tuple_impl!($($rest,)+); @@ -287,15 +355,13 @@ macro_rules! tuple_impl { #[allow(non_snake_case)] mod inner_tuple_impl { - use alloc::vec::Vec; - - use super::{Input, Slicable}; + use super::{Input, Output, Decode, Encode}; tuple_impl!(A, B, C, D, E, F, G, H, I, J, K,); } /// Trait to allow conversion to a know endian representation when sensitive. /// Types implementing this trait must have a size > 0. -// note: the copy bound and static lifetimes are necessary for safety of `Slicable` blanket +// note: the copy bound and static lifetimes are necessary for safety of `Codec` blanket // implementation. trait EndianSensitive: Copy + 'static { fn to_le(self) -> Self { self } @@ -317,22 +383,7 @@ macro_rules! impl_endians { fn as_le_then T>(&self, f: F) -> T { let d = self.to_le(); f(&d) } } - impl Slicable for $t { - fn decode(input: &mut I) -> Option { - let size = mem::size_of::<$t>(); - assert!(size > 0, "EndianSensitive can never be implemented for a zero-sized type."); - let mut val: $t = unsafe { mem::zeroed() }; - - unsafe { - let raw: &mut [u8] = slice::from_raw_parts_mut( - &mut val as *mut $t as *mut u8, - size - ); - if input.read(raw) != size { return None } - } - Some(val.from_le()) - } - + impl Encode for $t { fn using_encoded R>(&self, f: F) -> R { self.as_le_then(|le| { let size = mem::size_of::<$t>(); @@ -349,13 +400,8 @@ macro_rules! impl_endians { }) } } - )* } -} -macro_rules! impl_non_endians { - ( $( $t:ty ),* ) => { $( - impl EndianSensitive for $t {} - impl Slicable for $t { + impl Decode for $t { fn decode(input: &mut I) -> Option { let size = mem::size_of::<$t>(); assert!(size > 0, "EndianSensitive can never be implemented for a zero-sized type."); @@ -370,7 +416,14 @@ macro_rules! impl_non_endians { } Some(val.from_le()) } + } + )* } +} +macro_rules! impl_non_endians { + ( $( $t:ty ),* ) => { $( + impl EndianSensitive for $t {} + impl Encode for $t { fn using_encoded R>(&self, f: F) -> R { self.as_le_then(|le| { let size = mem::size_of::<$t>(); @@ -387,6 +440,23 @@ macro_rules! impl_non_endians { }) } } + + impl Decode for $t { + fn decode(input: &mut I) -> Option { + let size = mem::size_of::<$t>(); + assert!(size > 0, "EndianSensitive can never be implemented for a zero-sized type."); + let mut val: $t = unsafe { mem::zeroed() }; + + unsafe { + let raw: &mut [u8] = slice::from_raw_parts_mut( + &mut val as *mut $t as *mut u8, + size + ); + if input.read(raw) != size { return None } + } + Some(val.from_le()) + } + } )* } } diff --git a/substrate/codec/src/joiner.rs b/substrate/codec/src/joiner.rs index f5775082fd854..81105b060ce63 100644 --- a/substrate/codec/src/joiner.rs +++ b/substrate/codec/src/joiner.rs @@ -17,16 +17,16 @@ //! Trait use core::iter::Extend; -use super::slicable::Slicable; +use super::Codec; /// Trait to allow itself to be serialised into a value which can be extended /// by bytes. pub trait Joiner { - fn and(self, value: &V) -> Self; + fn and(self, value: &V) -> Self; } impl Joiner for T where T: for<'a> Extend<&'a u8> { - fn and(mut self, value: &V) -> Self { + fn and(mut self, value: &V) -> Self { value.using_encoded(|s| self.extend(s)); self } diff --git a/substrate/codec/src/keyedvec.rs b/substrate/codec/src/keyedvec.rs index 353c7ec0e97c8..301bdcb326e94 100644 --- a/substrate/codec/src/keyedvec.rs +++ b/substrate/codec/src/keyedvec.rs @@ -16,7 +16,7 @@ //! Serialiser and prepender. -use slicable::Slicable; +use Codec; use core::iter::Extend; use alloc::vec::Vec; @@ -25,7 +25,7 @@ pub trait KeyedVec { fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec; } -impl KeyedVec for T { +impl KeyedVec for T { fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec { self.using_encoded(|slice| { let mut r = prepend_key.to_vec(); diff --git a/substrate/codec/src/lib.rs b/substrate/codec/src/lib.rs index b0ed6dc328dca..d4a0843f0a657 100644 --- a/substrate/codec/src/lib.rs +++ b/substrate/codec/src/lib.rs @@ -34,10 +34,10 @@ pub mod alloc { pub use std::vec; } -mod slicable; +mod codec; mod joiner; mod keyedvec; -pub use self::slicable::{Input, Slicable}; +pub use self::codec::{Input, Output, Encode, Decode, Codec}; pub use self::joiner::Joiner; pub use self::keyedvec::KeyedVec; diff --git a/substrate/ed25519/src/lib.rs b/substrate/ed25519/src/lib.rs index f659ad5405b9d..e02108524604b 100644 --- a/substrate/ed25519/src/lib.rs +++ b/substrate/ed25519/src/lib.rs @@ -23,7 +23,7 @@ extern crate untrusted; extern crate blake2_rfc; use ring::{rand, signature}; -use primitives::hash::H512; +use primitives::{hash::H512, AuthorityId}; use base58::{ToBase58, FromBase58}; #[cfg(test)] @@ -166,15 +166,28 @@ impl AsRef for Pair { } } +impl Into for Public { + fn into(self) -> AuthorityId { + AuthorityId(self.0) + } +} + +impl From for Public { + fn from(id: AuthorityId) -> Self { + Public(id.0) + } +} + impl ::std::fmt::Display for Public { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "{}", ::primitives::hexdisplay::HexDisplay::from(&self.0)) + write!(f, "{}", self.to_ss58check()) } } impl ::std::fmt::Debug for Public { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "{}", ::primitives::hexdisplay::HexDisplay::from(&self.0)) + let s = self.to_ss58check(); + write!(f, "{} ({}...)", ::primitives::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) } } diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs index 86e1100ecccad..ff94c0c1ebbb0 100644 --- a/substrate/environmental/src/lib.rs +++ b/substrate/environmental/src/lib.rs @@ -190,33 +190,36 @@ macro_rules! environmental { } } }; - ($name:ident : trait $t:ident) => { - #[allow(non_camel_case_types)] + ($name:ident : trait @$t:ident [$($args:ty,)*]) => { + #[allow(non_camel_case_types, dead_code)] struct $name { __private_field: () } - thread_local_impl!(static GLOBAL: $crate::imp::RefCell> + thread_local_impl!(static GLOBAL: $crate::imp::RefCell + 'static)>> = $crate::imp::RefCell::new(None)); impl $name { - #[allow(unused_imports)] + #[allow(unused_imports)] pub fn using R>( - protected: &mut $t, + protected: &mut $t<$($args),*>, f: F ) -> R { let lifetime_extended = unsafe { - $crate::imp::transmute::<&mut $t, &mut ($t + 'static)>(protected) + $crate::imp::transmute::<&mut $t<$($args),*>, &mut ($t<$($args),*> + 'static)>(protected) }; $crate::using(&GLOBAL, lifetime_extended, f) } - pub fn with FnOnce(&'a mut ($t + 'a)) -> R>( + pub fn with FnOnce(&'a mut ($t<$($args),*> + 'a)) -> R>( f: F ) -> Option { $crate::with(&GLOBAL, |x| f(x)) } } - } + }; + ($name:ident : trait $t:ident <>) => { environmental! { $name : trait @$t [] } }; + ($name:ident : trait $t:ident < $($args:ty),* $(,)* >) => { environmental! { $name : trait @$t [$($args,)*] } }; + ($name:ident : trait $t:ident) => { environmental! { $name : trait @$t [] } }; } #[cfg(test)] @@ -322,4 +325,28 @@ mod tests { assert_eq!(got_sum, 15); } + + #[test] + fn use_generic_trait() { + trait Plus { fn plus42() -> usize; } + struct ConcretePlus; + impl Plus for ConcretePlus { + fn plus42() -> usize { 42 } + } + trait Multiplier { fn mul_and_add(&self) -> usize; } + impl<'a, P: Plus> Multiplier

for &'a [usize] { + fn mul_and_add(&self) -> usize { + self.iter().fold(1, |a, c| a * c) + P::plus42() + } + } + + let numbers = vec![1, 2, 3]; + let mut numbers = &numbers[..]; + let out = foo::using(&mut numbers, || { + foo::with(|x| x.mul_and_add() ) + }).unwrap(); + + assert_eq!(out, 6 + 42); + environmental!(foo: trait Multiplier); + } } diff --git a/substrate/executor/Cargo.toml b/substrate/executor/Cargo.toml index 47ad4ee1697c0..8d537dd3dc78e 100644 --- a/substrate/executor/Cargo.toml +++ b/substrate/executor/Cargo.toml @@ -4,22 +4,30 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] -error-chain = "0.11" +error-chain = "0.12" substrate-codec = { path = "../codec" } substrate-runtime-io = { path = "../runtime-io" } substrate-primitives = { path = "../primitives" } substrate-serializer = { path = "../serializer" } substrate-state-machine = { path = "../state-machine" } +substrate-runtime-version = { path = "../runtime/version" } ed25519 = { path = "../ed25519" } serde = "1.0" serde_derive = "1.0" -wasmi = "0.1.0" +wasmi = "0.3" byteorder = "1.1" rustc-hex = "1.0.0" triehash = "0.1.0" hex-literal = "0.1.0" +twox-hash = "1.1.0" +lazy_static = "1.0" +parking_lot = "*" log = "0.3" [dev-dependencies] assert_matches = "1.1" -wabt = "0.1.7" +wabt = "0.4" + +[features] +default = [] +wasm-extern-trace = [] \ No newline at end of file diff --git a/substrate/executor/src/error.rs b/substrate/executor/src/error.rs index 639d23c075e35..8cdb157c582e3 100644 --- a/substrate/executor/src/error.rs +++ b/substrate/executor/src/error.rs @@ -16,6 +16,7 @@ //! Rust executor possible errors. +use state_machine; use serializer; use wasmi; @@ -39,6 +40,12 @@ error_chain! { display("Invalid Code: {:?}", c), } + /// Cound not get runtime version. + VersionInvalid { + description("Runtime version error"), + display("On-chain runtime does not specify version"), + } + /// Externalities have failed. Externalities { description("externalities failure"), @@ -68,5 +75,21 @@ error_chain! { description("invalid memory reference"), display("Invalid memory reference"), } + + /// Retry, please. + PleaseRetry { + description("retry needed"), + display("Retry needed"), + } + } +} + +impl state_machine::Error for Error { + fn needs_retry(&self) -> bool { + if let ErrorKind::PleaseRetry = self.0 { + true + } else { + false + } } } diff --git a/substrate/executor/src/lib.rs b/substrate/executor/src/lib.rs index 6c79977c5efd6..f474946919f6c 100644 --- a/substrate/executor/src/lib.rs +++ b/substrate/executor/src/lib.rs @@ -26,12 +26,14 @@ //! I leave it as is for now as it might be removed before this is ever done. #![warn(missing_docs)] +#![recursion_limit="128"] extern crate substrate_codec as codec; extern crate substrate_runtime_io as runtime_io; extern crate substrate_primitives as primitives; extern crate substrate_serializer as serializer; extern crate substrate_state_machine as state_machine; +extern crate substrate_runtime_version as runtime_version; extern crate ed25519; extern crate serde; @@ -39,8 +41,13 @@ extern crate wasmi; extern crate byteorder; extern crate rustc_hex; extern crate triehash; +extern crate parking_lot; +extern crate twox_hash; #[macro_use] extern crate log; +#[macro_use] +extern crate lazy_static; + #[macro_use] extern crate error_chain; @@ -61,3 +68,18 @@ pub mod error; pub use wasm_executor::WasmExecutor; pub use native_executor::{with_native_environment, NativeExecutor, NativeExecutionDispatch}; pub use state_machine::Externalities; +pub use runtime_version::RuntimeVersion; +pub use codec::Codec; + +/// Provides runtime information. +pub trait RuntimeInfo { + /// Native runtime information if any. + const NATIVE_VERSION: Option; + + /// Extract RuntimeVersion of given :code block + fn runtime_version ( + &self, + ext: &mut E, + code: &[u8] + ) -> Option; +} diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index a759c046c662b..5101398b0eb7e 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -17,11 +17,74 @@ use error::{Error, ErrorKind, Result}; use state_machine::{CodeExecutor, Externalities}; use wasm_executor::WasmExecutor; +use wasmi::Module as WasmModule; +use runtime_version::RuntimeVersion; +use std::collections::HashMap; +use codec::Decode; +use twox_hash::XxHash; +use std::hash::Hasher; +use parking_lot::{Mutex, MutexGuard}; +use RuntimeInfo; + +// For the internal Runtime Cache: +// Is it compatible enough to run this natively or do we need to fall back on the WasmModule +enum Compatibility { + InvalidVersion(WasmModule), + IsCompatible(RuntimeVersion), + NotCompatible(RuntimeVersion, WasmModule) +} + +type CacheType = HashMap; + +lazy_static! { + static ref RUNTIMES_CACHE: Mutex = Mutex::new(HashMap::new()); +} + +// helper function to generate low-over-head caching_keys +// it is asserted that part of the audit process that any potential on-chain code change +// will have done is to ensure that the two-x hash is different to that of any other +// :code value from the same chain +fn gen_cache_key(code: &[u8]) -> u64 { + let mut h = XxHash::with_seed(0); + h.write(code); + h.finish() +} + +/// fetch a runtime version from the cache or if there is no cached version yet, create +/// the runtime version entry for `code`, determines whether `Compatibility::IsCompatible` +/// can be used by by comparing returned RuntimeVersion to `ref_version` +fn fetch_cached_runtime_version<'a, E: Externalities>( + cache: &'a mut MutexGuard, + ext: &mut E, + code: &[u8], + ref_version: RuntimeVersion +) -> &'a Compatibility { + cache.entry(gen_cache_key(code)) + .or_insert_with(|| { + let module = WasmModule::from_buffer(code).expect("all modules compiled with rustc are valid wasm code; qed"); + let version = WasmExecutor::new(8, 8).call_in_wasm_module(ext, &module, "version", &[]).ok() + .and_then(|v| RuntimeVersion::decode(&mut v.as_slice())); + + if let Some(v) = version { + if ref_version.can_call_with(&v) { + Compatibility::IsCompatible(v) + } else { + Compatibility::NotCompatible(v, module) + } + } else { + Compatibility::InvalidVersion(module) + } + }) +} fn safe_call(f: F) -> Result where F: ::std::panic::UnwindSafe + FnOnce() -> U { - ::std::panic::catch_unwind(f).map_err(|_| ErrorKind::Runtime.into()) + // Substrate uses custom panic hook that terminates process on panic. Disable it for the native call. + let hook = ::std::panic::take_hook(); + let result = ::std::panic::catch_unwind(f).map_err(|_| ErrorKind::Runtime.into()); + ::std::panic::set_hook(hook); + result } /// Set up the externalities and safe calling environment to execute calls to a native runtime. @@ -34,30 +97,74 @@ pub fn with_native_environment(ext: &mut Externalities, f: F) -> Result } /// Delegate for dispatching a CodeExecutor call to native code. -pub trait NativeExecutionDispatch { +pub trait NativeExecutionDispatch: Send + Sync { /// Get the wasm code that the native dispatch will be equivalent to. fn native_equivalent() -> &'static [u8]; /// Dispatch a method and input data to be executed natively. Returns `Some` result or `None` /// if the `method` is unknown. Panics if there's an unrecoverable error. fn dispatch(ext: &mut Externalities, method: &str, data: &[u8]) -> Result>; + + /// Get native runtime version. + const VERSION: RuntimeVersion; + + /// Construct corresponding `NativeExecutor` with given `heap_pages`. + fn with_heap_pages(min_heap_pages: usize, max_heap_pages: usize) -> NativeExecutor where Self: Sized { + NativeExecutor::with_heap_pages(min_heap_pages, max_heap_pages) + } } /// A generic `CodeExecutor` implementation that uses a delegate to determine wasm code equivalence /// and dispatch to native code when possible, falling back on `WasmExecutor` when not. -#[derive(Debug, Default)] -pub struct NativeExecutor { +#[derive(Debug)] +pub struct NativeExecutor { /// Dummy field to avoid the compiler complaining about us not using `D`. - pub _dummy: ::std::marker::PhantomData, + _dummy: ::std::marker::PhantomData, + /// The fallback executor in case native isn't available. + fallback: WasmExecutor, } -impl Clone for NativeExecutor { +impl NativeExecutor { + /// Create new instance with specific number of pages for wasm fallback's heap. + pub fn with_heap_pages(min_heap_pages: usize, max_heap_pages: usize) -> Self { + // FIXME: set this entry at compile time + RUNTIMES_CACHE.lock().insert( + gen_cache_key(D::native_equivalent()), + Compatibility::IsCompatible(D::VERSION)); + + NativeExecutor { + _dummy: Default::default(), + fallback: WasmExecutor::new(min_heap_pages, max_heap_pages), + } + } +} + +impl Clone for NativeExecutor { fn clone(&self) -> Self { - NativeExecutor { _dummy: Default::default() } + NativeExecutor { + _dummy: Default::default(), + fallback: self.fallback.clone(), + } } } -impl CodeExecutor for NativeExecutor { +impl RuntimeInfo for NativeExecutor { + const NATIVE_VERSION: Option = Some(D::VERSION); + + fn runtime_version( + &self, + ext: &mut E, + code: &[u8], + ) -> Option { + let mut c = RUNTIMES_CACHE.lock(); + match fetch_cached_runtime_version(&mut c, ext, code, D::VERSION) { + Compatibility::IsCompatible(v) | Compatibility::NotCompatible(v, _) => Some(v.clone()), + Compatibility::InvalidVersion(_m) => None + } + } +} + +impl CodeExecutor for NativeExecutor { type Error = Error; fn call( @@ -66,30 +173,33 @@ impl CodeExecutor for NativeExecutor Result> { - if code == D::native_equivalent() { - // call native - D::dispatch(ext, method, data) - } else { - // call into wasm. - WasmExecutor.call(ext, code, method, data) + use_native: bool, + ) -> (Result>, bool) { + let mut c = RUNTIMES_CACHE.lock(); + match (use_native, fetch_cached_runtime_version(&mut c, ext, code, D::VERSION)) { + (_, Compatibility::NotCompatible(_, m)) | (_, Compatibility::InvalidVersion(m)) => + (self.fallback.call_in_wasm_module(ext, m, method, data), false), + (false, _) => + (self.fallback.call(ext, code, method, data, false).0, false), + _ => (D::dispatch(ext, method, data), true), } } } #[macro_export] macro_rules! native_executor_instance { - (pub $name:ident, $dispatcher:path, $code:expr) => { + (pub $name:ident, $dispatcher:path, $version:path, $code:expr) => { pub struct $name; - native_executor_instance!(IMPL $name, $dispatcher, $code); + native_executor_instance!(IMPL $name, $dispatcher, $version, $code); }; - ($name:ident, $dispatcher:path, $code:expr) => { + ($name:ident, $dispatcher:path, $version:path, $code:expr) => { /// A unit struct which implements `NativeExecutionDispatch` feeding in the hard-coded runtime. struct $name; - native_executor_instance!(IMPL $name, $dispatcher, $code); + native_executor_instance!(IMPL $name, $dispatcher, $version, $code); }; - (IMPL $name:ident, $dispatcher:path, $code:expr) => { + (IMPL $name:ident, $dispatcher:path, $version:path, $code:expr) => { impl $crate::NativeExecutionDispatch for $name { + const VERSION: $crate::RuntimeVersion = $version; fn native_equivalent() -> &'static [u8] { // WARNING!!! This assumes that the runtime was built *before* the main project. Until we // get a proper build script, this must be strictly adhered to or things will go wrong. @@ -100,13 +210,10 @@ macro_rules! native_executor_instance { $crate::with_native_environment(ext, move || $dispatcher(method, data))? .ok_or_else(|| $crate::error::ErrorKind::MethodNotFound(method.to_owned()).into()) } - } - impl $name { - pub fn new() -> $crate::NativeExecutor<$name> { - $crate::NativeExecutor { _dummy: Default::default() } + fn with_heap_pages(min_heap_pages: usize, max_heap_pages: usize) -> $crate::NativeExecutor<$name> { + $crate::NativeExecutor::with_heap_pages(min_heap_pages, max_heap_pages) } } } - } diff --git a/substrate/executor/src/sandbox.rs b/substrate/executor/src/sandbox.rs index 51cbb85fb5a03..ec0f2e75bbb66 100644 --- a/substrate/executor/src/sandbox.rs +++ b/substrate/executor/src/sandbox.rs @@ -20,9 +20,9 @@ use std::collections::HashMap; use std::rc::Rc; -use codec::Slicable; +use codec::{Decode, Encode}; use primitives::sandbox as sandbox_primitives; -use wasm_utils::DummyUserError; +use wasm_utils::UserError; use wasmi; use wasmi::memory_units::Pages; use wasmi::{ @@ -161,14 +161,14 @@ pub trait SandboxCapabilities { /// # Errors /// /// Returns `Err` if `ptr + data.len()` is out of bounds. - fn write_memory(&mut self, ptr: u32, data: &[u8]) -> Result<(), DummyUserError>; + fn write_memory(&mut self, ptr: u32, data: &[u8]) -> Result<(), UserError>; /// Read `len` bytes from the supervisor memory. /// /// # Errors /// /// Returns `Err` if `ptr + len` is out of bounds. - fn read_memory(&self, ptr: u32, len: u32) -> Result, DummyUserError>; + fn read_memory(&self, ptr: u32, len: u32) -> Result, UserError>; } /// Implementation of [`Externals`] that allows execution of guest module with @@ -182,7 +182,7 @@ pub struct GuestExternals<'a, FE: SandboxCapabilities + Externals + 'a> { } fn trap() -> Trap { - TrapKind::Host(Box::new(DummyUserError)).into() + TrapKind::Host(Box::new(UserError("Sandbox error"))).into() } fn deserialize_result(serialized_result: &[u8]) -> Result, Trap> { @@ -338,8 +338,8 @@ impl SandboxInstance { fn decode_environment_definition( raw_env_def: &[u8], memories: &[Option], -) -> Result<(Imports, GuestToSupervisorFunctionMapping), DummyUserError> { - let env_def = sandbox_primitives::EnvironmentDefinition::decode(&mut &raw_env_def[..]).ok_or_else(|| DummyUserError)?; +) -> Result<(Imports, GuestToSupervisorFunctionMapping), UserError> { + let env_def = sandbox_primitives::EnvironmentDefinition::decode(&mut &raw_env_def[..]).ok_or_else(|| UserError("Sandbox error"))?; let mut func_map = HashMap::new(); let mut memories_map = HashMap::new(); @@ -359,8 +359,8 @@ fn decode_environment_definition( let memory_ref = memories .get(memory_idx as usize) .cloned() - .ok_or_else(|| DummyUserError)? - .ok_or_else(|| DummyUserError)?; + .ok_or_else(|| UserError("Sandbox error"))? + .ok_or_else(|| UserError("Sandbox error"))?; memories_map.insert((module, field), memory_ref); } } @@ -395,12 +395,12 @@ pub fn instantiate( wasm: &[u8], raw_env_def: &[u8], state: u32, -) -> Result { +) -> Result { let (imports, guest_to_supervisor_mapping) = decode_environment_definition(raw_env_def, &supervisor_externals.store().memories)?; - let module = Module::from_buffer(wasm).map_err(|_| DummyUserError)?; - let instance = ModuleInstance::new(&module, &imports).map_err(|_| DummyUserError)?; + let module = Module::from_buffer(wasm).map_err(|_| UserError("Sandbox error"))?; + let instance = ModuleInstance::new(&module, &imports).map_err(|_| UserError("Sandbox error"))?; let sandbox_instance = Rc::new(SandboxInstance { // In general, it's not a very good idea to use `.not_started_instance()` for anything @@ -418,7 +418,7 @@ pub fn instantiate( |guest_externals| { instance .run_start(guest_externals) - .map_err(|_| DummyUserError) + .map_err(|_| UserError("Sandbox error")) }, )?; @@ -451,14 +451,14 @@ impl Store { /// /// Returns `Err` if the memory couldn't be created. /// Typically happens if `initial` is more than `maximum`. - pub fn new_memory(&mut self, initial: u32, maximum: u32) -> Result { + pub fn new_memory(&mut self, initial: u32, maximum: u32) -> Result { let maximum = match maximum { sandbox_primitives::MEM_UNLIMITED => None, specified_limit => Some(Pages(specified_limit as usize)), }; let mem = - MemoryInstance::alloc(Pages(initial as usize), maximum).map_err(|_| DummyUserError)?; + MemoryInstance::alloc(Pages(initial as usize), maximum).map_err(|_| UserError("Sandbox error"))?; let mem_idx = self.memories.len(); self.memories.push(Some(mem)); Ok(mem_idx as u32) @@ -470,12 +470,12 @@ impl Store { /// /// Returns `Err` If `instance_idx` isn't a valid index of an instance or /// instance is already torndown. - pub fn instance(&self, instance_idx: u32) -> Result, DummyUserError> { + pub fn instance(&self, instance_idx: u32) -> Result, UserError> { self.instances .get(instance_idx as usize) .cloned() - .ok_or_else(|| DummyUserError)? - .ok_or_else(|| DummyUserError) + .ok_or_else(|| UserError("Sandbox error"))? + .ok_or_else(|| UserError("Sandbox error")) } /// Returns reference to a memory instance by `memory_idx`. @@ -484,12 +484,12 @@ impl Store { /// /// Returns `Err` If `memory_idx` isn't a valid index of an memory or /// memory is already torndown. - pub fn memory(&self, memory_idx: u32) -> Result { + pub fn memory(&self, memory_idx: u32) -> Result { self.memories .get(memory_idx as usize) .cloned() - .ok_or_else(|| DummyUserError)? - .ok_or_else(|| DummyUserError) + .ok_or_else(|| UserError("Sandbox error"))? + .ok_or_else(|| UserError("Sandbox error")) } /// Teardown the memory at the specified index. @@ -497,18 +497,18 @@ impl Store { /// # Errors /// /// Returns `Err` if `memory_idx` isn't a valid index of an memory. - pub fn memory_teardown(&mut self, memory_idx: u32) -> Result<(), DummyUserError> { + pub fn memory_teardown(&mut self, memory_idx: u32) -> Result<(), UserError> { if memory_idx as usize >= self.memories.len() { - return Err(DummyUserError); + return Err(UserError("Sandbox error")); } self.memories[memory_idx as usize] = None; Ok(()) } /// Teardown the instance at the specified index. - pub fn instance_teardown(&mut self, instance_idx: u32) -> Result<(), DummyUserError> { + pub fn instance_teardown(&mut self, instance_idx: u32) -> Result<(), UserError> { if instance_idx as usize >= self.instances.len() { - return Err(DummyUserError); + return Err(UserError("Sandbox error")); } self.instances[instance_idx as usize] = None; Ok(()) @@ -554,7 +554,7 @@ mod tests { "#).unwrap(); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_sandbox", &code).unwrap(), + WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_sandbox", &code, true).0.unwrap(), vec![1], ); } @@ -575,7 +575,7 @@ mod tests { "#).unwrap(); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_sandbox", &code).unwrap(), + WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_sandbox", &code, true).0.unwrap(), vec![0], ); } @@ -613,7 +613,7 @@ mod tests { "#).unwrap(); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_sandbox", &code).unwrap(), + WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_sandbox", &code, true).0.unwrap(), vec![1], ); } @@ -647,7 +647,7 @@ mod tests { "#).unwrap(); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_sandbox_args", &code).unwrap(), + WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_sandbox_args", &code, true).0.unwrap(), vec![1], ); } @@ -669,7 +669,7 @@ mod tests { "#).unwrap(); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_sandbox_return_val", &code).unwrap(), + WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_sandbox_return_val", &code, true).0.unwrap(), vec![1], ); } diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index d230cc19865d1..4582e423b4f43 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -17,15 +17,16 @@ //! Rust implementation of Substrate contracts. use std::cmp::Ordering; +use parking_lot::Mutex; use std::collections::HashMap; use wasmi::{ - Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, + Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder }; use wasmi::RuntimeValue::{I32, I64}; use wasmi::memory_units::{Pages, Bytes}; use state_machine::{Externalities, CodeExecutor}; use error::{Error, ErrorKind, Result}; -use wasm_utils::{DummyUserError}; +use wasm_utils::UserError; use primitives::{blake2_256, twox_128, twox_256}; use primitives::hexdisplay::HexDisplay; use primitives::sandbox as sandbox_primitives; @@ -37,32 +38,41 @@ struct Heap { } impl Heap { - /// Construct new `Heap` struct. + /// Construct new `Heap` struct with a given number of pages. /// /// Returns `Err` if the heap couldn't allocate required /// number of pages. /// /// This could mean that wasm binary specifies memory /// limit and we are trying to allocate beyond that limit. - fn new(memory: &MemoryRef) -> Result { - const HEAP_SIZE_IN_PAGES: usize = 8; - + fn new(memory: &MemoryRef, pages: usize) -> Result { let prev_page_count = memory - .grow(Pages(HEAP_SIZE_IN_PAGES)) + .grow(Pages(pages)) .map_err(|_| Error::from(ErrorKind::Runtime))?; Ok(Heap { end: Bytes::from(prev_page_count).0 as u32, }) } + fn allocate(&mut self, size: u32) -> u32 { let r = self.end; self.end += size; r } + fn deallocate(&mut self, _offset: u32) { } } +#[cfg(feature="wasm-extern-trace")] +macro_rules! debug_trace { + ( $( $x:tt )* ) => ( trace!( $( $x )* ) ) +} +#[cfg(not(feature="wasm-extern-trace"))] +macro_rules! debug_trace { + ( $( $x:tt )* ) => () +} + struct FunctionExecutor<'e, E: Externalities + 'e> { sandbox_store: sandbox::Store, heap: Heap, @@ -73,10 +83,10 @@ struct FunctionExecutor<'e, E: Externalities + 'e> { } impl<'e, E: Externalities> FunctionExecutor<'e, E> { - fn new(m: MemoryRef, t: Option, e: &'e mut E) -> Result { + fn new(m: MemoryRef, heap_pages: usize, t: Option, e: &'e mut E) -> Result { Ok(FunctionExecutor { sandbox_store: sandbox::Store::new(), - heap: Heap::new(&m)?, + heap: Heap::new(&m, heap_pages)?, memory: m, table: t, ext: e, @@ -98,54 +108,36 @@ impl<'e, E: Externalities> sandbox::SandboxCapabilities for FunctionExecutor<'e, fn deallocate(&mut self, ptr: u32) { self.heap.deallocate(ptr) } - fn write_memory(&mut self, ptr: u32, data: &[u8]) -> ::std::result::Result<(), DummyUserError> { - self.memory.set(ptr, data).map_err(|_| DummyUserError) + fn write_memory(&mut self, ptr: u32, data: &[u8]) -> ::std::result::Result<(), UserError> { + self.memory.set(ptr, data).map_err(|_| UserError("Invalid attempt to write_memory")) } - fn read_memory(&self, ptr: u32, len: u32) -> ::std::result::Result, DummyUserError> { - self.memory.get(ptr, len as usize).map_err(|_| DummyUserError) + fn read_memory(&self, ptr: u32, len: u32) -> ::std::result::Result, UserError> { + self.memory.get(ptr, len as usize).map_err(|_| UserError("Invalid attempt to write_memory")) } } trait WritePrimitive { - fn write_primitive(&self, offset: u32, t: T) -> ::std::result::Result<(), DummyUserError>; + fn write_primitive(&self, offset: u32, t: T) -> ::std::result::Result<(), UserError>; } impl WritePrimitive for MemoryInstance { - fn write_primitive(&self, offset: u32, t: u32) -> ::std::result::Result<(), DummyUserError> { + fn write_primitive(&self, offset: u32, t: u32) -> ::std::result::Result<(), UserError> { use byteorder::{LittleEndian, ByteOrder}; let mut r = [0u8; 4]; LittleEndian::write_u32(&mut r, t); - self.set(offset, &r).map_err(|_| DummyUserError) + self.set(offset, &r).map_err(|_| UserError("Invalid attempt to write_primitive")) } } trait ReadPrimitive { - fn read_primitive(&self, offset: u32) -> ::std::result::Result; + fn read_primitive(&self, offset: u32) -> ::std::result::Result; } impl ReadPrimitive for MemoryInstance { - fn read_primitive(&self, offset: u32) -> ::std::result::Result { + fn read_primitive(&self, offset: u32) -> ::std::result::Result { use byteorder::{LittleEndian, ByteOrder}; - Ok(LittleEndian::read_u32(&self.get(offset, 4).map_err(|_| DummyUserError)?)) - } -} - -fn ascii_format(asciish: &[u8]) -> String { - let mut r = String::new(); - let mut latch = false; - for c in asciish { - match (latch, *c) { - (false, 32...127) => r.push(*c as char), - _ => { - if !latch { - r.push('#'); - latch = true; - } - r.push_str(&format!("{:02x}", *c)); - } - } + Ok(LittleEndian::read_u32(&self.get(offset, 4).map_err(|_| UserError("Invalid attempt to read_primitive"))?)) } - r } impl_function_executor!(this: FunctionExecutor<'e, E>, @@ -168,8 +160,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, Ok(()) }, ext_memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 => { - let sl1 = this.memory.get(s1, n as usize).map_err(|_| DummyUserError)?; - let sl2 = this.memory.get(s2, n as usize).map_err(|_| DummyUserError)?; + let sl1 = this.memory.get(s1, n as usize).map_err(|_| UserError("Invalid attempt to read from memory in first arg of ext_memcmp"))?; + let sl2 = this.memory.get(s2, n as usize).map_err(|_| UserError("Invalid attempt to read from memory in second arg of ext_memcmp"))?; Ok(match sl1.cmp(&sl2) { Ordering::Greater => 1, Ordering::Less => -1, @@ -178,87 +170,116 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, }, ext_memcpy(dest: *mut u8, src: *const u8, count: usize) -> *mut u8 => { this.memory.copy_nonoverlapping(src as usize, dest as usize, count as usize) - .map_err(|_| DummyUserError)?; - trace!(target: "runtime-io", "memcpy {} from {}, {} bytes", dest, src, count); + .map_err(|_| UserError("Invalid attempt to copy_nonoverlapping in ext_memcpy"))?; + debug_trace!(target: "runtime-io", "memcpy {} from {}, {} bytes", dest, src, count); Ok(dest) }, ext_memmove(dest: *mut u8, src: *const u8, count: usize) -> *mut u8 => { this.memory.copy(src as usize, dest as usize, count as usize) - .map_err(|_| DummyUserError)?; - trace!(target: "runtime-io", "memmove {} from {}, {} bytes", dest, src, count); + .map_err(|_| UserError("Invalid attempt to copy in ext_memmove"))?; + debug_trace!(target: "runtime-io", "memmove {} from {}, {} bytes", dest, src, count); Ok(dest) }, ext_memset(dest: *mut u8, val: u32, count: usize) -> *mut u8 => { + debug_trace!(target: "runtime-io", "memset {} with {}, {} bytes", dest, val, count); this.memory.clear(dest as usize, val as u8, count as usize) - .map_err(|_| DummyUserError)?; - trace!(target: "runtime-io", "memset {} with {}, {} bytes", dest, val, count); + .map_err(|_| UserError("Invalid attempt to clear in ext_memset"))?; Ok(dest) }, ext_malloc(size: usize) -> *mut u8 => { let r = this.heap.allocate(size); - trace!(target: "runtime-io", "malloc {} bytes at {}", size, r); + debug_trace!(target: "runtime-io", "malloc {} bytes at {}", size, r); Ok(r) }, ext_free(addr: *mut u8) => { this.heap.deallocate(addr); - trace!(target: "runtime-io", "free {}", addr); + debug_trace!(target: "runtime-io", "free {}", addr); Ok(()) }, ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32) => { - let key = this.memory.get(key_data, key_len as usize).map_err(|_| DummyUserError)?; - let value = this.memory.get(value_data, value_len as usize).map_err(|_| DummyUserError)?; - if let Some(preimage) = this.hash_lookup.get(&key) { - trace!(target: "wasm-trace", "*** Setting storage: %{} -> {} [k={}]", ascii_format(&preimage), HexDisplay::from(&value), HexDisplay::from(&key)); + let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_set_storage"))?; + let value = this.memory.get(value_data, value_len as usize).map_err(|_| UserError("Invalid attempt to determine value in ext_set_storage"))?; + if let Some(_preimage) = this.hash_lookup.get(&key) { + debug_trace!(target: "wasm-trace", "*** Setting storage: %{} -> {} [k={}]", ::primitives::hexdisplay::ascii_format(&_preimage), HexDisplay::from(&value), HexDisplay::from(&key)); } else { - trace!(target: "wasm-trace", "*** Setting storage: {} -> {} [k={}]", ascii_format(&key), HexDisplay::from(&value), HexDisplay::from(&key)); + debug_trace!(target: "wasm-trace", "*** Setting storage: {} -> {} [k={}]", ::primitives::hexdisplay::ascii_format(&key), HexDisplay::from(&value), HexDisplay::from(&key)); } this.ext.set_storage(key, value); Ok(()) }, ext_clear_storage(key_data: *const u8, key_len: u32) => { - let key = this.memory.get(key_data, key_len as usize).map_err(|_| DummyUserError)?; - if let Some(preimage) = this.hash_lookup.get(&key) { - trace!(target: "wasm-trace", "*** Clearing storage: %{} [k={}]", ascii_format(&preimage), HexDisplay::from(&key)); - } else { - trace!(target: "wasm-trace", "*** Clearing storage: {} [k={}]", ascii_format(&key), HexDisplay::from(&key)); - } + let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_clear_storage"))?; + debug_trace!(target: "wasm-trace", "*** Clearing storage: {} [k={}]", + if let Some(_preimage) = this.hash_lookup.get(&key) { + format!("%{}", ::primitives::hexdisplay::ascii_format(&_preimage)) + } else { + format!(" {}", ::primitives::hexdisplay::ascii_format(&key)) + }, HexDisplay::from(&key)); this.ext.clear_storage(&key); Ok(()) }, + ext_exists_storage(key_data: *const u8, key_len: u32) -> u32 => { + let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_exists_storage"))?; + Ok(if this.ext.exists_storage(&key) { 1 } else { 0 }) + }, + ext_clear_prefix(prefix_data: *const u8, prefix_len: u32) => { + let prefix = this.memory.get(prefix_data, prefix_len as usize).map_err(|_| UserError("Invalid attempt to determine prefix in ext_clear_prefix"))?; + this.ext.clear_prefix(&prefix); + Ok(()) + }, // return 0 and place u32::max_value() into written_out if no value exists for the key. ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8 => { - let key = this.memory.get(key_data, key_len as usize).map_err(|_| DummyUserError)?; + let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_get_allocated_storage"))?; let maybe_value = this.ext.storage(&key); - if let Some(preimage) = this.hash_lookup.get(&key) { - trace!(target: "wasm-trace", " Getting storage: %{} == {} [k={}]", ascii_format(&preimage), if let Some(ref b) = maybe_value { format!("{}", HexDisplay::from(b)) } else { "".to_owned() }, HexDisplay::from(&key)); - } else { - trace!(target: "wasm-trace", " Getting storage: {} == {} [k={}]", ascii_format(&key), if let Some(ref b) = maybe_value { format!("{}", HexDisplay::from(b)) } else { "".to_owned() }, HexDisplay::from(&key)); - } + debug_trace!(target: "wasm-trace", "*** Getting storage: {} == {} [k={}]", + if let Some(_preimage) = this.hash_lookup.get(&key) { + format!("%{}", ::primitives::hexdisplay::ascii_format(&_preimage)) + } else { + format!(" {}", ::primitives::hexdisplay::ascii_format(&key)) + }, + if let Some(ref b) = maybe_value { + format!("{}", HexDisplay::from(b)) + } else { + "".to_owned() + }, + HexDisplay::from(&key) + ); if let Some(value) = maybe_value { let offset = this.heap.allocate(value.len() as u32) as u32; - this.memory.set(offset, &value).map_err(|_| DummyUserError)?; - this.memory.write_primitive(written_out, value.len() as u32)?; + this.memory.set(offset, &value).map_err(|_| UserError("Invalid attempt to set memory in ext_get_allocated_storage"))?; + this.memory.write_primitive(written_out, value.len() as u32) + .map_err(|_| UserError("Invalid attempt to write written_out in ext_get_allocated_storage"))?; Ok(offset) } else { - this.memory.write_primitive(written_out, u32::max_value())?; + this.memory.write_primitive(written_out, u32::max_value()) + .map_err(|_| UserError("Invalid attempt to write failed written_out in ext_get_allocated_storage"))?; Ok(0) } }, // return u32::max_value() if no value exists for the key. ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32 => { - let key = this.memory.get(key_data, key_len as usize).map_err(|_| DummyUserError)?; + let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to get key in ext_get_storage_into"))?; let maybe_value = this.ext.storage(&key); - if let Some(preimage) = this.hash_lookup.get(&key) { - trace!(target: "wasm-trace", " Getting storage: %{} == {} [k={}]", ascii_format(&preimage), if let Some(ref b) = maybe_value { format!("{}", HexDisplay::from(b)) } else { "".to_owned() }, HexDisplay::from(&key)); - } else { - trace!(target: "wasm-trace", " Getting storage: {} == {} [k={}]", ascii_format(&key), if let Some(ref b) = maybe_value { format!("{}", HexDisplay::from(b)) } else { "".to_owned() }, HexDisplay::from(&key)); - } + debug_trace!(target: "wasm-trace", "*** Getting storage: {} == {} [k={}]", + if let Some(_preimage) = this.hash_lookup.get(&key) { + format!("%{}", ::primitives::hexdisplay::ascii_format(&_preimage)) + } else { + format!(" {}", ::primitives::hexdisplay::ascii_format(&key)) + }, + if let Some(ref b) = maybe_value { + format!("{}", HexDisplay::from(b)) + } else { + "".to_owned() + }, + HexDisplay::from(&key) + ); + if let Some(value) = maybe_value { let value = &value[value_offset as usize..]; let written = ::std::cmp::min(value_len as usize, value.len()); - this.memory.set(value_data, &value[..written]).map_err(|_| DummyUserError)?; + this.memory.set(value_data, &value[..written]).map_err(|_| UserError("Invalid attempt to set value in ext_get_storage_into"))?; Ok(written as u32) } else { Ok(u32::max_value()) @@ -266,22 +287,22 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, }, ext_storage_root(result: *mut u8) => { let r = this.ext.storage_root(); - this.memory.set(result, &r[..]).map_err(|_| DummyUserError)?; + this.memory.set(result, &r[..]).map_err(|_| UserError("Invalid attempt to set memory in ext_storage_root"))?; Ok(()) }, ext_enumerated_trie_root(values_data: *const u8, lens_data: *const u32, lens_len: u32, result: *mut u8) => { let values = (0..lens_len) .map(|i| this.memory.read_primitive(lens_data + i * 4)) - .collect::<::std::result::Result, DummyUserError>>()? + .collect::<::std::result::Result, UserError>>()? .into_iter() .scan(0u32, |acc, v| { let o = *acc; *acc += v; Some((o, v)) }) .map(|(offset, len)| this.memory.get(values_data + offset, len as usize) - .map_err(|_| DummyUserError) + .map_err(|_| UserError("Invalid attempt to get memory in ext_enumerated_trie_root")) ) - .collect::<::std::result::Result, DummyUserError>>()?; + .collect::<::std::result::Result, UserError>>()?; let r = ordered_trie_root(values.into_iter()); - this.memory.set(result, &r[..]).map_err(|_| DummyUserError)?; + this.memory.set(result, &r[..]).map_err(|_| UserError("Invalid attempt to set memory in ext_enumerated_trie_root"))?; Ok(()) }, ext_chain_id() -> u64 => { @@ -290,48 +311,51 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, ext_twox_128(data: *const u8, len: u32, out: *mut u8) => { let result = if len == 0 { let hashed = twox_128(&[0u8; 0]); - trace!(target: "xxhash", "XXhash: '' -> {}", HexDisplay::from(&hashed)); + debug_trace!(target: "xxhash", "XXhash: '' -> {}", HexDisplay::from(&hashed)); this.hash_lookup.insert(hashed.to_vec(), vec![]); hashed } else { - let key = this.memory.get(data, len as usize).map_err(|_| DummyUserError)?; + let key = this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get key in ext_twox_128"))?; let hashed_key = twox_128(&key); - if let Ok(skey) = ::std::str::from_utf8(&key) { - trace!(target: "xxhash", "XXhash: {} -> {}", skey, HexDisplay::from(&hashed_key)); - } else { - trace!(target: "xxhash", "XXhash: {} -> {}", HexDisplay::from(&key), HexDisplay::from(&hashed_key)); - } + debug_trace!(target: "xxhash", "XXhash: {} -> {}", + if let Ok(_skey) = ::std::str::from_utf8(&key) { + _skey.to_owned() + } else { + format!("{}", HexDisplay::from(&key)) + }, + HexDisplay::from(&hashed_key) + ); this.hash_lookup.insert(hashed_key.to_vec(), key); hashed_key }; - this.memory.set(out, &result).map_err(|_| DummyUserError)?; + this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_twox_128"))?; Ok(()) }, ext_twox_256(data: *const u8, len: u32, out: *mut u8) => { let result = if len == 0 { twox_256(&[0u8; 0]) } else { - twox_256(&this.memory.get(data, len as usize).map_err(|_| DummyUserError)?) + twox_256(&this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get data in ext_twox_256"))?) }; - this.memory.set(out, &result).map_err(|_| DummyUserError)?; + this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_twox_256"))?; Ok(()) }, ext_blake2_256(data: *const u8, len: u32, out: *mut u8) => { let result = if len == 0 { blake2_256(&[0u8; 0]) } else { - blake2_256(&this.memory.get(data, len as usize).map_err(|_| DummyUserError)?) + blake2_256(&this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get data in ext_blake2_256"))?) }; - this.memory.set(out, &result).map_err(|_| DummyUserError)?; + this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_blake2_256"))?; Ok(()) }, ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32 => { let mut sig = [0u8; 64]; - this.memory.get_into(sig_data, &mut sig[..]).map_err(|_| DummyUserError)?; + this.memory.get_into(sig_data, &mut sig[..]).map_err(|_| UserError("Invalid attempt to get signature in ext_ed25519_verify"))?; let mut pubkey = [0u8; 32]; - this.memory.get_into(pubkey_data, &mut pubkey[..]).map_err(|_| DummyUserError)?; - let msg = this.memory.get(msg_data, msg_len as usize).map_err(|_| DummyUserError)?; + this.memory.get_into(pubkey_data, &mut pubkey[..]).map_err(|_| UserError("Invalid attempt to get pubkey in ext_ed25519_verify"))?; + let msg = this.memory.get(msg_data, msg_len as usize).map_err(|_| UserError("Invalid attempt to get message in ext_ed25519_verify"))?; Ok(if ::ed25519::verify(&sig, &msg, &pubkey) { 0 @@ -340,15 +364,15 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, }) }, ext_sandbox_instantiate(dispatch_thunk_idx: usize, wasm_ptr: *const u8, wasm_len: usize, imports_ptr: *const u8, imports_len: usize, state: usize) -> u32 => { - let wasm = this.memory.get(wasm_ptr, wasm_len as usize).map_err(|_| DummyUserError)?; - let raw_env_def = this.memory.get(imports_ptr, imports_len as usize).map_err(|_| DummyUserError)?; + let wasm = this.memory.get(wasm_ptr, wasm_len as usize).map_err(|_| UserError("Sandbox error"))?; + let raw_env_def = this.memory.get(imports_ptr, imports_len as usize).map_err(|_| UserError("Sandbox error"))?; // Extract a dispatch thunk from instance's table by the specified index. let dispatch_thunk = { - let table = this.table.as_ref().ok_or_else(|| DummyUserError)?; + let table = this.table.as_ref().ok_or_else(|| UserError("Sandbox error"))?; table.get(dispatch_thunk_idx) - .map_err(|_| DummyUserError)? - .ok_or_else(|| DummyUserError)? + .map_err(|_| UserError("Sandbox error"))? + .ok_or_else(|| UserError("Sandbox error"))? .clone() }; @@ -363,10 +387,10 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, ext_sandbox_invoke(instance_idx: u32, export_ptr: *const u8, export_len: usize, state: usize) -> u32 => { trace!(target: "runtime-sandbox", "invoke, instance_idx={}", instance_idx); let export = this.memory.get(export_ptr, export_len as usize) - .map_err(|_| DummyUserError) + .map_err(|_| UserError("Sandbox error")) .and_then(|b| String::from_utf8(b) - .map_err(|_| DummyUserError) + .map_err(|_| UserError("Sandbox error")) )?; let instance = this.sandbox_store.instance(instance_idx)?; @@ -379,21 +403,21 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, }, // TODO: Remove the old 'ext_sandbox_invoke' and rename this to it. ext_sandbox_invoke_poc2(instance_idx: u32, export_ptr: *const u8, export_len: usize, args_ptr: *const u8, args_len: usize, return_val_ptr: *const u8, return_val_len: usize, state: usize) -> u32 => { - use codec::Slicable; + use codec::{Decode, Encode}; trace!(target: "runtime-sandbox", "invoke, instance_idx={}", instance_idx); let export = this.memory.get(export_ptr, export_len as usize) - .map_err(|_| DummyUserError) + .map_err(|_| UserError("Sandbox error")) .and_then(|b| String::from_utf8(b) - .map_err(|_| DummyUserError) + .map_err(|_| UserError("Sandbox error")) )?; // Deserialize arguments and convert them into wasmi types. let serialized_args = this.memory.get(args_ptr, args_len as usize) - .map_err(|_| DummyUserError)?; + .map_err(|_| UserError("Sandbox error"))?; let args = Vec::::decode(&mut &serialized_args[..]) - .ok_or_else(|| DummyUserError)? + .ok_or_else(|| UserError("Sandbox error"))? .into_iter() .map(Into::into) .collect::>(); @@ -407,11 +431,11 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, // Serialize return value and write it back into the memory. sandbox_primitives::ReturnValue::Value(val.into()).using_encoded(|val| { if val.len() > return_val_len as usize { - Err(DummyUserError)?; + Err(UserError("Sandbox error"))?; } this.memory .set(return_val_ptr, val) - .map_err(|_| DummyUserError)?; + .map_err(|_| UserError("Sandbox error"))?; Ok(sandbox_primitives::ERR_OK) }) } @@ -460,24 +484,51 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, /// Wasm rust executor for contracts. /// /// Executes the provided code in a sandboxed wasm runtime. -#[derive(Debug, Default, Clone)] -pub struct WasmExecutor; +#[derive(Debug)] +pub struct WasmExecutor { + /// The min number of pages to allocate for the heap. + pub min_heap_pages: usize, + /// The max number of pages to allocate for the heap. + pub max_heap_pages: usize, + + try_heap_pages: Mutex<(usize, usize)>, +} -impl CodeExecutor for WasmExecutor { - type Error = Error; +impl Clone for WasmExecutor { + fn clone(&self) -> Self { + WasmExecutor { + min_heap_pages: self.min_heap_pages, + max_heap_pages: self.max_heap_pages, + try_heap_pages: Mutex::new((self.min_heap_pages, 0)), + } + } +} - fn call( +// Number of executions to continue with the old heap_pages before reducing to the next lowest POT. +const DECAY_TIMEOUT: usize = 16; + +impl WasmExecutor { + + /// Create a new instance. + pub fn new(min_heap_pages: usize, max_heap_pages: usize) -> Self { + WasmExecutor { + min_heap_pages, + max_heap_pages, + try_heap_pages: Mutex::new((min_heap_pages, 0)), + } + } + + /// Call a given method in the given wasm-module runtime. + pub fn call_in_wasm_module( &self, ext: &mut E, - code: &[u8], + module: &Module, method: &str, data: &[u8], ) -> Result> { - let module = Module::from_buffer(code).expect("all modules compiled with rustc are valid wasm code; qed"); - // start module instantiation. Don't run 'start' function yet. let intermediate_instance = ModuleInstance::new( - &module, + module, &ImportsBuilder::new() .with_resolver("env", FunctionExecutor::::resolver()) )?; @@ -487,31 +538,63 @@ impl CodeExecutor for WasmExecutor { let memory = intermediate_instance .not_started_instance() .export_by_name("memory") + // TODO: with code coming from the blockchain it isn't strictly been compiled with rustc anymore. + // these assumptions are probably not true anymore .expect("all modules compiled with rustc should have an export named 'memory'; qed") .as_memory() .expect("in module generated by rustc export named 'memory' should be a memory; qed") .clone(); let table: Option = intermediate_instance .not_started_instance() - .export_by_name("table") + .export_by_name("__indirect_function_table") .and_then(|e| e.as_table().cloned()); - let mut fec = FunctionExecutor::new(memory.clone(), table, ext)?; + + let mut try_heap_pages = self.try_heap_pages.lock(); + let mut fec = FunctionExecutor::new(memory.clone(), try_heap_pages.0, table, ext)?; // finish instantiation by running 'start' function (if any). let instance = intermediate_instance.run_start(&mut fec)?; let size = data.len() as u32; let offset = fec.heap.allocate(size); - memory.set(offset, &data).expect("heap always gives a sensible offset to write"); + if let Err(_) = memory.set(offset, &data) { + let old = try_heap_pages.0; + *try_heap_pages = ((old * 2).min(self.max_heap_pages), DECAY_TIMEOUT); + trace!(target: "wasm-executor", "Shrunk heap size too small at {} pages. Retrying with {}", old, try_heap_pages.0); + return Err(ErrorKind::PleaseRetry.into()) + } - let returned = instance.invoke_export( + let result = instance.invoke_export( method, &[ I32(offset as i32), I32(size as i32) ], &mut fec - )?; + ); + + let returned = match result { + Ok(x) => x, + Err(_) if try_heap_pages.0 < self.max_heap_pages => { + let old = try_heap_pages.0; + *try_heap_pages = ((old * 2).min(self.max_heap_pages), DECAY_TIMEOUT); + trace!(target: "wasm-executor", "Shrunk heap size too small at {} pages. Retrying with {}", old, try_heap_pages.0); + return Err(ErrorKind::PleaseRetry.into()) + } + Err(e) => { + trace!(target: "wasm-executor", "Failed to execute code with {} pages", try_heap_pages.0); + return Err(e.into()) + }, + }; + + let decay_timeout = try_heap_pages.1; + if decay_timeout == 0 { + if try_heap_pages.0 > self.min_heap_pages { + *try_heap_pages = (self.min_heap_pages.max(try_heap_pages.0 - 1), DECAY_TIMEOUT); + } + } else { + try_heap_pages.1 -= 1; + } if let Some(I64(r)) = returned { let offset = r as u32; @@ -524,11 +607,28 @@ impl CodeExecutor for WasmExecutor { } } +impl CodeExecutor for WasmExecutor { + type Error = Error; + + fn call( + &self, + ext: &mut E, + code: &[u8], + method: &str, + data: &[u8], + _use_native: bool + ) -> (Result>, bool) { + (Module::from_buffer(code).map_err(Into::into).and_then(|module| + self.call_in_wasm_module(ext, &module, method, data) + ), false) + } +} + #[cfg(test)] mod tests { use super::*; use rustc_hex::FromHex; - use codec::Slicable; + use codec::Encode; use state_machine::TestExternalities; // TODO: move into own crate. @@ -543,7 +643,7 @@ mod tests { let mut ext = TestExternalities::default(); let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); - let output = WasmExecutor.call(&mut ext, &test_code[..], "test_empty_return", &[]).unwrap(); + let output = WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_empty_return", &[], true).0.unwrap(); assert_eq!(output, vec![0u8; 0]); } @@ -552,10 +652,10 @@ mod tests { let mut ext = TestExternalities::default(); let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); - let output = WasmExecutor.call(&mut ext, &test_code[..], "test_panic", &[]); + let output = WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_panic", &[], true).0; assert!(output.is_err()); - let output = WasmExecutor.call(&mut ext, &test_code[..], "test_conditional_panic", &[2]); + let output = WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_conditional_panic", &[2], true).0; assert!(output.is_err()); } @@ -565,7 +665,7 @@ mod tests { ext.set_storage(b"foo".to_vec(), b"bar".to_vec()); let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); - let output = WasmExecutor.call(&mut ext, &test_code[..], "test_data_in", b"Hello world").unwrap(); + let output = WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_data_in", b"Hello world", true).0.unwrap(); assert_eq!(output, b"all ok!".to_vec()); @@ -577,16 +677,39 @@ mod tests { assert_eq!(expected, ext); } + #[test] + fn clear_prefix_should_work() { + let mut ext = TestExternalities::default(); + ext.set_storage(b"aaa".to_vec(), b"1".to_vec()); + ext.set_storage(b"aab".to_vec(), b"2".to_vec()); + ext.set_storage(b"aba".to_vec(), b"3".to_vec()); + ext.set_storage(b"abb".to_vec(), b"4".to_vec()); + ext.set_storage(b"bbb".to_vec(), b"5".to_vec()); + let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); + + // This will clear all entries which prefix is "ab". + let output = WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_clear_prefix", b"ab", true).0.unwrap(); + + assert_eq!(output, b"all ok!".to_vec()); + + let expected: HashMap<_, _> = map![ + b"aaa".to_vec() => b"1".to_vec(), + b"aab".to_vec() => b"2".to_vec(), + b"bbb".to_vec() => b"5".to_vec() + ]; + assert_eq!(expected, ext); + } + #[test] fn blake2_256_should_work() { let mut ext = TestExternalities::default(); let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_blake2_256", &[]).unwrap(), + WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_blake2_256", &[], true).0.unwrap(), blake2_256(&b""[..]).encode() ); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_blake2_256", b"Hello world!").unwrap(), + WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_blake2_256", b"Hello world!", true).0.unwrap(), blake2_256(&b"Hello world!"[..]).encode() ); } @@ -596,11 +719,11 @@ mod tests { let mut ext = TestExternalities::default(); let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_twox_256", &[]).unwrap(), + WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_twox_256", &[], true).0.unwrap(), FromHex::from_hex("99e9d85137db46ef4bbea33613baafd56f963c64b1f3685a4eb4abd67ff6203a").unwrap() ); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_twox_256", b"Hello world!").unwrap(), + WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_twox_256", b"Hello world!", true).0.unwrap(), FromHex::from_hex("b27dfd7f223f177f2a13647b533599af0c07f68bda23d96d059da2b451a35a74").unwrap() ); } @@ -610,11 +733,11 @@ mod tests { let mut ext = TestExternalities::default(); let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_twox_128", &[]).unwrap(), + WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_twox_128", &[], true).0.unwrap(), FromHex::from_hex("99e9d85137db46ef4bbea33613baafd5").unwrap() ); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_twox_128", b"Hello world!").unwrap(), + WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_twox_128", b"Hello world!", true).0.unwrap(), FromHex::from_hex("b27dfd7f223f177f2a13647b533599af").unwrap() ); } @@ -630,7 +753,7 @@ mod tests { calldata.extend_from_slice(sig.as_ref()); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_ed25519_verify", &calldata).unwrap(), + WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_ed25519_verify", &calldata, true).0.unwrap(), vec![1] ); @@ -640,7 +763,7 @@ mod tests { calldata.extend_from_slice(other_sig.as_ref()); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_ed25519_verify", &calldata).unwrap(), + WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_ed25519_verify", &calldata, true).0.unwrap(), vec![0] ); } @@ -650,7 +773,7 @@ mod tests { let mut ext = TestExternalities::default(); let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_enumerated_trie_root", &[]).unwrap(), + WasmExecutor::new(8, 8).call(&mut ext, &test_code[..], "test_enumerated_trie_root", &[], true).0.unwrap(), ordered_trie_root(vec![b"zero".to_vec(), b"one".to_vec(), b"two".to_vec()]).0.encode() ); } diff --git a/substrate/executor/src/wasm_utils.rs b/substrate/executor/src/wasm_utils.rs index 1553273728a1b..5459266ba46c0 100644 --- a/substrate/executor/src/wasm_utils.rs +++ b/substrate/executor/src/wasm_utils.rs @@ -17,16 +17,17 @@ //! Rust implementation of Substrate contracts. use wasmi::{ValueType, RuntimeValue, HostError}; +use wasmi::nan_preserving_float::{F32, F64}; use std::fmt; #[derive(Debug)] -pub struct DummyUserError; -impl fmt::Display for DummyUserError { +pub struct UserError(pub &'static str); +impl fmt::Display for UserError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "DummyUserError") + write!(f, "UserError: {}", self.0) } } -impl HostError for DummyUserError { +impl HostError for UserError { } pub trait ConvertibleToWasm { const VALUE_TYPE: ValueType; type NativeType; fn to_runtime_value(self) -> RuntimeValue; } @@ -34,8 +35,8 @@ impl ConvertibleToWasm for i32 { type NativeType = i32; const VALUE_TYPE: ValueT impl ConvertibleToWasm for u32 { type NativeType = u32; const VALUE_TYPE: ValueType = ValueType::I32; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self as i32) } } impl ConvertibleToWasm for i64 { type NativeType = i64; const VALUE_TYPE: ValueType = ValueType::I64; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I64(self) } } impl ConvertibleToWasm for u64 { type NativeType = u64; const VALUE_TYPE: ValueType = ValueType::I64; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I64(self as i64) } } -impl ConvertibleToWasm for f32 { type NativeType = f32; const VALUE_TYPE: ValueType = ValueType::F32; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::F32(self) } } -impl ConvertibleToWasm for f64 { type NativeType = f64; const VALUE_TYPE: ValueType = ValueType::F64; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::F64(self) } } +impl ConvertibleToWasm for F32 { type NativeType = F32; const VALUE_TYPE: ValueType = ValueType::F32; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::F32(self) } } +impl ConvertibleToWasm for F64 { type NativeType = F64; const VALUE_TYPE: ValueType = ValueType::F64; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::F64(self) } } impl ConvertibleToWasm for isize { type NativeType = i32; const VALUE_TYPE: ValueType = ValueType::I32; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self as i32) } } impl ConvertibleToWasm for usize { type NativeType = u32; const VALUE_TYPE: ValueType = ValueType::I32; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self as u32 as i32) } } impl ConvertibleToWasm for *const T { type NativeType = u32; const VALUE_TYPE: ValueType = ValueType::I32; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self as isize as i32) } } diff --git a/substrate/executor/wasm/build.sh b/substrate/executor/wasm/build.sh index 7dcb11af109bc..66064f6f065f8 100755 --- a/substrate/executor/wasm/build.sh +++ b/substrate/executor/wasm/build.sh @@ -1,11 +1,8 @@ -#!/bin/bash +#!/usr/bin/env bash set -e -cargo +nightly build --target=wasm32-unknown-unknown --release +RUSTFLAGS="-C link-arg=--export-table" cargo +nightly build --target=wasm32-unknown-unknown --release for i in test do - # Add export of the default table under name 'table'. - wasm-export-table target/wasm32-unknown-unknown/release/runtime_$i.wasm target/wasm32-unknown-unknown/release/runtime_$i.table.wasm - cp target/wasm32-unknown-unknown/release/runtime_$i.table.wasm target/wasm32-unknown-unknown/release/runtime_$i.wasm wasm-gc target/wasm32-unknown-unknown/release/runtime_$i.wasm target/wasm32-unknown-unknown/release/runtime_$i.compact.wasm done diff --git a/substrate/executor/wasm/src/lib.rs b/substrate/executor/wasm/src/lib.rs index 804dd3b89cb77..126d1bbf86c61 100644 --- a/substrate/executor/wasm/src/lib.rs +++ b/substrate/executor/wasm/src/lib.rs @@ -11,7 +11,7 @@ extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_sandbox as sandbox; use runtime_io::{ - set_storage, storage, print, blake2_256, + set_storage, storage, clear_prefix, print, blake2_256, twox_128, twox_256, ed25519_verify, enumerated_trie_root }; @@ -29,6 +29,10 @@ impl_stubs!( print("finished!"); b"all ok!".to_vec() }, + test_clear_prefix NO_DECODE => |input| { + clear_prefix(input); + b"all ok!".to_vec() + }, test_empty_return NO_DECODE => |_| Vec::new(), test_panic NO_DECODE => |_| panic!("test panic"), test_conditional_panic NO_DECODE => |input: &[u8]| { diff --git a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index 2022cf88522fd..790eb1909f21d 100644 Binary files a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm and b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm differ diff --git a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm index 7776affa86622..51a27fe0197ad 100755 Binary files a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm and b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm differ diff --git a/substrate/extrinsic-pool/Cargo.toml b/substrate/extrinsic-pool/Cargo.toml index 88f639117b286..b991bd697e2d7 100644 --- a/substrate/extrinsic-pool/Cargo.toml +++ b/substrate/extrinsic-pool/Cargo.toml @@ -4,7 +4,9 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] -error-chain = "0.11" +serde = "1.0" +serde_derive = "1.0" +error-chain = "0.12" futures = "0.1" log = "0.3" parking_lot = "0.4" diff --git a/substrate/extrinsic-pool/src/api.rs b/substrate/extrinsic-pool/src/api.rs index ba76c45c046c5..0d8bcfbf223d0 100644 --- a/substrate/extrinsic-pool/src/api.rs +++ b/substrate/extrinsic-pool/src/api.rs @@ -16,9 +16,10 @@ //! External API for extrinsic pool. -use std::fmt; -use std::ops::Deref; -use txpool::{self, VerifiedTransaction}; +use txpool; +use futures::sync::mpsc; + +use watcher::Watcher; /// Extrinsic pool error. pub trait Error: ::std::error::Error + Send + Sized { @@ -34,29 +35,23 @@ impl Error for txpool::Error { fn into_pool_error(self) -> Result { Ok(self) } } +/// Modification notification event stream type; +pub type EventStream = mpsc::UnboundedReceiver<()>; + /// Extrinsic pool. -pub trait ExtrinsicPool: Send + Sync + 'static { +pub trait ExtrinsicPool: Send + Sync + 'static { /// Error type type Error: Error; /// Submit a collection of extrinsics to the pool. - fn submit(&self, xt: Vec) -> Result, Self::Error>; -} + fn submit(&self, block: BlockId, xt: Vec) -> Result, Self::Error>; + + /// Submit an extrinsic to the pool and start watching it's progress. + fn submit_and_watch(&self, block: BlockId, xt: Ex) -> Result, Self::Error>; + + /// Returns light status of the pool. + fn light_status(&self) -> txpool::LightStatus; -// Blanket implementation for anything that `Derefs` to the pool. -impl ExtrinsicPool for T where - Hash: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex + Default, - T: Deref> + Send + Sync + 'static, - V: txpool::Verifier, - S: txpool::Scoring, - V::VerifiedTransaction: txpool::VerifiedTransaction, - E: From, - E: From, - E: Error, -{ - type Error = E; - - fn submit(&self, xt: Vec) -> Result, Self::Error> { - self.deref().submit(xt).map(|result| result.into_iter().map(|xt| *xt.hash()).collect()) - } + /// Return an event stream of transactions imported to the pool. + fn import_notification_stream(&self) -> EventStream; } diff --git a/substrate/extrinsic-pool/src/lib.rs b/substrate/extrinsic-pool/src/lib.rs index c7b44a57096e9..ae6ac60f0f043 100644 --- a/substrate/extrinsic-pool/src/lib.rs +++ b/substrate/extrinsic-pool/src/lib.rs @@ -20,17 +20,20 @@ extern crate futures; extern crate parking_lot; +extern crate serde; #[macro_use] extern crate log; +#[macro_use] +extern crate serde_derive; pub extern crate transaction_pool as txpool; pub mod api; +pub mod watcher; mod listener; mod pool; -mod watcher; +pub use self::listener::Listener; pub use self::pool::Pool; -pub use self::watcher::Watcher; diff --git a/substrate/extrinsic-pool/src/listener.rs b/substrate/extrinsic-pool/src/listener.rs index 106c1f23e62f2..6bf110e55f977 100644 --- a/substrate/extrinsic-pool/src/listener.rs +++ b/substrate/extrinsic-pool/src/listener.rs @@ -23,17 +23,22 @@ use txpool; use watcher; +/// Extrinsic pool default listener. #[derive(Default)] pub struct Listener { watchers: HashMap> } impl Listener { + /// Creates a new watcher for given verified extrinsic. + /// + /// The watcher can be used to subscribe to lifecycle events of that extrinsic. pub fn create_watcher>(&mut self, xt: Arc) -> watcher::Watcher { let sender = self.watchers.entry(*xt.hash()).or_insert_with(watcher::Sender::default); sender.new_watcher() } + /// Notify the listeners about extrinsic broadcast. pub fn broadcasted(&mut self, hash: &H, peers: Vec) { self.fire(hash, |watcher| watcher.broadcast(peers)); } diff --git a/substrate/extrinsic-pool/src/pool.rs b/substrate/extrinsic-pool/src/pool.rs index c0e44b3edb7cc..488834398e6bb 100644 --- a/substrate/extrinsic-pool/src/pool.rs +++ b/substrate/extrinsic-pool/src/pool.rs @@ -18,7 +18,7 @@ use std::{ collections::HashMap, fmt, marker::PhantomData, - sync::{Arc, Weak}, + sync::Arc, }; use futures::sync::mpsc; @@ -29,52 +29,47 @@ use listener::Listener; use watcher::Watcher; /// Extrinsics pool. -pub struct Pool where +pub struct Pool where Hash: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex, - V: txpool::Verifier, - S: txpool::Scoring, + S: txpool::Scoring, + VEx: txpool::VerifiedTransaction, { _error: Mutex>, pool: RwLock, >>, - verifier: V, - import_notification_sinks: Mutex>>>, + import_notification_sinks: Mutex>>, } -impl Pool where +impl Pool where Hash: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex + Default, - V: txpool::Verifier, - S: txpool::Scoring, - V::VerifiedTransaction: txpool::VerifiedTransaction, - E: From, + S: txpool::Scoring, + VEx: txpool::VerifiedTransaction, E: From, { /// Create a new transaction pool. - pub fn new(options: txpool::Options, verifier: V, scoring: S) -> Self { + pub fn new(options: txpool::Options, scoring: S) -> Self { Pool { _error: Default::default(), pool: RwLock::new(txpool::Pool::new(Listener::default(), scoring, options)), - verifier, import_notification_sinks: Default::default(), } } /// Imports a pre-verified extrinsic to the pool. - pub fn import(&self, xt: V::VerifiedTransaction) -> Result, E> { + pub fn import(&self, xt: VEx) -> Result, E> { let result = self.pool.write().import(xt)?; - let weak = Arc::downgrade(&result); self.import_notification_sinks.lock() - .retain(|sink| sink.unbounded_send(weak.clone()).is_ok()); + .retain(|sink| sink.unbounded_send(()).is_ok()); Ok(result) } /// Return an event stream of transactions imported to the pool. - pub fn import_notification_stream(&self) -> mpsc::UnboundedReceiver> { + pub fn import_notification_stream(&self) -> mpsc::UnboundedReceiver<()> { let (sink, stream) = mpsc::unbounded(); self.import_notification_sinks.lock().push(sink); stream @@ -87,11 +82,15 @@ impl Pool where } } - /// Imports a bunch of extrinsics to the pool - pub fn submit(&self, xts: Vec) -> Result>, E> { + /// Imports a bunch of unverified extrinsics to the pool + pub fn submit(&self, verifier: V, xts: T) -> Result>, E> where + V: txpool::Verifier, + E: From, + T: IntoIterator + { xts .into_iter() - .map(|xt| self.verifier.verify_transaction(xt)) + .map(|xt| verifier.verify_transaction(xt)) .map(|xt| { Ok(self.pool.write().import(xt?)?) }) @@ -99,13 +98,16 @@ impl Pool where } /// Import a single extrinsic and starts to watch their progress in the pool. - pub fn submit_and_watch(&self, xt: Ex) -> Result, E> { - let xt = self.submit(vec![xt])?.pop().expect("One extrinsic passed; one result returned; qed"); + pub fn submit_and_watch(&self, verifier: V, xt: Ex) -> Result, E> where + V: txpool::Verifier, + E: From, + { + let xt = self.submit(verifier, vec![xt])?.pop().expect("One extrinsic passed; one result returned; qed"); Ok(self.pool.write().listener_mut().create_watcher(xt)) } /// Remove from the pool. - pub fn remove(&self, hashes: &[Hash], is_valid: bool) -> Vec>> { + pub fn remove(&self, hashes: &[Hash], is_valid: bool) -> Vec>> { let mut pool = self.pool.write(); let mut results = Vec::with_capacity(hashes.len()); for hash in hashes { @@ -115,24 +117,14 @@ impl Pool where } /// Cull transactions from the queue. - pub fn cull(&self, senders: Option<&[::Sender]>, ready: R) -> usize where - R: txpool::Ready, + pub fn cull(&self, senders: Option<&[::Sender]>, ready: R) -> usize where + R: txpool::Ready, { self.pool.write().cull(senders, ready) } - /// Cull transactions from the queue and then compute the pending set. - pub fn cull_and_get_pending(&self, ready: R, f: F) -> T where - R: txpool::Ready + Clone, - F: FnOnce(txpool::PendingIterator>) -> T, - { - let mut pool = self.pool.write(); - pool.cull(None, ready.clone()); - f(pool.pending(ready)) - } - /// Get the full status of the queue (including readiness) - pub fn status>(&self, ready: R) -> txpool::Status { + pub fn status>(&self, ready: R) -> txpool::Status { self.pool.read().status(ready) } @@ -140,4 +132,21 @@ impl Pool where pub fn light_status(&self) -> txpool::LightStatus { self.pool.read().light_status() } + + /// Removes all transactions from given sender + pub fn remove_sender(&self, sender: VEx::Sender) -> Vec> { + let mut pool = self.pool.write(); + let pending = pool.pending_from_sender(|_: &VEx| txpool::Readiness::Ready, &sender).collect(); + // remove all transactions from this sender + pool.cull(Some(&[sender]), |_: &VEx| txpool::Readiness::Stale); + pending + } + + /// Retrieve the pending set. Be careful to not leak the pool `ReadGuard` to prevent deadlocks. + pub fn pending(&self, ready: R, f: F) -> T where + R: txpool::Ready, + F: FnOnce(txpool::PendingIterator>) -> T, + { + f(self.pool.read().pending(ready)) + } } diff --git a/substrate/extrinsic-pool/src/watcher.rs b/substrate/extrinsic-pool/src/watcher.rs index e4d8b9921f8ff..e468d03ec2b4b 100644 --- a/substrate/extrinsic-pool/src/watcher.rs +++ b/substrate/extrinsic-pool/src/watcher.rs @@ -14,10 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use futures::sync::mpsc; +//! Extrinsics status updates. + +use futures::{ + Stream, + sync::mpsc, +}; /// Possible extrinsic status events -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub enum Status { /// Extrinsic has been finalised in block with given hash. Finalised(H), @@ -37,8 +43,19 @@ pub struct Watcher { receiver: mpsc::UnboundedReceiver>, } +impl Watcher { + /// Pipe the notifications to given sink. + /// + /// Make sure to drive the future to completion. + pub fn into_stream(self) -> impl Stream, Error=()> { + // we can safely ignore the error here, `UnboundedReceiver` never fails. + self.receiver.map_err(|_| ()) + } +} + +/// Sender part of the watcher. Exposed only for testing purposes. #[derive(Debug, Default)] -pub(crate) struct Sender { +pub struct Sender { receivers: Vec>>, finalised: bool, } @@ -74,6 +91,7 @@ impl Sender { self.send(Status::Broadcast(peers)) } + /// Returns true if the are no more listeners for this extrinsic or it was finalised. pub fn is_done(&self) -> bool { self.finalised || self.receivers.is_empty() diff --git a/substrate/keystore/Cargo.toml b/substrate/keystore/Cargo.toml index 18b0f3a33ec54..88ec623f34d4d 100644 --- a/substrate/keystore/Cargo.toml +++ b/substrate/keystore/Cargo.toml @@ -6,7 +6,7 @@ authors = ["Parity Technologies "] [dependencies] ethcore-crypto = { git = "https://github.com/paritytech/parity.git", default_features = false } ed25519 = { path = "../ed25519" } -error-chain = "0.11" +error-chain = "0.12" hex = "0.3" rand = "0.4" serde_json = "1.0" diff --git a/substrate/keystore/src/lib.rs b/substrate/keystore/src/lib.rs index 77aeb16ae1a80..97210b29ef015 100644 --- a/substrate/keystore/src/lib.rs +++ b/substrate/keystore/src/lib.rs @@ -84,7 +84,7 @@ impl EncryptedKey { // two parts of derived key // DK = [ DK[0..15] DK[16..31] ] = [derived_left_bits, derived_right_bits] - let (derived_left_bits, derived_right_bits) = crypto::derive_key_iterations(password, &salt, iterations); + let (derived_left_bits, derived_right_bits) = crypto::derive_key_iterations(password.as_bytes(), &salt, iterations); // preallocated (on-stack in case of `Secret`) buffer to hold cipher // length = length(plain) as we are using CTR-approach @@ -108,7 +108,7 @@ impl EncryptedKey { fn decrypt(&self, password: &str) -> Result<[u8; PKCS_LEN]> { let (derived_left_bits, derived_right_bits) = - crypto::derive_key_iterations(password, &self.salt, self.iterations); + crypto::derive_key_iterations(password.as_bytes(), &self.salt, self.iterations); let mac = crypto::derive_mac(&derived_right_bits, &self.ciphertext).keccak256(); diff --git a/substrate/misbehavior-check/Cargo.toml b/substrate/misbehavior-check/Cargo.toml index 3ab615b2d411a..c51e705369564 100644 --- a/substrate/misbehavior-check/Cargo.toml +++ b/substrate/misbehavior-check/Cargo.toml @@ -11,6 +11,7 @@ substrate-runtime-io = { path = "../runtime-io", default-features = false } [dev-dependencies] substrate-bft = { path = "../bft" } +rhododendron = "0.2" substrate-keyring = { path = "../keyring" } [features] diff --git a/substrate/misbehavior-check/src/lib.rs b/substrate/misbehavior-check/src/lib.rs index 1c7ff08e4bce0..0f2010c914d3c 100644 --- a/substrate/misbehavior-check/src/lib.rs +++ b/substrate/misbehavior-check/src/lib.rs @@ -27,14 +27,16 @@ extern crate substrate_runtime_primitives as runtime_primitives; extern crate substrate_bft; #[cfg(test)] extern crate substrate_keyring as keyring; +#[cfg(test)] +extern crate rhododendron; -use codec::Slicable; +use codec::{Codec, Encode}; use primitives::{AuthorityId, Signature}; use runtime_primitives::bft::{Action, Message, MisbehaviorKind}; // check a message signature. returns true if signed by that authority. -fn check_message_sig( +fn check_message_sig( message: Message, signature: &Signature, from: &AuthorityId @@ -62,7 +64,7 @@ fn commit(parent: H, round_number: u32, hash: H) -> Message { /// Doesn't check that the header hash in question is /// valid or whether the misbehaving authority was part of /// the set at that block. -pub fn evaluate_misbehavior( +pub fn evaluate_misbehavior( misbehaved: &AuthorityId, parent_hash: H, kind: &MisbehaviorKind, @@ -85,7 +87,6 @@ pub fn evaluate_misbehavior( mod tests { use super::*; - use substrate_bft::generic; use keyring::ed25519; use keyring::Keyring; @@ -95,26 +96,26 @@ mod tests { fn sign_prepare(key: &ed25519::Pair, round: u32, hash: H256, parent_hash: H256) -> (H256, Signature) { let msg = substrate_bft::sign_message::( - generic::Message::Vote(generic::Vote::Prepare(round as _, hash)), + rhododendron::Message::Vote(rhododendron::Vote::Prepare(round as _, hash)), key, parent_hash ); match msg { - generic::LocalizedMessage::Vote(vote) => (hash, vote.signature.signature), + rhododendron::LocalizedMessage::Vote(vote) => (hash, vote.signature.signature), _ => panic!("signing vote leads to signed vote"), } } fn sign_commit(key: &ed25519::Pair, round: u32, hash: H256, parent_hash: H256) -> (H256, Signature) { let msg = substrate_bft::sign_message::( - generic::Message::Vote(generic::Vote::Commit(round as _, hash)), + rhododendron::Message::Vote(rhododendron::Vote::Commit(round as _, hash)), key, parent_hash ); match msg { - generic::LocalizedMessage::Vote(vote) => (hash, vote.signature.signature), + rhododendron::LocalizedMessage::Vote(vote) => (hash, vote.signature.signature), _ => panic!("signing vote leads to signed vote"), } } @@ -127,7 +128,7 @@ mod tests { let hash_2 = [1; 32].into(); assert!(evaluate_misbehavior::( - &key.public().0, + &key.public().into(), parent_hash, &MisbehaviorKind::BftDoublePrepare( 1, @@ -139,7 +140,7 @@ mod tests { // same signature twice is not misbehavior. let signed = sign_prepare(&key, 1, hash_1, parent_hash); assert!(evaluate_misbehavior::( - &key.public().0, + &key.public().into(), parent_hash, &MisbehaviorKind::BftDoublePrepare( 1, @@ -150,7 +151,7 @@ mod tests { // misbehavior has wrong target. assert!(evaluate_misbehavior::( - &Keyring::Two.to_raw_public(), + &Keyring::Two.to_raw_public().into(), parent_hash, &MisbehaviorKind::BftDoublePrepare( 1, @@ -168,7 +169,7 @@ mod tests { let hash_2 = [1; 32].into(); assert!(evaluate_misbehavior::( - &key.public().0, + &key.public().into(), parent_hash, &MisbehaviorKind::BftDoubleCommit( 1, @@ -180,7 +181,7 @@ mod tests { // same signature twice is not misbehavior. let signed = sign_commit(&key, 1, hash_1, parent_hash); assert!(evaluate_misbehavior::( - &key.public().0, + &key.public().into(), parent_hash, &MisbehaviorKind::BftDoubleCommit( 1, @@ -191,7 +192,7 @@ mod tests { // misbehavior has wrong target. assert!(evaluate_misbehavior::( - &Keyring::Two.to_raw_public(), + &Keyring::Two.to_raw_public().into(), parent_hash, &MisbehaviorKind::BftDoubleCommit( 1, diff --git a/substrate/network-libp2p/Cargo.toml b/substrate/network-libp2p/Cargo.toml new file mode 100644 index 0000000000000..91382a0b0d665 --- /dev/null +++ b/substrate/network-libp2p/Cargo.toml @@ -0,0 +1,32 @@ +[package] +description = "libp2p implementation of the ethcore network library" +homepage = "http://parity.io" +license = "GPL-3.0" +name = "substrate-network-libp2p" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +bytes = "0.4" +error-chain = { version = "0.12", default-features = false } +fnv = "1.0" +futures = "0.1" +libp2p = { git = "https://github.com/tomaka/libp2p-rs", branch = "polkadot-2", default-features = false, features = ["libp2p-secio", "libp2p-secio-secp256k1"] } +ethcore-io = { git = "https://github.com/paritytech/parity.git" } +ethkey = { git = "https://github.com/paritytech/parity.git" } +ethereum-types = "0.3" +ipnetwork = "0.12.6" +parking_lot = "0.5" +libc = "0.2" +log = "0.3" +rand = "0.5.0" +tokio = "0.1" +tokio-io = "0.1" +tokio-timer = "0.2" +varint = { git = "https://github.com/tomaka/libp2p-rs", branch = "polkadot-2" } + +[dev-dependencies] +assert_matches = "1.2" +ethcore-bytes = { git = "https://github.com/paritytech/parity.git" } +ethcore-io = { git = "https://github.com/paritytech/parity.git" } +ethcore-logger = { git = "https://github.com/paritytech/parity.git" } diff --git a/substrate/network-libp2p/src/connection_filter.rs b/substrate/network-libp2p/src/connection_filter.rs new file mode 100644 index 0000000000000..46d9d86b58d33 --- /dev/null +++ b/substrate/network-libp2p/src/connection_filter.rs @@ -0,0 +1,31 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +//! Connection filter trait. + +use super::NodeId; + +/// Filtered connection direction. +pub enum ConnectionDirection { + Inbound, + Outbound, +} + +/// Connection filter. Each connection is checked against `connection_allowed`. +pub trait ConnectionFilter : Send + Sync { + /// Filter a connection. Returns `true` if connection should be allowed. `false` if rejected. + fn connection_allowed(&self, own_id: &NodeId, connecting_id: &NodeId, direction: ConnectionDirection) -> bool; +} diff --git a/substrate/network-libp2p/src/custom_proto.rs b/substrate/network-libp2p/src/custom_proto.rs new file mode 100644 index 0000000000000..77d2fdec3e1f3 --- /dev/null +++ b/substrate/network-libp2p/src/custom_proto.rs @@ -0,0 +1,290 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see .? + +use bytes::{Bytes, BytesMut}; +use ProtocolId; +use libp2p::core::{Multiaddr, ConnectionUpgrade, Endpoint}; +use PacketId; +use std::io::Error as IoError; +use std::vec::IntoIter as VecIntoIter; +use futures::{future, Future, stream, Stream, Sink}; +use futures::sync::mpsc; +use tokio_io::{AsyncRead, AsyncWrite}; +use varint::VarintCodec; + +/// Connection upgrade for a single protocol. +/// +/// Note that "a single protocol" here refers to `par` for example. However +/// each protocol can have multiple different versions for networking purposes. +#[derive(Clone)] +pub struct RegisteredProtocol { + /// Id of the protocol for API purposes. + id: ProtocolId, + /// Base name of the protocol as advertised on the network. + /// Ends with `/` so that we can append a version number behind. + base_name: Bytes, + /// List of protocol versions that we support, plus their packet count. + /// Ordered in descending order so that the best comes first. + /// The packet count is used to filter out invalid messages. + supported_versions: Vec<(u8, u8)>, + /// Custom data. + custom_data: T, +} + +/// Output of a `RegisteredProtocol` upgrade. +pub struct RegisteredProtocolOutput { + /// Data passed to `RegisteredProtocol::new`. + pub custom_data: T, + + /// Id of the protocol. + pub protocol_id: ProtocolId, + + /// Endpoint of the connection. + pub endpoint: Endpoint, + + /// Version of the protocol that was negotiated. + pub protocol_version: u8, + + /// Channel to sender outgoing messages to. + // TODO: consider assembling packet_id here + pub outgoing: mpsc::UnboundedSender, + + /// Stream where incoming messages are received. The stream ends whenever + /// either side is closed. + pub incoming: Box>, +} + +impl RegisteredProtocol { + /// Creates a new `RegisteredProtocol`. The `custom_data` parameter will be + /// passed inside the `RegisteredProtocolOutput`. + pub fn new(custom_data: T, protocol: ProtocolId, versions: &[(u8, u8)]) + -> Self { + let mut proto_name = Bytes::from_static(b"/substrate/"); + proto_name.extend_from_slice(&protocol); + proto_name.extend_from_slice(b"/"); + + RegisteredProtocol { + base_name: proto_name, + id: protocol, + supported_versions: { + let mut tmp: Vec<_> = versions.iter().rev().cloned().collect(); + tmp.sort_unstable_by(|a, b| b.1.cmp(&a.1)); + tmp + }, + custom_data: custom_data, + } + } + + /// Returns the ID of the protocol. + pub fn id(&self) -> ProtocolId { + self.id + } + + /// Returns the custom data that was passed to `new`. + pub fn custom_data(&self) -> &T { + &self.custom_data + } +} + +// `Maf` is short for `MultiaddressFuture` +impl ConnectionUpgrade for RegisteredProtocol +where C: AsyncRead + AsyncWrite + 'static, // TODO: 'static :-/ + Maf: Future + 'static, // TODO: 'static :( +{ + type NamesIter = VecIntoIter<(Bytes, Self::UpgradeIdentifier)>; + type UpgradeIdentifier = u8; // Protocol version + + #[inline] + fn protocol_names(&self) -> Self::NamesIter { + // Report each version as an individual protocol. + self.supported_versions.iter().map(|&(ver, _)| { + let num = ver.to_string(); + let mut name = self.base_name.clone(); + name.extend_from_slice(num.as_bytes()); + (name, ver) + }).collect::>().into_iter() + } + + type Output = RegisteredProtocolOutput; + type MultiaddrFuture = Maf; + type Future = future::FutureResult<(Self::Output, Self::MultiaddrFuture), IoError>; + + #[allow(deprecated)] + fn upgrade( + self, + socket: C, + protocol_version: Self::UpgradeIdentifier, + endpoint: Endpoint, + remote_addr: Maf + ) -> Self::Future { + let packet_count = self.supported_versions + .iter() + .find(|&(v, _)| *v == protocol_version) + .expect("negotiated protocol version that wasn't advertised ; \ + programmer error") + .1; + + // This function is called whenever we successfully negotiated a + // protocol with a remote (both if initiated by us or by the remote) + + // This channel is used to send outgoing packets to the custom_data + // for this open substream. + let (msg_tx, msg_rx) = mpsc::unbounded(); + + // Build the sink for outgoing network bytes, and the stream for + // incoming instructions. `stream` implements `Stream`. + enum Message { + /// Received data from the network. + RecvSocket(BytesMut), + /// Data to send to the network. + /// The packet_id must already be inside the `Bytes`. + SendReq(Bytes), + /// The socket has been closed. + Finished, + } + + let (sink, stream) = { + let framed = AsyncRead::framed(socket, VarintCodec::default()); + let msg_rx = msg_rx.map(Message::SendReq) + .map_err(|()| unreachable!("mpsc::UnboundedReceiver never errors")); + let (sink, stream) = framed.split(); + let stream = stream.map(Message::RecvSocket) + .chain(stream::once(Ok(Message::Finished))); + (sink, msg_rx.select(stream)) + }; + + let incoming = stream::unfold((sink, stream, false), move |(sink, stream, finished)| { + if finished { + return None + } + + Some(stream + .into_future() + .map_err(|(err, _)| err) + .and_then(move |(message, stream)| + match message { + Some(Message::RecvSocket(mut data)) => { + // The `data` should be prefixed by the packet ID, + // therefore an empty packet is invalid. + if data.is_empty() { + debug!(target: "sub-libp2p", "ignoring incoming \ + packet because it was empty"); + let f = future::ok((None, (sink, stream, false))); + return future::Either::A(f) + } + + let packet_id = data[0]; + let data = data.split_off(1); + + if packet_id >= packet_count { + debug!(target: "sub-libp2p", "ignoring incoming packet \ + because packet_id {} is too large", packet_id); + let f = future::ok((None, (sink, stream, false))); + future::Either::A(f) + } else { + let out = Some((packet_id, data.freeze())); + let f = future::ok((out, (sink, stream, false))); + future::Either::A(f) + } + }, + + Some(Message::SendReq(data)) => { + let fut = sink.send(data) + .map(move |sink| (None, (sink, stream, false))); + future::Either::B(fut) + }, + + Some(Message::Finished) | None => { + let f = future::ok((None, (sink, stream, true))); + future::Either::A(f) + }, + } + )) + }).filter_map(|v| v); + + let out = RegisteredProtocolOutput { + custom_data: self.custom_data, + protocol_id: self.id, + endpoint, + protocol_version: protocol_version, + outgoing: msg_tx, + incoming: Box::new(incoming), + }; + + future::ok((out, remote_addr)) + } +} + +// Connection upgrade for all the protocols contained in it. +#[derive(Clone)] +pub struct RegisteredProtocols(pub Vec>); + +impl RegisteredProtocols { + /// Finds a protocol in the list by its id. + pub fn find_protocol(&self, protocol: ProtocolId) + -> Option<&RegisteredProtocol> { + self.0.iter().find(|p| p.id == protocol) + } + + /// Returns true if the given protocol is in the list. + pub fn has_protocol(&self, protocol: ProtocolId) -> bool { + self.0.iter().any(|p| p.id == protocol) + } +} + +impl Default for RegisteredProtocols { + fn default() -> Self { + RegisteredProtocols(Vec::new()) + } +} + +impl ConnectionUpgrade for RegisteredProtocols +where C: AsyncRead + AsyncWrite + 'static, // TODO: 'static :-/ + Maf: Future + 'static, // TODO: 'static :( +{ + type NamesIter = VecIntoIter<(Bytes, Self::UpgradeIdentifier)>; + type UpgradeIdentifier = (usize, + as ConnectionUpgrade>::UpgradeIdentifier); + + fn protocol_names(&self) -> Self::NamesIter { + // We concat the lists of `RegisteredProtocol::protocol_names` for + // each protocol. + self.0.iter().enumerate().flat_map(|(n, proto)| + ConnectionUpgrade::::protocol_names(proto) + .map(move |(name, id)| (name, (n, id))) + ).collect::>().into_iter() + } + + type Output = as ConnectionUpgrade>::Output; + type MultiaddrFuture = as + ConnectionUpgrade>::MultiaddrFuture; + type Future = as ConnectionUpgrade>::Future; + + #[inline] + fn upgrade( + self, + socket: C, + upgrade_identifier: Self::UpgradeIdentifier, + endpoint: Endpoint, + remote_addr: Maf + ) -> Self::Future { + let (protocol_index, inner_proto_id) = upgrade_identifier; + self.0.into_iter() + .nth(protocol_index) + .expect("invalid protocol index ; programmer logic error") + .upgrade(socket, inner_proto_id, endpoint, remote_addr) + } +} diff --git a/substrate/network-libp2p/src/error.rs b/substrate/network-libp2p/src/error.rs new file mode 100644 index 0000000000000..d095858b12203 --- /dev/null +++ b/substrate/network-libp2p/src/error.rs @@ -0,0 +1,221 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +use std::{io, net, fmt}; +use libc::{ENFILE, EMFILE}; +use io::IoError; +use ethkey; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum DisconnectReason +{ + DisconnectRequested, + TCPError, + BadProtocol, + UselessPeer, + TooManyPeers, + DuplicatePeer, + IncompatibleProtocol, + NullIdentity, + ClientQuit, + UnexpectedIdentity, + LocalIdentity, + PingTimeout, + Unknown, +} + +impl DisconnectReason { + pub fn from_u8(n: u8) -> DisconnectReason { + match n { + 0 => DisconnectReason::DisconnectRequested, + 1 => DisconnectReason::TCPError, + 2 => DisconnectReason::BadProtocol, + 3 => DisconnectReason::UselessPeer, + 4 => DisconnectReason::TooManyPeers, + 5 => DisconnectReason::DuplicatePeer, + 6 => DisconnectReason::IncompatibleProtocol, + 7 => DisconnectReason::NullIdentity, + 8 => DisconnectReason::ClientQuit, + 9 => DisconnectReason::UnexpectedIdentity, + 10 => DisconnectReason::LocalIdentity, + 11 => DisconnectReason::PingTimeout, + _ => DisconnectReason::Unknown, + } + } +} + +impl fmt::Display for DisconnectReason { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::DisconnectReason::*; + + let msg = match *self { + DisconnectRequested => "disconnect requested", + TCPError => "TCP error", + BadProtocol => "bad protocol", + UselessPeer => "useless peer", + TooManyPeers => "too many peers", + DuplicatePeer => "duplicate peer", + IncompatibleProtocol => "incompatible protocol", + NullIdentity => "null identity", + ClientQuit => "client quit", + UnexpectedIdentity => "unexpected identity", + LocalIdentity => "local identity", + PingTimeout => "ping timeout", + Unknown => "unknown", + }; + + f.write_str(msg) + } +} + +error_chain! { + foreign_links { + SocketIo(IoError) #[doc = "Socket IO error."]; + } + + errors { + #[doc = "Error concerning the network address parsing subsystem."] + AddressParse { + description("Failed to parse network address"), + display("Failed to parse network address"), + } + + #[doc = "Error concerning the network address resolution subsystem."] + AddressResolve(err: Option) { + description("Failed to resolve network address"), + display("Failed to resolve network address {}", err.as_ref().map_or("".to_string(), |e| e.to_string())), + } + + #[doc = "Authentication failure"] + Auth { + description("Authentication failure"), + display("Authentication failure"), + } + + #[doc = "Unrecognised protocol"] + BadProtocol { + description("Bad protocol"), + display("Bad protocol"), + } + + #[doc = "Expired message"] + Expired { + description("Expired message"), + display("Expired message"), + } + + #[doc = "Peer not found"] + PeerNotFound { + description("Peer not found"), + display("Peer not found"), + } + + #[doc = "Peer is disconnected"] + Disconnect(reason: DisconnectReason) { + description("Peer disconnected"), + display("Peer disconnected: {}", reason), + } + + #[doc = "Invalid node id"] + InvalidNodeId { + description("Invalid node id"), + display("Invalid node id"), + } + + #[doc = "Packet size is over the protocol limit"] + OversizedPacket { + description("Packet is too large"), + display("Packet is too large"), + } + + #[doc = "Reached system resource limits for this process"] + ProcessTooManyFiles { + description("Too many open files in process."), + display("Too many open files in this process. Check your resource limits and restart parity"), + } + + #[doc = "Reached system wide resource limits"] + SystemTooManyFiles { + description("Too many open files on system."), + display("Too many open files on system. Consider closing some processes/release some file handlers or increas the system-wide resource limits and restart parity."), + } + + #[doc = "An unknown IO error occurred."] + Io(err: io::Error) { + description("IO Error"), + display("Unexpected IO error: {}", err), + } + } +} + +impl From for Error { + fn from(err: io::Error) -> Self { + match err.raw_os_error() { + Some(ENFILE) => ErrorKind::ProcessTooManyFiles.into(), + Some(EMFILE) => ErrorKind::SystemTooManyFiles.into(), + _ => Error::from_kind(ErrorKind::Io(err)) + } + } +} + +impl From for Error { + fn from(_err: ethkey::Error) -> Self { + ErrorKind::Auth.into() + } +} + +impl From for Error { + fn from(_err: ethkey::crypto::Error) -> Self { + ErrorKind::Auth.into() + } +} + +impl From for Error { + fn from(_err: net::AddrParseError) -> Self { ErrorKind::AddressParse.into() } +} + +#[test] +fn test_errors() { + assert_eq!(DisconnectReason::ClientQuit, DisconnectReason::from_u8(8)); + let mut r = DisconnectReason::DisconnectRequested; + for i in 0 .. 20 { + r = DisconnectReason::from_u8(i); + } + assert_eq!(DisconnectReason::Unknown, r); +} + +#[test] +fn test_io_errors() { + use libc::{EMFILE, ENFILE}; + + assert_matches!( + >::from( + io::Error::from_raw_os_error(ENFILE) + ).kind(), + ErrorKind::ProcessTooManyFiles); + + assert_matches!( + >::from( + io::Error::from_raw_os_error(EMFILE) + ).kind(), + ErrorKind::SystemTooManyFiles); + + assert_matches!( + >::from( + io::Error::from_raw_os_error(0) + ).kind(), + ErrorKind::Io(_)); +} diff --git a/substrate/network-libp2p/src/lib.rs b/substrate/network-libp2p/src/lib.rs new file mode 100644 index 0000000000000..cd00cc4b63fcb --- /dev/null +++ b/substrate/network-libp2p/src/lib.rs @@ -0,0 +1,66 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see .? + +#![recursion_limit="128"] +#![type_length_limit = "268435456"] + +extern crate parking_lot; +extern crate fnv; +extern crate futures; +extern crate tokio; +extern crate tokio_io; +extern crate tokio_timer; +extern crate ethkey; +extern crate libc; +extern crate libp2p; +extern crate rand; +extern crate bytes; +extern crate varint; + +extern crate ethcore_io as io; +extern crate ethereum_types; +extern crate ipnetwork; + +#[macro_use] +extern crate error_chain; +#[macro_use] +extern crate log; +#[cfg(test)] #[macro_use] +extern crate assert_matches; + +pub use connection_filter::{ConnectionFilter, ConnectionDirection}; +pub use io::TimerToken; +pub use error::{Error, ErrorKind, DisconnectReason}; +pub use traits::*; + +mod connection_filter; +mod custom_proto; +mod error; +mod network_state; +mod service; +mod timeouts; +mod traits; +mod transport; + +pub use service::NetworkService; + +/// Check if node url is valid +pub fn validate_node_url(url: &str) -> Result<(), Error> { + match url.parse::() { + Ok(_) => Ok(()), + Err(_) => Err(ErrorKind::InvalidNodeId.into()), + } +} diff --git a/substrate/network-libp2p/src/network_state.rs b/substrate/network-libp2p/src/network_state.rs new file mode 100644 index 0000000000000..c7285590a3180 --- /dev/null +++ b/substrate/network-libp2p/src/network_state.rs @@ -0,0 +1,994 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see .? + +use bytes::Bytes; +use fnv::{FnvHashMap, FnvHashSet}; +use futures::sync::mpsc; +use libp2p::core::{multiaddr::ToMultiaddr, Multiaddr, AddrComponent, Endpoint, UniqueConnec}; +use libp2p::core::{UniqueConnecState, PeerId, PublicKey}; +use libp2p::kad::KadConnecController; +use libp2p::peerstore::{Peerstore, PeerAccess}; +use libp2p::peerstore::json_peerstore::JsonPeerstore; +use libp2p::peerstore::memory_peerstore::MemoryPeerstore; +use libp2p::ping::Pinger; +use libp2p::secio; +use {Error, ErrorKind, NetworkConfiguration, NonReservedPeerMode}; +use {NodeIndex, ProtocolId, SessionInfo}; +use parking_lot::{Mutex, RwLock}; +use rand::{self, Rng}; +use std::fs; +use std::io::{Error as IoError, ErrorKind as IoErrorKind, Read, Write}; +use std::path::Path; +use std::sync::atomic; +use std::{thread, time}; +use std::time::{Duration, Instant}; + +// File where the peers are stored. +const NODES_FILE: &str = "nodes.json"; +// File where the private key is stored. +const SECRET_FILE: &str = "secret"; +// Duration during which a peer is disabled. +const PEER_DISABLE_DURATION: Duration = Duration::from_secs(5 * 60); + +// Common struct shared throughout all the components of the service. +pub struct NetworkState { + /// Contains the information about the network. + node_store: NodeStore, + + /// Active connections. + connections: RwLock, + + /// Maximum incoming peers. + max_incoming_peers: u32, + /// Maximum outgoing peers. + max_outgoing_peers: u32, + + /// If true, only reserved peers can connect. + reserved_only: atomic::AtomicBool, + /// List of the IDs of the reserved peers. + reserved_peers: RwLock>, + + /// Each node we discover gets assigned a new unique ID. This ID increases linearly. + next_node_index: atomic::AtomicUsize, + + /// List of the IDs of the disabled peers. These peers will see their + /// connections refused. Includes the time when the disabling expires. + disabled_nodes: Mutex>, + + /// Local private key. + local_private_key: secio::SecioKeyPair, + /// Local public key. + local_public_key: PublicKey, +} + +enum NodeStore { + /// Peers are stored in memory. Nothing is stored on disk. + Memory(MemoryPeerstore), + /// Peers are stored in a JSON file on the disk. + Json(JsonPeerstore), +} + +struct Connections { + /// For each libp2p peer ID, the ID of the peer in the API we expose. + /// Also corresponds to the index in `info_by_peer`. + peer_by_nodeid: FnvHashMap, + + /// For each peer ID, information about our connection to this peer. + info_by_peer: FnvHashMap, +} + +struct PeerConnectionInfo { + /// A list of protocols, and the potential corresponding connection. + /// The `UniqueConnec` contains a sender and the protocol version. + /// The sender can be used to transmit data for the remote. Note that the + /// packet_id has to be inside the `Bytes`. + protocols: Vec<(ProtocolId, UniqueConnec<(mpsc::UnboundedSender, u8)>)>, + + /// The Kademlia connection to this node. + kad_connec: UniqueConnec, + + /// The ping connection to this node. + ping_connec: UniqueConnec, + + /// Id of the peer. + id: PeerId, + + /// True if this connection was initiated by us. + /// Note that it is theoretically possible that we dial the remote at the + /// same time they dial us, in which case the protocols may be dispatched + /// between both connections, and in which case the value here will be racy. + originated: bool, + + /// Latest known ping duration. + ping: Mutex>, + + /// The client version of the remote, or `None` if not known. + client_version: Option, + + /// The multiaddress of the remote, or `None` if not known. + remote_address: Option, + + /// The local multiaddress used to communicate with the remote, or `None` + /// if not known. + local_address: Option, +} + +/// Simplified, POD version of PeerConnectionInfo. +#[derive(Debug, Clone)] +pub struct PeerInfo { + /// Id of the peer. + pub id: PeerId, + + /// True if this connection was initiated by us. + /// Note that it is theoretically possible that we dial the remote at the + /// same time they dial us, in which case the protocols may be dispatched + /// between both connections, and in which case the value here will be racy. + pub originated: bool, + + /// Latest known ping duration. + pub ping: Option, + + /// The client version of the remote, or `None` if not known. + pub client_version: Option, + + /// The multiaddress of the remote, or `None` if not known. + pub remote_address: Option, + + /// The local multiaddress used to communicate with the remote, or `None` + /// if not known. + pub local_address: Option, +} + +impl<'a> From<&'a PeerConnectionInfo> for PeerInfo { + fn from(i: &'a PeerConnectionInfo) -> PeerInfo { + PeerInfo { + id: i.id.clone(), + originated: i.originated, + ping: i.ping.lock().clone(), + client_version: i.client_version.clone(), + remote_address: i.remote_address.clone(), + local_address: i.local_address.clone(), + } + } +} + +impl NetworkState { + pub fn new(config: &NetworkConfiguration) -> Result { + // Private and public keys configuration. + let local_private_key = obtain_private_key(&config)?; + let local_public_key = local_private_key.to_public_key(); + + // Build the storage for peers, including the bootstrap nodes. + let node_store = if let Some(ref path) = config.net_config_path { + let path = Path::new(path).join(NODES_FILE); + if let Ok(node_store) = JsonPeerstore::new(path.clone()) { + debug!(target: "sub-libp2p", "Initialized peer store for JSON file {:?}", path); + NodeStore::Json(node_store) + } else { + warn!(target: "sub-libp2p", "Failed to open peer storage {:?}; peers file will be reset", path); + fs::remove_file(&path).expect("Failed deleting peers.json"); + + // we check for about 1s if the file was really deleted and move on + for _x in 0..200 { + if !Path::new(&path).exists() { + break; + } else { + debug!("Waiting for effective deletion of invalid/outdate peers.json"); + thread::sleep(time::Duration::from_millis(5)); + } + } + + if let Ok(peerstore) = JsonPeerstore::new(path.clone()) { + debug!("peers.json reset"); + NodeStore::Json(peerstore) + } else { + warn!(target: "sub-libp2p", + "Failed to reset peer storage {:?}; peers change will not be saved", + path + ); + NodeStore::Memory(MemoryPeerstore::empty()) + } + } + } else { + debug!(target: "sub-libp2p", "No peers file configured ; peers won't be saved"); + NodeStore::Memory(MemoryPeerstore::empty()) + }; + + let reserved_peers = { + let mut reserved_peers = FnvHashSet::with_capacity_and_hasher( + config.reserved_nodes.len(), + Default::default() + ); + for peer in config.reserved_nodes.iter() { + let id = parse_and_add_to_node_store(peer, &node_store)?; + reserved_peers.insert(id); + } + RwLock::new(reserved_peers) + }; + + let expected_max_peers = config.max_peers as usize + config.reserved_nodes.len(); + + Ok(NetworkState { + node_store, + max_outgoing_peers: config.min_peers, + max_incoming_peers: config.max_peers.saturating_sub(config.min_peers), + connections: RwLock::new(Connections { + peer_by_nodeid: FnvHashMap::with_capacity_and_hasher(expected_max_peers, Default::default()), + info_by_peer: FnvHashMap::with_capacity_and_hasher(expected_max_peers, Default::default()), + }), + reserved_only: atomic::AtomicBool::new(false), + reserved_peers, + next_node_index: atomic::AtomicUsize::new(0), + disabled_nodes: Mutex::new(Default::default()), + local_private_key, + local_public_key, + }) + } + + /// Returns the private key of the local node. + pub fn local_private_key(&self) -> &secio::SecioKeyPair { + &self.local_private_key + } + + /// Returns the public key of the local node. + pub fn local_public_key(&self) -> &PublicKey { + &self.local_public_key + } + + /// Returns the ID of a random peer of the network. + /// + /// Returns `None` if we don't know any peer. + pub fn random_peer(&self) -> Option { + // TODO: optimize by putting the operation directly in the node_store + // https://github.com/libp2p/rust-libp2p/issues/316 + let peers = match self.node_store { + NodeStore::Memory(ref mem) => + mem.peers().collect::>(), + NodeStore::Json(ref json) => + json.peers().collect::>(), + }; + + if peers.is_empty() { + return None + } + + let nth = rand::random::() % peers.len(); + Some(peers[nth].clone()) + } + + /// Returns all the IDs of the peers on the network we have knowledge of. + /// + /// This includes peers we are not connected to. + pub fn known_peers(&self) -> impl Iterator { + match self.node_store { + NodeStore::Memory(ref mem) => + mem.peers().collect::>().into_iter(), + NodeStore::Json(ref json) => + json.peers().collect::>().into_iter(), + } + } + + /// Returns true if we are connected to any peer at all. + pub fn has_connected_peer(&self) -> bool { + !self.connections.read().peer_by_nodeid.is_empty() + } + + /// Get a list of all connected peers by id. + pub fn connected_peers(&self) -> Vec { + self.connections.read().peer_by_nodeid.values().cloned().collect() + } + + /// Returns true if the given `NodeIndex` is valid. + /// + /// `NodeIndex`s are never reused, so once this function returns `false` it + /// will never return `true` again for the same `NodeIndex`. + pub fn is_peer_connected(&self, peer: NodeIndex) -> bool { + self.connections.read().info_by_peer.contains_key(&peer) + } + + /// Reports the ping of the peer. Returned later by `session_info()`. + /// No-op if the `who` is not valid/expired. + pub fn report_ping_duration(&self, who: NodeIndex, ping: Duration) { + let mut connections = self.connections.write(); + let info = match connections.info_by_peer.get_mut(&who) { + Some(info) => info, + None => return, + }; + *info.ping.lock() = Some(ping); + } + + /// If we're connected to a peer with the given protocol, returns + /// information about the connection. Otherwise, returns `None`. + pub fn session_info(&self, peer: NodeIndex, protocol: ProtocolId) -> Option { + let connections = self.connections.read(); + let info = match connections.info_by_peer.get(&peer) { + Some(info) => info, + None => return None, + }; + + let protocol_version = match info.protocols.iter().find(|&(ref p, _)| p == &protocol) { + Some(&(_, ref unique_connec)) => + if let Some(val) = unique_connec.poll() { + val.1 as u32 + } else { + return None + } + None => return None, + }; + + let ping = info.ping.lock().clone(); + + Some(SessionInfo { + id: None, // TODO: ???? what to do??? wrong format! + client_version: info.client_version.clone().take().unwrap_or(String::new()), + protocol_version, + capabilities: Vec::new(), // TODO: list of supported protocols ; hard + peer_capabilities: Vec::new(), // TODO: difference with `peer_capabilities`? + ping, + originated: info.originated, + remote_address: info.remote_address.as_ref().map(|a| a.to_string()) + .unwrap_or(String::new()), + local_address: info.local_address.as_ref().map(|a| a.to_string()) + .unwrap_or(String::new()), + }) + } + + /// If we're connected to a peer with the given protocol, returns the + /// protocol version. Otherwise, returns `None`. + pub fn protocol_version(&self, peer: NodeIndex, protocol: ProtocolId) -> Option { + let connections = self.connections.read(); + let peer = match connections.info_by_peer.get(&peer) { + Some(peer) => peer, + None => return None, + }; + + peer.protocols.iter() + .find(|p| p.0 == protocol) + .and_then(|p| p.1.poll()) + .map(|(_, version)| version) + } + + /// Equivalent to `session_info(peer).map(|info| info.client_version)`. + pub fn peer_client_version(&self, peer: NodeIndex, protocol: ProtocolId) -> Option { + // TODO: implement more directly, without going through `session_info` + self.session_info(peer, protocol) + .map(|info| info.client_version) + } + + /// Adds an address discovered by Kademlia. + /// Note that we don't have to be connected to a peer to add an address. + pub fn add_kad_discovered_addr(&self, node_id: &PeerId, addr: Multiaddr) { + trace!(target: "sub-libp2p", "Peer store: adding address {} for {:?}", + addr, node_id); + match self.node_store { + NodeStore::Memory(ref mem) => + mem.peer_or_create(node_id) + .add_addr(addr, Duration::from_secs(3600)), + NodeStore::Json(ref json) => + json.peer_or_create(node_id) + .add_addr(addr, Duration::from_secs(3600)), + } + } + + /// Signals that an address doesn't match the corresponding node ID. + /// This removes the address from the peer store, so that it is not + /// returned by `addrs_of_peer` again in the future. + pub fn set_invalid_kad_address(&self, node_id: &PeerId, addr: &Multiaddr) { + // TODO: blacklist the address? + match self.node_store { + NodeStore::Memory(ref mem) => + if let Some(mut peer) = mem.peer(node_id) { + peer.rm_addr(addr.clone()) // TODO: cloning necessary? + }, + NodeStore::Json(ref json) => + if let Some(mut peer) = json.peer(node_id) { + peer.rm_addr(addr.clone()) // TODO: cloning necessary? + }, + } + } + + /// Returns the known multiaddresses of a peer. + pub fn addrs_of_peer(&self, node_id: &PeerId) -> Vec { + match self.node_store { + NodeStore::Memory(ref mem) => + mem.peer(node_id) + .into_iter() + .flat_map(|p| p.addrs()) + .collect::>(), + NodeStore::Json(ref json) => + json.peer(node_id) + .into_iter() + .flat_map(|p| p.addrs()) + .collect::>(), + } + } + + /// Sets information about a peer. + pub fn set_peer_info( + &self, + node_id: PeerId, + endpoint: Endpoint, + client_version: String, + local_addr: Multiaddr, + remote_addr: Multiaddr + ) -> Result { + let mut connections = self.connections.write(); + let who = accept_connection(&mut connections, &self.next_node_index, + node_id.clone(), endpoint)?; + let infos = connections.info_by_peer.get_mut(&who) + .expect("Newly-created peer id is always valid"); + + infos.client_version = Some(client_version); + infos.remote_address = Some(remote_addr); + infos.local_address = Some(local_addr); + + Ok(who) + } + + /// Adds a peer to the internal peer store. + /// Returns an error if the peer address is invalid. + pub fn add_peer(&self, peer: &str) -> Result { + parse_and_add_to_node_store(peer, &self.node_store) + } + + /// Adds a reserved peer to the list of reserved peers. + /// Returns an error if the peer address is invalid. + pub fn add_reserved_peer(&self, peer: &str) -> Result<(), Error> { + let id = parse_and_add_to_node_store(peer, &self.node_store)?; + self.reserved_peers.write().insert(id); + Ok(()) + } + + /// Removes the peer from the list of reserved peers. If we're in reserved mode, drops any + /// active connection to this peer. + /// Returns an error if the peer address is invalid. + pub fn remove_reserved_peer(&self, peer: &str) -> Result<(), Error> { + let id = parse_and_add_to_node_store(peer, &self.node_store)?; + self.reserved_peers.write().remove(&id); + + // Dropping the peer if we're in reserved mode. + if self.reserved_only.load(atomic::Ordering::SeqCst) { + let mut connections = self.connections.write(); + if let Some(who) = connections.peer_by_nodeid.remove(&id) { + connections.info_by_peer.remove(&who); + } + } + + Ok(()) + } + + /// Set the non-reserved peer mode. + pub fn set_non_reserved_mode(&self, mode: NonReservedPeerMode) { + match mode { + NonReservedPeerMode::Accept => + self.reserved_only.store(false, atomic::Ordering::SeqCst), + NonReservedPeerMode::Deny => + // TODO: drop existing peers? + self.reserved_only.store(true, atomic::Ordering::SeqCst), + } + } + + /// Returns the number of new outgoing custom connections to peers to + /// open. This takes into account the number of active peers. + pub fn should_open_outgoing_custom_connections(&self) -> u32 { + if self.reserved_only.load(atomic::Ordering::Relaxed) { + 0 + } else { + let num_open_custom_connections = num_open_custom_connections(&self.connections.read(), &self.reserved_peers.read()); + self.max_outgoing_peers.saturating_sub(num_open_custom_connections.unreserved_outgoing) + } + } + + /// Returns true if we are connected to the given node. + pub fn has_connection(&self, node_id: &PeerId) -> bool { + let connections = self.connections.read(); + connections.peer_by_nodeid.contains_key(node_id) + } + + /// Obtains the `UniqueConnec` corresponding to the Kademlia connection to a peer. + pub fn kad_connection( + &self, + node_id: PeerId + ) -> Result<(NodeIndex, UniqueConnec), IoError> { + // TODO: check that the peer is disabled? should disabling a peer also prevent + // kad from working? + let mut connections = self.connections.write(); + let who = accept_connection(&mut connections, &self.next_node_index, + node_id, Endpoint::Listener)?; + let infos = connections.info_by_peer.get_mut(&who) + .expect("Newly-created peer id is always valid"); + let connec = infos.kad_connec.clone(); + Ok((who, connec)) + } + + /// Obtains the `UniqueConnec` corresponding to the Ping connection to a peer. + pub fn ping_connection( + &self, + node_id: PeerId + ) -> Result<(NodeIndex, UniqueConnec), IoError> { + let mut connections = self.connections.write(); + let who = accept_connection(&mut connections, &self.next_node_index, + node_id, Endpoint::Listener)?; + let infos = connections.info_by_peer.get_mut(&who) + .expect("Newly-created peer id is always valid"); + let connec = infos.ping_connec.clone(); + Ok((who, connec)) + } + + /// Cleans up inactive connections and returns a list of + /// connections to ping. + pub fn cleanup_and_prepare_ping( + &self + ) -> Vec<(NodeIndex, PeerId, UniqueConnec)> { + let mut connections = self.connections.write(); + let connections = &mut *connections; + let peer_by_nodeid = &mut connections.peer_by_nodeid; + let info_by_peer = &mut connections.info_by_peer; + + let mut ret = Vec::with_capacity(info_by_peer.len()); + info_by_peer.retain(|&who, infos| { + // Remove the peer if neither Kad nor any protocol is alive. + if !infos.kad_connec.is_alive() && + !infos.protocols.iter().any(|(_, conn)| conn.is_alive()) + { + peer_by_nodeid.remove(&infos.id); + trace!(target: "sub-libp2p", "Cleaning up expired peer \ + #{:?} ({:?})", who, infos.id); + return false; + } + + ret.push((who, infos.id.clone(), infos.ping_connec.clone())); + true + }); + ret + } + + /// Try to add a new connection to a node in the list. + /// + /// Returns a `NodeIndex` to allow further interfacing with this connection. + /// Note that all `NodeIndex`s are unique and never reused. + /// + /// Can return an error if we are refusing the connection to the remote. + /// + /// You must pass an `UnboundedSender` which will be used by the `send` + /// method. Actually sending the data is not covered by this code. + /// + /// The various methods of the `NetworkState` that close a connection do + /// so by dropping this sender. + pub fn custom_proto( + &self, + node_id: PeerId, + protocol_id: ProtocolId, + endpoint: Endpoint, + ) -> Result<(NodeIndex, UniqueConnec<(mpsc::UnboundedSender, u8)>), IoError> { + let mut connections = self.connections.write(); + + if is_peer_disabled(&self.disabled_nodes, &node_id) { + debug!(target: "sub-libp2p", "Refusing node {:?} because it was disabled", node_id); + return Err(IoError::new(IoErrorKind::PermissionDenied, "disabled peer")) + } + + let who = accept_connection(&mut connections, &self.next_node_index, + node_id.clone(), endpoint)?; + + let num_open_connections = num_open_custom_connections(&connections, &self.reserved_peers.read()); + + let infos = connections.info_by_peer.get_mut(&who) + .expect("Newly-created peer id is always valid"); + + let node_is_reserved = self.reserved_peers.read().contains(&infos.id); + if !node_is_reserved { + if self.reserved_only.load(atomic::Ordering::Relaxed) || + (endpoint == Endpoint::Listener && + num_open_connections.unreserved_incoming >= self.max_incoming_peers) || + (endpoint == Endpoint::Dialer && + num_open_connections.unreserved_outgoing >= self.max_outgoing_peers) + { + debug!(target: "sub-libp2p", "Refusing node {:?} because we reached the max number of peers", node_id); + return Err(IoError::new(IoErrorKind::PermissionDenied, "maximum number of peers reached")) + } + } + + if let Some((_, ref uconn)) = infos.protocols.iter().find(|&(prot, _)| prot == &protocol_id) { + return Ok((who, uconn.clone())) + } + + let unique_connec = UniqueConnec::empty(); + infos.protocols.push((protocol_id.clone(), unique_connec.clone())); + Ok((who, unique_connec)) + } + + /// Sends some data to the given peer, using the sender that was passed + /// to the `UniqueConnec` of `custom_proto`. + pub fn send(&self, protocol: ProtocolId, who: NodeIndex, message: Bytes) -> Result<(), Error> { + if let Some(peer) = self.connections.read().info_by_peer.get(&who) { + let sender = peer.protocols.iter().find(|elem| elem.0 == protocol) + .and_then(|e| e.1.poll()) + .map(|e| e.0); + if let Some(sender) = sender { + sender.unbounded_send(message) + .map_err(|err| ErrorKind::Io(IoError::new(IoErrorKind::Other, err)))?; + Ok(()) + } else { + // We are connected to this peer, but not with the current + // protocol. + debug!(target: "sub-libp2p", + "Tried to send message to peer {} for which we aren't connected with the requested protocol", + who + ); + return Err(ErrorKind::PeerNotFound.into()) + } + } else { + debug!(target: "sub-libp2p", "Tried to send message to invalid peer ID {}", who); + return Err(ErrorKind::PeerNotFound.into()) + } + } + + /// Get the info on a peer, if there's an active connection. + pub fn peer_info(&self, who: NodeIndex) -> Option { + self.connections.read().info_by_peer.get(&who).map(Into::into) + } + + /// Reports that an attempt to make a low-level ping of the peer failed. + pub fn report_ping_failed(&self, who: NodeIndex) { + self.drop_peer(who); + } + + /// Disconnects a peer, if a connection exists (ie. drops the Kademlia + /// controller, and the senders that were stored in the `UniqueConnec` of + /// `custom_proto`). + pub fn drop_peer(&self, who: NodeIndex) { + let mut connections = self.connections.write(); + if let Some(peer_info) = connections.info_by_peer.remove(&who) { + trace!(target: "sub-libp2p", "Destroying peer #{} {:?} ; kademlia = {:?} ; num_protos = {:?}", + who, + peer_info.id, + peer_info.kad_connec.is_alive(), + peer_info.protocols.iter().filter(|c| c.1.is_alive()).count()); + let old = connections.peer_by_nodeid.remove(&peer_info.id); + debug_assert_eq!(old, Some(who)); + } + } + + /// Disconnects all the peers. + /// This destroys all the Kademlia controllers and the senders that were + /// stored in the `UniqueConnec` of `custom_proto`. + pub fn disconnect_all(&self) { + let mut connec = self.connections.write(); + *connec = Connections { + info_by_peer: FnvHashMap::with_capacity_and_hasher( + connec.peer_by_nodeid.capacity(), Default::default()), + peer_by_nodeid: FnvHashMap::with_capacity_and_hasher( + connec.peer_by_nodeid.capacity(), Default::default()), + }; + } + + /// Disables a peer for `PEER_DISABLE_DURATION`. This adds the peer to the + /// list of disabled peers, and drops any existing connections if + /// necessary (ie. drops the sender that was stored in the `UniqueConnec` + /// of `custom_proto`). + pub fn ban_peer(&self, who: NodeIndex, reason: &str) { + // TODO: what do we do if the peer is reserved? + // TODO: same logging as in disconnect_peer + let mut connections = self.connections.write(); + let peer_info = if let Some(peer_info) = connections.info_by_peer.remove(&who) { + if let (&Some(ref client_version), &Some(ref remote_address)) = (&peer_info.client_version, &peer_info.remote_address) { + info!(target: "network", "Peer {} (version: {}, address: {}) disabled. {}", who, client_version, remote_address, reason); + } else { + info!(target: "network", "Peer {} disabled. {}", who, reason); + } + let old = connections.peer_by_nodeid.remove(&peer_info.id); + debug_assert_eq!(old, Some(who)); + peer_info + } else { + return + }; + + drop(connections); + let timeout = Instant::now() + PEER_DISABLE_DURATION; + self.disabled_nodes.lock().insert(peer_info.id.clone(), timeout); + } + + /// Flushes the caches to the disk. + /// + /// This is done in an atomical way, so that an error doesn't corrupt + /// anything. + pub fn flush_caches_to_disk(&self) -> Result<(), IoError> { + match self.node_store { + NodeStore::Memory(_) => Ok(()), + NodeStore::Json(ref json) => + match json.flush() { + Ok(()) => { + debug!(target: "sub-libp2p", "Flushed JSON peer store to disk"); + Ok(()) + } + Err(err) => { + warn!(target: "sub-libp2p", "Failed to flush changes to JSON peer store: {}", err); + Err(err) + } + } + } + } +} + +impl Drop for NetworkState { + fn drop(&mut self) { + let _ = self.flush_caches_to_disk(); + } +} + +/// Assigns a `NodeIndex` to a node, or returns an existing ID if any exists. +/// +/// The function only accepts already-locked structs, so that we don't risk +/// any deadlock. +fn accept_connection( + connections: &mut Connections, + next_node_index: &atomic::AtomicUsize, + node_id: PeerId, + endpoint: Endpoint +) -> Result { + let peer_by_nodeid = &mut connections.peer_by_nodeid; + let info_by_peer = &mut connections.info_by_peer; + + let who = *peer_by_nodeid.entry(node_id.clone()).or_insert_with(|| { + let new_id = next_node_index.fetch_add(1, atomic::Ordering::Relaxed); + trace!(target: "sub-libp2p", "Creating new peer #{:?} for {:?}", new_id, node_id); + + info_by_peer.insert(new_id, PeerConnectionInfo { + protocols: Vec::new(), // TODO: Vec::with_capacity(num_registered_protocols), + kad_connec: UniqueConnec::empty(), + ping_connec: UniqueConnec::empty(), + id: node_id.clone(), + originated: endpoint == Endpoint::Dialer, + ping: Mutex::new(None), + client_version: None, + local_address: None, + remote_address: None, + }); + new_id + }); + + Ok(who) +} + +/// Returns true if a peer is disabled. +fn is_peer_disabled( + list: &Mutex>, + peer: &PeerId +) -> bool { + let mut list = list.lock(); + if let Some(timeout) = list.get(peer).cloned() { + if timeout > Instant::now() { + true + } else { + list.remove(peer); + false + } + } else { + false + } +} + +struct OpenCustomConnectionsNumbers { + /// Total number of open and pending connections. + pub total: u32, + /// Unreserved incoming number of open and pending connections. + pub unreserved_incoming: u32, + /// Unreserved outgoing number of open and pending connections. + pub unreserved_outgoing: u32, +} + +/// Returns the number of open and pending connections with +/// custom protocols. +fn num_open_custom_connections(connections: &Connections, reserved_peers: &FnvHashSet) -> OpenCustomConnectionsNumbers { + let filtered = connections + .info_by_peer + .values() + .filter(|info| + info.protocols.iter().any(|&(_, ref connec)| + match connec.state() { + UniqueConnecState::Pending | UniqueConnecState::Full => true, + _ => false + } + ) + ); + + let mut total: u32 = 0; + let mut unreserved_incoming: u32 = 0; + let mut unreserved_outgoing: u32 = 0; + + for info in filtered { + total += 1; + let node_is_reserved = reserved_peers.contains(&info.id); + if !node_is_reserved { + if !info.originated { + unreserved_incoming += 1; + } else { + unreserved_outgoing += 1; + } + } + } + + OpenCustomConnectionsNumbers { + total, + unreserved_incoming, + unreserved_outgoing, + } +} + +/// Parses an address of the form `/ip4/x.x.x.x/tcp/x/p2p/xxxxxx`, and adds it +/// to the given node_store. Returns the corresponding peer ID. +fn parse_and_add_to_node_store( + addr_str: &str, + node_store: &NodeStore +) -> Result { + + let mut addr = addr_str.to_multiaddr().map_err(|_| ErrorKind::AddressParse)?; + let who = match addr.pop() { + Some(AddrComponent::P2P(key)) | Some(AddrComponent::IPFS(key)) => + PeerId::from_bytes(key).map_err(|_| ErrorKind::AddressParse)?, + _ => return Err(ErrorKind::AddressParse.into()), + }; + + // Registering the bootstrap node with a TTL of 100000 years TODO: wrong + match node_store { + NodeStore::Memory(ref node_store) => + node_store + .peer_or_create(&who) + .set_addr_ttl(addr, Duration::from_secs(100000 * 365 * 24 * 3600)), + NodeStore::Json(ref node_store) => + node_store + .peer_or_create(&who) + .set_addr_ttl(addr, Duration::from_secs(100000 * 365 * 24 * 3600)), + } + + Ok(who) +} + +/// Obtains or generates the local private key using the configuration. +fn obtain_private_key(config: &NetworkConfiguration) + -> Result { + if let Some(ref secret) = config.use_secret { + // Key was specified in the configuration. + secio::SecioKeyPair::secp256k1_raw_key(&secret[..]) + .map_err(|err| IoError::new(IoErrorKind::InvalidData, err)) + + } else { + if let Some(ref path) = config.net_config_path { + fs::create_dir_all(Path::new(path))?; + + // Try fetch the key from a the file containing th esecret. + let secret_path = Path::new(path).join(SECRET_FILE); + match load_private_key_from_file(&secret_path) { + Ok(s) => Ok(s), + Err(err) => { + // Failed to fetch existing file ; generate a new key + trace!(target: "sub-libp2p", + "Failed to load existing secret key file {:?}, generating new key ; err = {:?}", + secret_path, + err + ); + Ok(gen_key_and_try_write_to_file(&secret_path)) + } + } + + } else { + // No path in the configuration, nothing we can do except generate + // a new key. + let mut key: [u8; 32] = [0; 32]; + rand::rngs::EntropyRng::new().fill(&mut key); + Ok(secio::SecioKeyPair::secp256k1_raw_key(&key) + .expect("randomly-generated key with correct len should always be valid")) + } + } +} + +/// Tries to load a private key from a file located at the given path. +fn load_private_key_from_file

(path: P) + -> Result + where P: AsRef + { + fs::File::open(path) + .and_then(|mut file| { + // We are in 2018 and there is still no method on `std::io::Read` + // that directly returns a `Vec`. + let mut buf = Vec::new(); + file.read_to_end(&mut buf).map(|_| buf) + }) + .and_then(|content| + secio::SecioKeyPair::secp256k1_raw_key(&content) + .map_err(|err| IoError::new(IoErrorKind::InvalidData, err)) + ) +} + +/// Generates a new secret key and tries to write it to the given file. +/// Doesn't error if we couldn't open or write to the file. +fn gen_key_and_try_write_to_file

(path: P) -> secio::SecioKeyPair + where P: AsRef { + let raw_key: [u8; 32] = rand::rngs::EntropyRng::new().gen(); + let secio_key = secio::SecioKeyPair::secp256k1_raw_key(&raw_key) + .expect("randomly-generated key with correct len should always be valid"); + + // And store the newly-generated key in the file if possible. + // Errors that happen while doing so are ignored. + match open_priv_key_file(&path) { + Ok(mut file) => + match file.write_all(&raw_key) { + Ok(()) => (), + Err(err) => warn!(target: "sub-libp2p", + "Failed to write secret key in file {:?} ; err = {:?}", + path.as_ref(), + err + ), + }, + Err(err) => warn!(target: "sub-libp2p", + "Failed to store secret key in file {:?} ; err = {:?}", + path.as_ref(), + err + ), + } + + secio_key +} + +/// Opens a file containing a private key in write mode. +#[cfg(unix)] +fn open_priv_key_file

(path: P) -> Result + where P: AsRef +{ + use std::os::unix::fs::OpenOptionsExt; + fs::OpenOptions::new() + .write(true) + .create_new(true) + .mode(256 | 128) // 0o600 in decimal + .open(path) +} +/// Opens a file containing a private key in write mode. +#[cfg(not(unix))] +fn open_priv_key_file

(path: P) -> Result + where P: AsRef +{ + fs::OpenOptions::new() + .write(true) + .create_new(true) + .open(path) +} + +#[cfg(test)] +mod tests { + use libp2p::core::{Endpoint, PublicKey}; + use network_state::NetworkState; + + #[test] + fn refuse_disabled_peer() { + let state = NetworkState::new(&Default::default()).unwrap(); + let example_peer = PublicKey::Rsa(vec![1, 2, 3, 4]).into_peer_id(); + + let (who, _) = state.custom_proto( + example_peer.clone(), + [1, 2, 3], + Endpoint::Dialer + ).unwrap(); + + state.ban_peer(who, "Just a test"); + + assert!(state.custom_proto( + example_peer.clone(), + [1, 2, 3], + Endpoint::Dialer + ).is_err()); + } +} diff --git a/substrate/network-libp2p/src/service.rs b/substrate/network-libp2p/src/service.rs new file mode 100644 index 0000000000000..ef86d2b4346b9 --- /dev/null +++ b/substrate/network-libp2p/src/service.rs @@ -0,0 +1,1412 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see .? + +use bytes::Bytes; +use {Error, ErrorKind, NetworkConfiguration, NetworkProtocolHandler}; +use {NonReservedPeerMode, NetworkContext, Severity, NodeIndex, ProtocolId}; +use parking_lot::{Mutex, RwLock}; +use libp2p; +use libp2p::multiaddr::{AddrComponent, Multiaddr}; +use libp2p::kad::{KadSystem, KadConnecConfig, KadSystemConfig}; +use libp2p::kad::{KadIncomingRequest, KadConnecController, KadPeer}; +use libp2p::kad::{KadConnectionType, KadQueryEvent}; +use libp2p::identify::{IdentifyInfo, IdentifyOutput, IdentifyTransportOutcome}; +use libp2p::identify::{IdentifyProtocolConfig, PeerIdTransport}; +use libp2p::core::{upgrade, Transport, MuxedTransport, ConnectionUpgrade}; +use libp2p::core::{Endpoint, PeerId as PeerstorePeerId, PublicKey}; +use libp2p::core::{SwarmController, UniqueConnecState}; +use libp2p::ping; +use libp2p::transport_timeout::TransportTimeout; +use {PacketId, SessionInfo, ConnectionFilter, TimerToken}; +use rand; +use std::io::{Error as IoError, ErrorKind as IoErrorKind}; +use std::iter; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +use std::sync::Arc; +use std::sync::mpsc as sync_mpsc; +use std::thread; +use std::time::{Duration, Instant}; +use futures::{future, Future, Stream, IntoFuture}; +use futures::sync::{mpsc, oneshot}; +use tokio::runtime::current_thread; +use tokio_io::{AsyncRead, AsyncWrite}; +use tokio_timer::{Interval, Deadline}; + +use custom_proto::{RegisteredProtocol, RegisteredProtocols}; +use custom_proto::RegisteredProtocolOutput; +use network_state::NetworkState; +use timeouts; +use transport; + +/// IO Service with networking. +pub struct NetworkService { + shared: Arc, + + /// Holds the networking-running background thread alive. The `Option` is + /// `None` if the service is stopped. + /// Sending a message on the channel will trigger the end of the + /// background thread. We can then wait on the join handle. + bg_thread: Mutex, thread::JoinHandle<()>)>>, +} + +/// Common struct shared throughout all the components of the service. +struct Shared { + /// Original configuration of the service. + config: NetworkConfiguration, + + /// Contains the state of the network. + network_state: NetworkState, + + /// Kademlia system. Contains the DHT. + kad_system: KadSystem, + + /// Configuration for the Kademlia upgrade. + kad_upgrade: KadConnecConfig, + + /// List of protocols available on the network. It is a logic error to + /// remove protocols from this list, and the code may assume that protocols + /// stay at the same index forever. + protocols: RwLock>>, + + /// Use this channel to send a timeout request to the background thread's + /// events loop. After the timeout, elapsed, it will call `timeout` on the + /// `NetworkProtocolHandler`. This can be closed if the background thread + /// is not running. The sender will be overwritten every time we start + /// the service. + timeouts_register_tx: RwLock, ProtocolId, TimerToken))>>, + + /// Original address from the configuration, after being adjusted by the `Transport`. + /// Contains `None` if the network hasn't started yet. + original_listened_addr: RwLock>, + + /// Contains the addresses we known about ourselves. + listened_addrs: RwLock>, +} + +impl NetworkService { + /// Starts IO event loop + pub fn new( + config: NetworkConfiguration, + filter: Option> + ) -> Result { + // TODO: for now `filter` is always `None` ; remove it from the code or implement it + assert!(filter.is_none()); + + let network_state = NetworkState::new(&config)?; + + let local_peer_id = network_state.local_public_key().clone() + .into_peer_id(); + let mut listen_addr = config_to_listen_addr(&config); + listen_addr.append(AddrComponent::P2P(local_peer_id.clone().into_bytes())); + info!(target: "sub-libp2p", "Local node address is: {}", listen_addr); + + let kad_system = KadSystem::without_init(KadSystemConfig { + parallelism: 3, + local_peer_id: local_peer_id.clone(), + kbuckets_timeout: Duration::from_secs(600), + request_timeout: Duration::from_secs(10), + known_initial_peers: network_state.known_peers(), + }); + + let shared = Arc::new(Shared { + network_state, + protocols: RwLock::new(Default::default()), + kad_system, + kad_upgrade: KadConnecConfig::new(), + config, + timeouts_register_tx: RwLock::new(mpsc::unbounded().0), + original_listened_addr: RwLock::new(None), + listened_addrs: RwLock::new(Vec::new()), + }); + + Ok(NetworkService { + shared, + bg_thread: Mutex::new(None), + }) + } + + /// Returns network configuration. + pub fn config(&self) -> &NetworkConfiguration { + &self.shared.config + } + + pub fn external_url(&self) -> Option { + // TODO: in the context of libp2p, it is hard to define what an external + // URL is, as different nodes can have multiple different ways to + // reach us + self.shared.original_listened_addr.read().as_ref() + .map(|addr| + format!("{}/p2p/{}", addr, self.shared.kad_system.local_peer_id().to_base58()) + ) + } + + /// Start network IO. + /// Note that we could use an iterator for `protocols`, but having a + /// generic here is too much and crashes the Rust compiler. + // TODO (design): the notion of having a `NetworkService` alive should mean + // that it is running ; the `start` and `stop` functions are bad design + pub fn start( + &self, + protocols: Vec<(Arc, ProtocolId, &[(u8, u8)])> + ) -> Result<(), (Error, Option)> { + // TODO: check that service is started already? + + *self.shared.protocols.write() = RegisteredProtocols( + protocols.into_iter() + .map(|(handler, protocol, versions)| + RegisteredProtocol::new(handler.clone(), protocol, versions)) + .collect() + ); + + // Channel we use to signal success or failure of the bg thread + // initialization process. + let (init_tx, init_rx) = sync_mpsc::channel(); + // Channel the main thread uses to signal the bg thread that it + // should stop + let (close_tx, close_rx) = oneshot::channel(); + let (timeouts_register_tx, timeouts_register_rx) = mpsc::unbounded(); + *self.shared.timeouts_register_tx.write() = timeouts_register_tx; + + // Initialize all the protocols now. + for protocol in self.shared.protocols.read().0.iter() { + protocol.custom_data().initialize(&NetworkContextImpl { + inner: self.shared.clone(), + protocol: protocol.id().clone(), + current_peer: None, + }); + } + + let shared = self.shared.clone(); + let join_handle = thread::spawn(move || { + // Tokio runtime that is going to run everything in this thread. + let mut runtime = match current_thread::Runtime::new() { + Ok(c) => c, + Err(err) => { + let _ = init_tx.send(Err(err.into())); + return + } + }; + + let fut = match init_thread(shared, + timeouts_register_rx, close_rx) { + Ok(future) => { + debug!(target: "sub-libp2p", "Successfully started networking service"); + let _ = init_tx.send(Ok(())); + future + }, + Err(err) => { + let _ = init_tx.send(Err(err)); + return + } + }; + + match runtime.block_on(fut) { + Ok(()) => debug!(target: "sub-libp2p", "libp2p future finished"), + Err(err) => error!(target: "sub-libp2p", "error while running libp2p: {:?}", err), + } + }); + + init_rx.recv().expect("libp2p background thread panicked") + .map_err(|err| (err, self.shared.config.listen_address.clone()))?; + + *self.bg_thread.lock() = Some((close_tx, join_handle)); + Ok(()) + } + + /// Stop network IO. + pub fn stop(&self) { + if let Some((close_tx, join)) = self.bg_thread.lock().take() { + let _ = close_tx.send(()); + if let Err(e) = join.join() { + warn!(target: "sub-libp2p", "error while waiting on libp2p background thread: {:?}", e); + } + } + + debug_assert!(!self.shared.network_state.has_connected_peer()); + } + + /// Get a list of all connected peers by id. + pub fn connected_peers(&self) -> Vec { + self.shared.network_state.connected_peers() + } + + /// Try to add a reserved peer. + pub fn add_reserved_peer(&self, peer: &str) -> Result<(), Error> { + // TODO: try to dial the peer? + self.shared.network_state.add_reserved_peer(peer) + } + + /// Try to remove a reserved peer. + pub fn remove_reserved_peer(&self, peer: &str) -> Result<(), Error> { + self.shared.network_state.remove_reserved_peer(peer) + } + + /// Set the non-reserved peer mode. + pub fn set_non_reserved_mode(&self, mode: NonReservedPeerMode) { + self.shared.network_state.set_non_reserved_mode(mode) + } + + /// Executes action in the network context + pub fn with_context(&self, protocol: ProtocolId, action: F) + where F: FnOnce(&NetworkContext) { + self.with_context_eval(protocol, action); + } + + /// Evaluates function in the network context + pub fn with_context_eval(&self, protocol: ProtocolId, action: F) + -> Option + where F: FnOnce(&NetworkContext) -> T { + if !self.shared.protocols.read().has_protocol(protocol) { + return None + } + + Some(action(&NetworkContextImpl { + inner: self.shared.clone(), + protocol: protocol.clone(), + current_peer: None, + })) + } +} + +impl Drop for NetworkService { + fn drop(&mut self) { + self.stop() + } +} + +#[derive(Clone)] +struct NetworkContextImpl { + inner: Arc, + protocol: ProtocolId, + current_peer: Option, +} + +impl NetworkContext for NetworkContextImpl { + fn send(&self, peer: NodeIndex, packet_id: PacketId, data: Vec) { + self.send_protocol(self.protocol, peer, packet_id, data) + } + + fn send_protocol( + &self, + protocol: ProtocolId, + peer: NodeIndex, + packet_id: PacketId, + data: Vec + ) { + debug_assert!(self.inner.protocols.read().has_protocol(protocol), + "invalid protocol id requested in the API of the libp2p networking"); + // TODO: could be "optimized" by building `message` only after checking the validity of + // the peer, but that's probably not worth the effort + let mut message = Bytes::with_capacity(1 + data.len()); + message.extend_from_slice(&[packet_id]); + message.extend_from_slice(&data); + if self.inner.network_state.send(protocol, peer, message).is_err() { + debug!(target: "sub-libp2p", "Sending to peer {} failed. Dropping.", peer); + self.inner.network_state.drop_peer(peer); + } + } + + fn respond(&self, packet_id: PacketId, data: Vec) { + if let Some(peer) = self.current_peer { + self.send_protocol(self.protocol, peer, packet_id, data) + } else { + panic!("respond() called outside of a received message"); + } + } + + fn report_peer(&self, peer: NodeIndex, reason: Severity) { + if let Some(info) = self.inner.network_state.peer_info(peer) { + if let (Some(client_version), Some(remote_address)) = (info.client_version, info.remote_address) { + info!(target: "sub-libp2p", + "Peer {} ({} {}) reported by client: {}", + peer, + remote_address, + client_version, + reason + ); + } else { + info!(target: "sub-libp2p", "Peer {} reported by client: {}", peer, reason); + } + } + match reason { + Severity::Bad(reason) => self.inner.network_state.ban_peer(peer, reason), + Severity::Useless(_) => self.inner.network_state.drop_peer(peer), + Severity::Timeout => self.inner.network_state.drop_peer(peer), + } + } + + fn is_expired(&self) -> bool { + if let Some(current_peer) = self.current_peer { + !self.inner.network_state.is_peer_connected(current_peer) + } else { + // TODO: is this correct? + true + } + } + + fn register_timer(&self, token: usize, duration: Duration) + -> Result<(), Error> { + let handler = self.inner.protocols + .read() + .find_protocol(self.protocol) + .ok_or(ErrorKind::BadProtocol)? + .custom_data() + .clone(); + self.inner.timeouts_register_tx.read() + .unbounded_send((duration, (handler, self.protocol, token))) + .map_err(|err| ErrorKind::Io(IoError::new(IoErrorKind::Other, err)))?; + Ok(()) + } + + fn peer_client_version(&self, peer: NodeIndex) -> String { + // Devp2p returns "unknown" on unknown peer ID, so we do the same. + self.inner.network_state.peer_client_version(peer, self.protocol) + .unwrap_or_else(|| "unknown".to_string()) + } + + fn session_info(&self, peer: NodeIndex) -> Option { + self.inner.network_state.session_info(peer, self.protocol) + } + + fn protocol_version(&self, protocol: ProtocolId, peer: NodeIndex) -> Option { + self.inner.network_state.protocol_version(peer, protocol) + } + + fn subprotocol_name(&self) -> ProtocolId { + self.protocol.clone() + } +} + +/// Builds the main `Future` for the network service. +/// +/// - `timeouts_register_rx` should receive newly-registered timeouts. +/// - `close_rx` should be triggered when we want to close the network. +fn init_thread( + shared: Arc, + timeouts_register_rx: mpsc::UnboundedReceiver< + (Duration, (Arc, ProtocolId, TimerToken)) + >, + close_rx: oneshot::Receiver<()> +) -> Result, Error> { + // Build the transport layer. + let transport = { + let base = transport::build_transport( + transport::UnencryptedAllowed::Denied, + shared.network_state.local_private_key().clone() + ); + + let addr_resolver = { + let shared = shared.clone(); + move |who| { + let addrs = shared.network_state.addrs_of_peer(&who); + for addr in &addrs { + trace!(target: "sub-libp2p", "{:?} resolved as {}", who, addr); + } + addrs.into_iter() + } + }; + + PeerIdTransport::new(base.clone(), addr_resolver).and_then({ + let shared = shared.clone(); + move |out, endpoint, remote_addr| { + let original_addr = out.original_addr.clone(); + let info = out.info.and_then(move |info| { + process_identify_info(shared, &info, original_addr, + endpoint, &base)?; + Ok(info) + }); + + let out = TransportOutput { + socket: out.socket, + info: Box::new(info) as Box<_>, + original_addr: out.original_addr, + }; + + future::ok((out, remote_addr)) + } + }) + }; + + // Build the swarm. The swarm is the single entry point where successfully + // negotiated protocols arrive. + let (swarm_controller, swarm_future) = { + let upgraded_transport = transport.clone() + .and_then({ + let shared = shared.clone(); + move |out, endpoint, client_addr| { + let original_addr = out.original_addr; + let listener_upgrade = upgrade::or(upgrade::or(upgrade::or( + upgrade::map_with_addr(shared.kad_upgrade.clone(), |(c, f), a| FinalUpgrade::Kad(c, f, a.clone())), + upgrade::map(IdentifyProtocolConfig, |id| FinalUpgrade::Identify(id, original_addr))), + upgrade::map_with_addr(ping::Ping, |(p, f), addr| FinalUpgrade::Ping(p, f, addr.clone()))), + upgrade::map_with_addr(DelayedProtosList(shared), |c, a| FinalUpgrade::Custom(c, a.clone()))); + upgrade::apply(out.socket, listener_upgrade, endpoint, client_addr) + } + }); + let shared = shared.clone(); + + libp2p::core::swarm( + upgraded_transport, + move |upgrade, _client_addr| + listener_handle(shared.clone(), upgrade) + ) + }; + + // Listen on multiaddress. + // TODO: change the network config to directly contain a `Multiaddr` + { + let listen_addr = config_to_listen_addr(&shared.config); + debug!(target: "sub-libp2p", "Libp2p listening on {}", listen_addr); + match swarm_controller.listen_on(listen_addr.clone()) { + Ok(new_addr) => { + *shared.original_listened_addr.write() = Some(new_addr.clone()); + }, + Err(_) => { + warn!(target: "sub-libp2p", "Can't listen on {}, protocol not supported", listen_addr); + return Err(ErrorKind::BadProtocol.into()) + }, + } + } + // Explicitely connect to _all_ the boostrap nodes as a temporary measure. + for bootnode in shared.config.boot_nodes.iter() { + match shared.network_state.add_peer(bootnode) { + Ok(who) => { + trace!(target: "sub-libp2p", "Dialing bootnode {:?}", who); + for proto in shared.protocols.read().0.clone().into_iter() { + open_peer_custom_proto( + shared.clone(), + transport.clone(), + proto, + who.clone(), + &swarm_controller + ) + } + }, + Err(Error(ErrorKind::AddressParse, _)) => { + // fallback: trying with IP:Port + let multi = match bootnode.parse::() { + Ok(SocketAddr::V4(socket)) => + format!("/ip4/{}/tcp/{}", socket.ip(), socket.port()).parse::(), + Ok(SocketAddr::V6(socket)) => + format!("/ip6/{}/tcp/{}", socket.ip(), socket.port()).parse::(), + _ => { + warn!(target: "sub-libp2p", "Not a valid Bootnode Address {:}", bootnode); + continue; + } + }; + + if let Ok(addr) = multi { + trace!(target: "sub-libp2p", "Missing NodeIndex for Bootnode {:}. Querying", bootnode); + for proto in shared.protocols.read().0.clone().into_iter() { + connect_with_query_peer_id( + shared.clone(), + transport.clone(), + proto, + addr.clone(), + &swarm_controller + ) + } + } else { + warn!(target: "sub-libp2p", "Not a valid Bootnode Address {:}", bootnode); + continue; + } + }, + Err(err) => warn!(target:"sub-libp2p", "Couldn't parse Bootnode Address: {}", err), + } + } + + // Start connecting to nodes now. + connect_to_nodes(shared.clone(), transport.clone(), &swarm_controller); + + // Build the timeouts system for the `register_timeout` function. + // (note: this has nothing to do with socket timeouts) + let timeouts = timeouts::build_timeouts_stream(timeouts_register_rx) + .for_each({ + let shared = shared.clone(); + move |(handler, protocol_id, timer_token)| { + handler.timeout(&NetworkContextImpl { + inner: shared.clone(), + protocol: protocol_id, + current_peer: None, + }, timer_token); + Ok(()) + } + }) + .then(|val| { + warn!(target: "sub-libp2p", "Timeouts stream closed unexpectedly: {:?}", val); + val + }); + + // Start the process of periodically discovering nodes to connect to. + let discovery = start_kademlia_discovery(shared.clone(), + transport.clone(), swarm_controller.clone()); + + // Start the process of pinging the active nodes on the network. + let pinger = start_pinger(shared.clone(), transport, swarm_controller); + + // Merge all the futures into one! + Ok(swarm_future + .select(discovery).map_err(|(err, _)| err).and_then(|(_, rest)| rest) + .select(pinger).map_err(|(err, _)| err).and_then(|(_, rest)| rest) + .select(timeouts).map_err(|(err, _)| err).and_then(|(_, rest)| rest) + .select(close_rx.then(|_| Ok(()))).map(|_| ()).map_err(|(err, _)| err) + + .and_then(move |_| { + debug!(target: "sub-libp2p", "Networking ended ; disconnecting all peers"); + shared.network_state.disconnect_all(); + Ok(()) + })) +} + +/// Output of the common transport layer. +struct TransportOutput { + socket: S, + info: Box>, + original_addr: Multiaddr, +} + +/// Enum of all the possible protocols our service handles. +enum FinalUpgrade { + Kad(KadConnecController, Box>, Multiaddr), + /// The remote identification system, and the multiaddress we see the remote as. + Identify(IdentifyOutput, Multiaddr), + Ping(ping::Pinger, Box>, Multiaddr), + /// `Custom` means anything not in the core libp2p and is handled + /// by `CustomProtoConnectionUpgrade`. + Custom(RegisteredProtocolOutput>, Multiaddr), +} + +/// Called whenever we successfully open a multistream with a remote. +fn listener_handle<'a, C>( + shared: Arc, + upgrade: FinalUpgrade, +) -> Box + 'a> + where C: AsyncRead + AsyncWrite + 'a { + match upgrade { + FinalUpgrade::Kad(controller, kademlia_stream, client_addr) => { + trace!(target: "sub-libp2p", "Opened kademlia substream with {:?}", client_addr); + match handle_kademlia_connection(shared, client_addr, controller, kademlia_stream) { + Ok(fut) => Box::new(fut) as Box<_>, + Err(err) => Box::new(future::err(err)) as Box<_>, + } + }, + + FinalUpgrade::Identify(IdentifyOutput::Sender { sender }, original_addr) => { + trace!(target: "sub-libp2p", "Sending back identification info"); + sender.send( + IdentifyInfo { + public_key: shared.network_state.local_public_key().clone(), + protocol_version: concat!("substrate/", + env!("CARGO_PKG_VERSION")).to_owned(), // TODO: ? + agent_version: concat!("substrate/", + env!("CARGO_PKG_VERSION")).to_owned(), + listen_addrs: shared.listened_addrs.read().clone(), + protocols: Vec::new(), // TODO: protocols_to_report, + }, + &original_addr + ) + }, + + FinalUpgrade::Identify(IdentifyOutput::RemoteInfo { .. }, _) => + unreachable!("We are never dialing with the identify protocol"), + + FinalUpgrade::Ping(pinger, future, client_addr) => { + let node_id = p2p_multiaddr_to_node_id(client_addr); + match shared.network_state.ping_connection(node_id.clone()) { + Ok((_, ping_connec)) => { + trace!(target: "sub-libp2p", "Successfully opened ping substream with {:?}", node_id); + let fut = ping_connec.tie_or_passthrough(pinger, future); + Box::new(fut) as Box<_> + }, + Err(err) => Box::new(future::err(err)) as Box<_> + } + }, + + FinalUpgrade::Custom(custom_proto_out, client_addr) => { + // A "custom" protocol is one that is part of substrate and not part of libp2p. + let shared = shared.clone(); + let fut = handle_custom_connection(shared, client_addr, custom_proto_out); + Box::new(fut) as Box<_> + }, + } +} + +/// Handles a newly-opened Kademlia connection. +fn handle_kademlia_connection( + shared: Arc, + client_addr: Multiaddr, + controller: KadConnecController, + kademlia_stream: Box> +) -> Result, IoError> { + let node_id = p2p_multiaddr_to_node_id(client_addr); + let (who, kad_connec) = shared.network_state + .kad_connection(node_id.clone())?; + + let node_id2 = node_id.clone(); + let future = future::loop_fn(kademlia_stream, move |kademlia_stream| { + let shared = shared.clone(); + let node_id = node_id.clone(); + + let next = kademlia_stream + .into_future() + .map_err(|(err, _)| err); + let deadline = Instant::now() + Duration::from_secs(20); + + Deadline::new(next, deadline) + .map_err(|err| + // TODO: improve the error reporting here, but tokio-timer's API is bad + IoError::new(IoErrorKind::Other, err) + ) + .and_then(move |(req, rest)| { + shared.kad_system.update_kbuckets(node_id); + match req { + Some(KadIncomingRequest::FindNode { searched, responder }) => + responder.respond(build_kademlia_response(&shared, &searched)), + Some(KadIncomingRequest::PingPong) => (), + None => return Ok(future::Loop::Break(())) + } + Ok(future::Loop::Continue(rest)) + }) + }).then(move |val| { + trace!(target: "sub-libp2p", "Closed Kademlia connection with #{} {:?} => {:?}", who, node_id2, val); + val + }); + + Ok(kad_connec.tie_or_passthrough(controller, future)) +} + +/// When a remote performs a `FIND_NODE` Kademlia request for `searched`, +/// this function builds the response to send back. +fn build_kademlia_response( + shared: &Arc, + searched: &PeerstorePeerId +) -> Vec { + shared.kad_system + .known_closest_peers(searched) + .map(move |who| { + if who == *shared.kad_system.local_peer_id() { + KadPeer { + node_id: who.clone(), + multiaddrs: shared.listened_addrs.read().clone(), + connection_ty: KadConnectionType::Connected, + } + } else { + let addrs = shared.network_state.addrs_of_peer(&who); + let connec_ty = if shared.network_state.has_connection(&who) { + // TODO: this only checks connections with substrate ; but what + // if we're connected through Kademlia only? + KadConnectionType::Connected + } else { + KadConnectionType::NotConnected + }; + + KadPeer { + node_id: who.clone(), + multiaddrs: addrs, + connection_ty: connec_ty, + } + } + }) + // TODO: we really want to remove nodes with no multiaddress from + // the results, but a flaw in the Kad protocol of libp2p makes it + // impossible to return empty results ; therefore we must at least + // return ourselves + .filter(|p| p.node_id == *shared.kad_system.local_peer_id() || + !p.multiaddrs.is_empty()) + .take(20) + .collect::>() +} + +/// Handles a newly-opened connection to a remote with a custom protocol +/// (eg. `/substrate/dot/0`). +/// Returns a future that corresponds to when the handling is finished. +fn handle_custom_connection( + shared: Arc, + client_addr: Multiaddr, + custom_proto_out: RegisteredProtocolOutput> +) -> impl Future { + let handler = custom_proto_out.custom_data; + let protocol_id = custom_proto_out.protocol_id; + + // We're using the `PeerIdTransport` layer, so all the multiaddresses received + // here should be of the format `/p2p/`. + let node_id = p2p_multiaddr_to_node_id(client_addr); + + // Determine the ID of this peer, or drop the connection if the peer is disabled, + // if we reached `max_peers`, or a similar reason. + // TODO: is there a better way to refuse connections than to drop the + // newly-opened substream? should we refuse the connection + // beforehand? + let (who, unique_connec) = match shared.network_state.custom_proto( + node_id.clone(), + protocol_id, + custom_proto_out.endpoint, + ) { + Ok(a) => a, + Err(err) => return future::Either::A(future::err(err.into())), + }; + + if let UniqueConnecState::Full = unique_connec.state() { + debug!(target: "sub-libp2p", + "Interrupting connection attempt to {:?} with {:?} because we're already connected", + node_id, + custom_proto_out.protocol_id + ); + return future::Either::A(future::ok(())) + } + + struct ProtoDisconnectGuard { + inner: Arc, + who: NodeIndex, + node_id: PeerstorePeerId, + handler: Arc, + protocol: ProtocolId + } + + impl Drop for ProtoDisconnectGuard { + fn drop(&mut self) { + info!(target: "sub-libp2p", + "Node {:?} with peer ID {} through protocol {:?} disconnected", + self.node_id, + self.who, + self.protocol + ); + self.handler.disconnected(&NetworkContextImpl { + inner: self.inner.clone(), + protocol: self.protocol, + current_peer: Some(self.who), + }, &self.who); + + // When any custom protocol drops, we drop the peer entirely. + // TODO: is this correct? + self.inner.network_state.drop_peer(self.who); + } + } + + let dc_guard = ProtoDisconnectGuard { + inner: shared.clone(), + who, + node_id: node_id.clone(), + handler: handler.clone(), + protocol: protocol_id, + }; + + let fut = custom_proto_out.incoming + .for_each({ + let shared = shared.clone(); + let handler = handler.clone(); + let node_id = node_id.clone(); + move |(packet_id, data)| { + shared.kad_system.update_kbuckets(node_id.clone()); + handler.read(&NetworkContextImpl { + inner: shared.clone(), + protocol: protocol_id, + current_peer: Some(who.clone()), + }, &who, packet_id, &data); + Ok(()) + } + }); + + let val = (custom_proto_out.outgoing, custom_proto_out.protocol_version); + let final_fut = unique_connec.tie_or_stop(val, fut) + .then(move |val| { + // Makes sure that `dc_guard` is kept alive until here. + drop(dc_guard); + val + }); + + debug!(target: "sub-libp2p", + "Successfully connected to {:?} (peer id {}) with protocol {:?} version {}", + node_id, + who, + protocol_id, + custom_proto_out.protocol_version + ); + + handler.connected(&NetworkContextImpl { + inner: shared.clone(), + protocol: protocol_id, + current_peer: Some(who), + }, &who); + + future::Either::B(final_fut) +} + +/// Builds the multiaddress corresponding to the address we need to listen to +/// according to the config. +// TODO: put the `Multiaddr` directly in the `NetworkConfiguration` +fn config_to_listen_addr(config: &NetworkConfiguration) -> Multiaddr { + if let Some(addr) = config.listen_address { + let ip = match addr.ip() { + IpAddr::V4(addr) => AddrComponent::IP4(addr), + IpAddr::V6(addr) => AddrComponent::IP6(addr), + }; + iter::once(ip).chain(iter::once(AddrComponent::TCP(addr.port()))).collect() + } else { + let host = AddrComponent::IP4(Ipv4Addr::new(0, 0, 0, 0)); + let port = AddrComponent::TCP(0); + iter::once(host).chain(iter::once(port)).collect() + } +} + +/// Randomly discovers peers to connect to. +/// This works by running a round at a regular interval, and skipping if we +/// reached `min_peers`. When we are over `min_peers`, we stop trying to dial +/// nodes and only accept incoming connections. +fn start_kademlia_discovery(shared: Arc, transport: T, + swarm_controller: SwarmController) -> impl Future + where T: MuxedTransport> + Clone + 'static, + T::MultiaddrFuture: 'static, + To: AsyncRead + AsyncWrite + 'static, + St: MuxedTransport> + Clone + 'static, + C: 'static { + let kad_init = shared.kad_system.perform_initialization({ + let shared = shared.clone(); + let transport = transport.clone(); + let swarm_controller = swarm_controller.clone(); + move |who| + obtain_kad_connection( + shared.clone(), + who.clone(), + transport.clone(), + swarm_controller.clone() + ) + }); + + let discovery = Interval::new(Instant::now(), Duration::from_secs(32)) + // TODO: add a timeout to the lookups + .map_err(|err| IoError::new(IoErrorKind::Other, err)) + .and_then({ + let shared = shared.clone(); + let transport = transport.clone(); + let swarm_controller = swarm_controller.clone(); + move |_| { + // Note that this is a small hack. We flush the caches here so + // that we don't need to run a timer just for flushing. + let _ = shared.network_state.flush_caches_to_disk(); + + if shared.network_state.should_open_outgoing_custom_connections() != 0 { + future::Either::A(perform_kademlia_query(shared.clone(), + transport.clone(), swarm_controller.clone())) + } else { + // If we shouldn't open connections (eg. we reached + // `min_peers`), pretend we did a lookup but with an empty + // result. + trace!(target: "sub-libp2p", "Bypassing kademlia discovery"); + future::Either::B(future::ok(())) + } + } + }) + .for_each({ + let shared = shared.clone(); + move |_| { + connect_to_nodes(shared.clone(), transport.clone(), &swarm_controller); + Ok(()) + } + }); + + let final_future = kad_init + .select(discovery) + .map_err(|(err, _)| err) + .and_then(|(_, rest)| rest); + + // Note that we use a Box in order to speed compilation time. + Box::new(final_future) as Box> +} + +/// Performs a kademlia request to a random node. +/// Note that we don't actually care about the results, so the future +/// produces `()`. +fn perform_kademlia_query( + shared: Arc, + transport: T, + swarm_controller: SwarmController +) -> impl Future + where T: MuxedTransport> + Clone + 'static, + T::MultiaddrFuture: 'static, + To: AsyncRead + AsyncWrite + 'static, + St: MuxedTransport> + Clone + 'static, + C: 'static { + // Query the node IDs that are closest to a random ID. + // Note that the randomness doesn't have to be secure, as this only + // influences which nodes we end up being connected to. + let random_key = PublicKey::Ed25519((0 .. 32) + .map(|_| -> u8 { rand::random() }).collect()); + let random_peer_id = random_key.into_peer_id(); + trace!(target: "sub-libp2p", "Start kademlia discovery for {:?}", random_peer_id); + + let future = shared.clone() + .kad_system + .find_node(random_peer_id, { + let shared = shared.clone(); + let transport = transport.clone(); + let swarm_controller = swarm_controller.clone(); + move |who| obtain_kad_connection(shared.clone(), who.clone(), + transport.clone(), swarm_controller.clone()) + }) + .filter_map(move |event| + match event { + KadQueryEvent::NewKnownMultiaddrs(peers) => { + for (peer, addrs) in peers { + for addr in addrs { + shared.network_state.add_kad_discovered_addr(&peer, addr); + } + } + None + }, + KadQueryEvent::Finished(_) => Some(()), + } + ) + .into_future() + .map_err(|(err, _)| err) + .map(|_| ()); + + // Note that we use a `Box` in order to speed up compilation. + Box::new(future) as Box> +} + +/// Connects to additional nodes, if necessary. +fn connect_to_nodes( + shared: Arc, + base_transport: T, + swarm_controller: &SwarmController +) + where T: MuxedTransport> + Clone + 'static, + T::MultiaddrFuture: 'static, + To: AsyncRead + AsyncWrite + 'static, + St: MuxedTransport> + Clone + 'static, + C: 'static { + let num_slots = shared.network_state.should_open_outgoing_custom_connections(); + debug!(target: "sub-libp2p", + "Outgoing connections cycle ; opening up to {} outgoing connections", + num_slots + ); + + for _ in 0 .. num_slots { + // Choose a random peer. We are potentially already connected to + // this peer, but this is not a problem as this function is called + // regularly. + // TODO: is it ^ ? + let peer = match shared.network_state.random_peer() { + Some(p) => p, + // `None` returned when no peer is known + None => break, + }; + + // Try to dial that node for each registered protocol. Since dialing + // upgrades the connection to use multiplexing, dialing multiple times + // should automatically open multiple substreams. + for proto in shared.protocols.read().0.clone().into_iter() { + open_peer_custom_proto( + shared.clone(), + base_transport.clone(), + proto, + peer.clone(), + swarm_controller + ) + } + } +} + + +fn connect_with_query_peer_id( + shared: Arc, + base_transport: T, + proto: RegisteredProtocol>, + addr: Multiaddr, + swarm_controller: &SwarmController +) + where T: MuxedTransport> + Clone + 'static, + T::MultiaddrFuture: 'static, + To: AsyncRead + AsyncWrite + 'static, + St: MuxedTransport> + Clone + 'static, + C: 'static, +{ + let addr2 = addr.clone(); + let with_proto = base_transport + .clone() + .and_then(move |out, endpoint, client_addr| { + trace!(target: "sub-libp2p", "in"); + let socket = out.socket; + let original_addr = out.original_addr; + out.info + .and_then(move |info| { + let _ = process_identify_info(shared, &info, original_addr, + endpoint, &base_transport); + trace!(target: "sub-libp2p", + "Bootnode {:} found with peer id: {:?}", + addr2, + info.info.public_key.into_peer_id() + ); + upgrade::apply(socket, proto, endpoint, client_addr) + }) + }) + .and_then(move |out, _endpoint, client_addr| + client_addr.map(move |client_addr| + (FinalUpgrade::Custom(out, client_addr.clone()), future::ok(client_addr)) + ) + ); + + let with_timeout = TransportTimeout::new(with_proto, Duration::from_secs(10)); + let with_err = with_timeout + .map_err({ + let addr = addr.clone(); + move |err| { + warn!(target: "sub-libp2p", + "Error while dialing {:?} to query peer id: {:?}", + addr, + err + ); + err + } + }); + + let _ = swarm_controller.dial(addr.clone(), with_err) + .map_err(move |err| + warn!(target: "sub-libp2p", "Error when querying peer node info {:} of {:}", err, addr) + ); +} + +/// If necessary, dials the given address for the given protocol and using the +/// given `swarm_controller`. Has no effect if we already dialed earlier. +/// Checks that the peer ID matches `expected_peer_id`. +// TODO: check that the secio key matches the id given by kademlia +fn open_peer_custom_proto( + shared: Arc, + base_transport: T, + proto: RegisteredProtocol>, + expected_peer_id: PeerstorePeerId, + swarm_controller: &SwarmController +) + where T: MuxedTransport> + Clone + 'static, + T::MultiaddrFuture: 'static, + To: AsyncRead + AsyncWrite + 'static, + St: MuxedTransport> + Clone + 'static, + C: 'static, +{ + // Don't connect to ourselves. + // TODO: remove this eventually + if &expected_peer_id == shared.kad_system.local_peer_id() { + trace!(target: "sub-libp2p", "Skipped connecting to {:?} because it is ourselves", expected_peer_id); + return + } + + let proto_id = proto.id(); + let node_id = expected_peer_id.clone(); + let shared2 = shared.clone(); + let addr: Multiaddr = AddrComponent::P2P(expected_peer_id.clone().into_bytes()).into(); + + // TODO: check that the secio key matches the id given by kademlia + let with_proto = base_transport + .clone() + .and_then(move |out, endpoint, client_addr| { + let socket = out.socket; + let original_addr = out.original_addr; + out.info + .and_then(move |info| { + let actual_peer_id = info.info.public_key.into_peer_id(); + if actual_peer_id == expected_peer_id { + Ok(socket) + } else { + debug!(target: "sub-libp2p", + "Public key mismatch for node {:?} ; actual: {:?}", + expected_peer_id, + actual_peer_id + ); + trace!(target: "sub-libp2p", "Removing addr {} for {:?}", original_addr, expected_peer_id); + shared.network_state.set_invalid_kad_address(&expected_peer_id, &original_addr); + Err(IoError::new(IoErrorKind::InvalidData, "public key mismatch when identifying peer")) + } + }) + .and_then(move |socket| + upgrade::apply(socket, proto, endpoint, client_addr) + ) + }) + .and_then(move |out, _endpoint, client_addr| + client_addr.map(move |client_addr| { + let out = FinalUpgrade::Custom(out, client_addr.clone()); + (out, future::ok(client_addr)) + }) + ); + + let with_timeout = TransportTimeout::new(with_proto, + Duration::from_secs(20)); + let with_err = with_timeout + .map_err({ + let node_id = node_id.clone(); + move |err| { + debug!(target: "sub-libp2p", "Error while dialing {:?} with custom proto: {:?}", node_id, err); + err + } + }); + + match shared2.network_state.custom_proto(node_id.clone(), proto_id, Endpoint::Dialer) { + Ok((who, unique_connec)) => { + if !unique_connec.is_alive() { + trace!(target: "sub-libp2p", + "Opening connection to #{} {:?} with proto {:?}", + who, + node_id, + proto_id + ); + } + + unique_connec.dial(&swarm_controller, &addr, with_err); + }, + Err(err) => { + trace!(target: "sub-libp2p", + "Error while opening connection to {:?} with proto {:?} => {:?}", + node_id, + proto_id, + err + ); + }, + } +} + +/// Obtain a Kademlia connection to the given peer. +fn obtain_kad_connection(shared: Arc, + who: PeerstorePeerId, transport: T, swarm_controller: SwarmController) + -> impl Future + where T: MuxedTransport> + Clone + 'static, + T::MultiaddrFuture: 'static, + To: AsyncRead + AsyncWrite + 'static, + St: MuxedTransport> + Clone + 'static, + C: 'static { + let kad_upgrade = shared.kad_upgrade.clone(); + let addr: Multiaddr = AddrComponent::P2P(who.clone().into_bytes()).into(); + let transport = transport + .and_then(move |out, endpoint, client_addr| + upgrade::apply(out.socket, kad_upgrade.clone(), + endpoint, client_addr) + ) + .and_then(move |(ctrl, fut), _, client_addr| { + client_addr.map(|client_addr| { + let out = FinalUpgrade::Kad(ctrl, fut, client_addr.clone()); + (out, future::ok(client_addr)) + }) + }); + + let future = shared.network_state + .kad_connection(who.clone()) + .into_future() + .map(move |(_, k)| k.dial(&swarm_controller, &addr, transport)) + .flatten(); + + // Note that we use a Box in order to speed up compilation. + Box::new(future) as Box> +} + +/// Processes the information about a node. +/// +/// - `original_addr` is the address used to originally dial this node. +/// - `endpoint` is whether we dialed or listened to this node. +/// - `transport` is used for the `nat_traversal` method. +/// +/// Returns an error if the node has been refused access. +fn process_identify_info( + shared: Arc, + info: &IdentifyTransportOutcome, + original_addr: Multiaddr, + endpoint: Endpoint, + transport: &impl Transport +) -> Result<(), IoError> { + let node_id = info.info.public_key.clone().into_peer_id(); + let _peer_id = shared.network_state.set_peer_info(node_id.clone(), endpoint, + info.info.agent_version.clone(), original_addr.clone(), + original_addr.clone())?; // TODO: wrong local addr + + if let Some(ref original_listened_addr) = *shared.original_listened_addr.read() { + if let Some(mut ext_addr) = transport.nat_traversal(original_listened_addr, &info.observed_addr) { + let mut listened_addrs = shared.listened_addrs.write(); + if !listened_addrs.iter().any(|a| a == &ext_addr) { + trace!(target: "sub-libp2p", + "NAT traversal: remote observes us as {}; registering {} as one of our own addresses", + info.observed_addr, + ext_addr + ); + listened_addrs.push(ext_addr.clone()); + ext_addr.append(AddrComponent::P2P(shared.kad_system + .local_peer_id().clone().into_bytes())); + info!(target: "sub-libp2p", "New external node address: {}", ext_addr); + } + } + } + + for addr in info.info.listen_addrs.iter() { + shared.network_state.add_kad_discovered_addr(&node_id, addr.clone()); + } + + Ok(()) +} + +/// Returns a future that regularly pings every peer we're connected to. +/// If a peer doesn't respond after a while, we disconnect it. +fn start_pinger( + shared: Arc, + transport: T, + swarm_controller: SwarmController +) -> impl Future + where T: MuxedTransport> + Clone + 'static, + T::MultiaddrFuture: 'static, + To: AsyncRead + AsyncWrite + 'static, + St: MuxedTransport> + Clone + 'static, + C: 'static { + let transport = transport + .and_then(move |out, endpoint, client_addr| + upgrade::apply(out.socket, ping::Ping, endpoint, client_addr) + ) + .and_then(move |(ctrl, fut), _, client_addr| { + client_addr.map(|client_addr| { + let out = FinalUpgrade::Ping(ctrl, fut, client_addr.clone()); + (out, future::ok(client_addr)) + }) + }); + + let fut = Interval::new(Instant::now(), Duration::from_secs(30)) + .map_err(|err| IoError::new(IoErrorKind::Other, err)) + .for_each(move |_| + ping_all(shared.clone(), transport.clone(), &swarm_controller)) + .then(|val| { + warn!(target: "sub-libp2p", "Pinging stream has stopped: {:?}", val); + val + }); + + // Note that we use a Box in order to speed compilation time. + Box::new(fut) as Box> +} + +/// Pings all the nodes we're connected to and disconnects any node that +/// doesn't respond. Returns a `Future` when all the pings have either +/// suceeded or timed out. +fn ping_all( + shared: Arc, + transport: T, + swarm_controller: &SwarmController +) -> impl Future + where T: MuxedTransport> + Clone + 'static, + T::MultiaddrFuture: 'static, + St: MuxedTransport> + Clone + 'static, + C: 'static { + let mut ping_futures = Vec::new(); + + for (peer, who, pinger) in shared.network_state.cleanup_and_prepare_ping() { + let shared = shared.clone(); + + let addr = Multiaddr::from(AddrComponent::P2P(who.clone().into_bytes())); + let fut = pinger + .dial(&swarm_controller, &addr, transport.clone()) + .and_then(move |mut p| { + trace!(target: "sub-libp2p", "Pinging peer #{} aka. {:?}", peer, who); + p.ping() + .map(|()| who) + .map_err(|err| IoError::new(IoErrorKind::Other, err)) + }); + let ping_start_time = Instant::now(); + let fut = Deadline::new(fut, ping_start_time + Duration::from_secs(30)) + .then(move |val| + match val { + Err(err) => { + trace!(target: "sub-libp2p", "Error while pinging #{:?} => {:?}", peer, err); + shared.network_state.report_ping_failed(peer); + // Return Ok, otherwise we would close the ping service + Ok(()) + }, + Ok(who) => { + let elapsed = ping_start_time.elapsed(); + trace!(target: "sub-libp2p", "Pong from #{:?} in {:?}", peer, elapsed); + shared.network_state.report_ping_duration(peer, elapsed); + shared.kad_system.update_kbuckets(who); + Ok(()) + } + } + ); + ping_futures.push(fut); + } + + let future = future::loop_fn(ping_futures, |ping_futures| { + if ping_futures.is_empty() { + let fut = future::ok(future::Loop::Break(())); + return future::Either::A(fut) + } + + let fut = future::select_all(ping_futures) + .map(|((), _, rest)| future::Loop::Continue(rest)) + .map_err(|(err, _, _)| err); + future::Either::B(fut) + }); + + // Note that we use a Box in order to speed up compilation. + Box::new(future) as Box> +} + +/// Expects a multiaddr of the format `/p2p/` and returns the node ID. +/// Panics if the format is not correct. +fn p2p_multiaddr_to_node_id(client_addr: Multiaddr) -> PeerstorePeerId { + let (first, second); + { + let mut iter = client_addr.iter(); + first = iter.next(); + second = iter.next(); + } + match (first, second) { + (Some(AddrComponent::P2P(node_id)), None) => + PeerstorePeerId::from_bytes(node_id).expect("libp2p always reports a valid node id"), + _ => panic!("Reported multiaddress is in the wrong format ; programmer error") + } +} + +/// Since new protocols are added after the networking starts, we have to load the protocols list +/// in a lazy way. This is what this wrapper does. +#[derive(Clone)] +struct DelayedProtosList(Arc); +// `Maf` is short for `MultiaddressFuture` +impl ConnectionUpgrade for DelayedProtosList +where C: AsyncRead + AsyncWrite + 'static, // TODO: 'static :-/ + Maf: Future + 'static, // TODO: 'static :( +{ + type NamesIter = > as ConnectionUpgrade>::NamesIter; + type UpgradeIdentifier = > as ConnectionUpgrade>::UpgradeIdentifier; + + fn protocol_names(&self) -> Self::NamesIter { + ConnectionUpgrade::::protocol_names(&*self.0.protocols.read()) + } + + type Output = > as ConnectionUpgrade>::Output; + type MultiaddrFuture = > as ConnectionUpgrade>::MultiaddrFuture; + type Future = > as ConnectionUpgrade>::Future; + + #[inline] + fn upgrade(self, socket: C, id: Self::UpgradeIdentifier, endpoint: Endpoint, + remote_addr: Maf) -> Self::Future + { + self.0.protocols.read() + .clone() + .upgrade(socket, id, endpoint, remote_addr) + } +} + +#[cfg(test)] +mod tests { + use super::NetworkService; + + #[test] + fn builds_and_finishes_in_finite_time() { + // Checks that merely starting the network doesn't end up in an infinite loop. + let service = NetworkService::new(Default::default(), None).unwrap(); + service.start(vec![]).map_err(|(err, _)| err).unwrap(); + } +} diff --git a/substrate/network-libp2p/src/timeouts.rs b/substrate/network-libp2p/src/timeouts.rs new file mode 100644 index 0000000000000..acd4ecc2d8c92 --- /dev/null +++ b/substrate/network-libp2p/src/timeouts.rs @@ -0,0 +1,115 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see .? + +use futures::{Async, future, Future, Poll, stream, Stream, sync::mpsc}; +use std::io::{Error as IoError, ErrorKind as IoErrorKind}; +use std::marker::PhantomData; +use std::time::{Duration, Instant}; +use tokio_timer::{self, Delay}; + +/// Builds the timeouts system. +/// +/// The `timeouts_rx` should be a stream receiving newly-created timeout +/// requests. Returns a stream that produces items as their timeout elapses. +/// `T` can be anything you want, as it is transparently passed from the input +/// to the output. Timeouts continue to fire forever, as there is no way to +/// unregister them. +pub fn build_timeouts_stream<'a, T>( + timeouts_rx: mpsc::UnboundedReceiver<(Duration, T)> +) -> Box + 'a> + where T: Clone + 'a { + let next_timeout = next_in_timeouts_stream(timeouts_rx); + + // The `unfold` function is essentially a loop turned into a stream. The + // first parameter is the initial state, and the closure returns the new + // state and an item. + let stream = stream::unfold(vec![future::Either::A(next_timeout)], move |timeouts| { + // `timeouts` is a `Vec` of futures that produce an `Out`. + + // `select_ok` panics if `timeouts` is empty anyway. + if timeouts.is_empty() { + return None + } + + Some(future::select_ok(timeouts.into_iter()) + .and_then(move |(item, mut timeouts)| + match item { + Out::NewTimeout((Some((duration, item)), next_timeouts)) => { + // Received a new timeout request on the channel. + let next_timeout = next_in_timeouts_stream(next_timeouts); + let timeout = Delay::new(Instant::now() + duration); + let timeout = TimeoutWrapper(timeout, duration, Some(item), PhantomData); + timeouts.push(future::Either::B(timeout)); + timeouts.push(future::Either::A(next_timeout)); + Ok((None, timeouts)) + }, + Out::NewTimeout((None, _)) => + // The channel has been closed. + Ok((None, timeouts)), + Out::Timeout(duration, item) => { + // A timeout has happened. + let returned = item.clone(); + let timeout = Delay::new(Instant::now() + duration); + let timeout = TimeoutWrapper(timeout, duration, Some(item), PhantomData); + timeouts.push(future::Either::B(timeout)); + Ok((Some(returned), timeouts)) + }, + } + ) + ) + }).filter_map(|item| item); + + // Note that we use a `Box` in order to speed up compilation time. + Box::new(stream) as Box> +} + +/// Local enum representing the output of the selection. +enum Out { + NewTimeout(A), + Timeout(Duration, B), +} + +/// Convenience function that calls `.into_future()` on the timeouts stream, +/// and applies some modifiers. +/// This function is necessary. Otherwise if we copy-paste its content we run +/// into errors because the type of the copy-pasted closures differs. +fn next_in_timeouts_stream( + stream: mpsc::UnboundedReceiver +) -> impl Future, mpsc::UnboundedReceiver), B>, Error = IoError> { + stream + .into_future() + .map(Out::NewTimeout) + .map_err(|_| unreachable!("an UnboundedReceiver can never error")) +} + +/// Does the equivalent to `future.map(move |()| (duration, item)).map_err(|err| to_io_err(err))`. +struct TimeoutWrapper(F, Duration, Option, PhantomData); +impl Future for TimeoutWrapper + where F: Future { + type Item = Out; + type Error = IoError; + + fn poll(&mut self) -> Poll { + match self.0.poll() { + Ok(Async::Ready(())) => (), + Ok(Async::NotReady) => return Ok(Async::NotReady), + Err(err) => return Err(IoError::new(IoErrorKind::Other, err.to_string())), + } + + let out = Out::Timeout(self.1, self.2.take().expect("poll() called again after success")); + Ok(Async::Ready(out)) + } +} diff --git a/substrate/network-libp2p/src/traits.rs b/substrate/network-libp2p/src/traits.rs new file mode 100644 index 0000000000000..15c9af78c50fa --- /dev/null +++ b/substrate/network-libp2p/src/traits.rs @@ -0,0 +1,403 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +use std::fmt; +use std::cmp::Ordering; +use std::collections::HashMap; +use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr}; +use std::str::{self, FromStr}; +use std::sync::Arc; +use std::time::Duration; +use io::TimerToken; +use ipnetwork::{IpNetwork, IpNetworkError}; +use error::Error; +use ethkey::Secret; +use ethereum_types::H512; + +/// Protocol handler level packet id +pub type PacketId = u8; +/// Protocol / handler id +pub type ProtocolId = [u8; 3]; + +/// Node public key +pub type NodeId = H512; + +/// Local (temporary) peer session ID. +/// RENAME TO NodeIndex +pub type NodeIndex = usize; + +/// Messages used to communitate with the event loop from other threads. +#[derive(Clone)] +pub enum NetworkIoMessage { + /// Register a new protocol handler. + AddHandler { + /// Handler shared instance. + handler: Arc, + /// Protocol Id. + protocol: ProtocolId, + /// Supported protocol versions and number of packet IDs reserved by the protocol (packet count). + versions: Vec<(u8, u8)>, + }, + /// Register a new protocol timer + AddTimer { + /// Protocol Id. + protocol: ProtocolId, + /// Timer token. + token: TimerToken, + /// Timer delay. + delay: Duration, + }, + /// Initliaze public interface. + InitPublicInterface, + /// Disconnect a peer. + Disconnect(NodeIndex), + /// Disconnect and temporary disable peer. + DisablePeer(NodeIndex), + /// Network has been started with the host as the given enode. + NetworkStarted(String), +} + +/// Shared session information +#[derive(Debug, Clone)] +pub struct SessionInfo { + /// Peer public key + pub id: Option, + /// Peer client ID + pub client_version: String, + /// Peer RLPx protocol version + pub protocol_version: u32, + /// Session protocol capabilities + pub capabilities: Vec, + /// Peer protocol capabilities + pub peer_capabilities: Vec, + /// Peer ping delay + pub ping: Option, + /// True if this session was originated by us. + pub originated: bool, + /// Remote endpoint address of the session + pub remote_address: String, + /// Local endpoint address of the session + pub local_address: String, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct PeerCapabilityInfo { + pub protocol: ProtocolId, + pub version: u8, +} + +impl ToString for PeerCapabilityInfo { + fn to_string(&self) -> String { + format!("{}/{}", str::from_utf8(&self.protocol[..]).unwrap_or("???"), self.version) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SessionCapabilityInfo { + pub protocol: [u8; 3], + pub version: u8, + pub packet_count: u8, + pub id_offset: u8, +} + +impl PartialOrd for SessionCapabilityInfo { + fn partial_cmp(&self, other: &SessionCapabilityInfo) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for SessionCapabilityInfo { + fn cmp(&self, b: &SessionCapabilityInfo) -> Ordering { + // By protocol id first + if self.protocol != b.protocol { + return self.protocol.cmp(&b.protocol); + } + // By version + self.version.cmp(&b.version) + } +} + +/// Network service configuration +#[derive(Debug, PartialEq, Clone)] +pub struct NetworkConfiguration { + /// Directory path to store general network configuration. None means nothing will be saved + pub config_path: Option, + /// Directory path to store network-specific configuration. None means nothing will be saved + pub net_config_path: Option, + /// IP address to listen for incoming connections. Listen to all connections by default + pub listen_address: Option, + /// IP address to advertise. Detected automatically if none. + pub public_address: Option, + /// Port for UDP connections, same as TCP by default + pub udp_port: Option, + /// Enable NAT configuration + pub nat_enabled: bool, + /// Enable discovery + pub discovery_enabled: bool, + /// List of initial node addresses + pub boot_nodes: Vec, + /// Use provided node key instead of default + pub use_secret: Option, + /// Minimum number of connected peers to maintain + pub min_peers: u32, + /// Maximum allowed number of peers + pub max_peers: u32, + /// Maximum handshakes + pub max_handshakes: u32, + /// Reserved protocols. Peers with protocol get additional connection slots. + pub reserved_protocols: HashMap, + /// List of reserved node addresses. + pub reserved_nodes: Vec, + /// The non-reserved peer mode. + pub non_reserved_mode: NonReservedPeerMode, + /// IP filter + pub ip_filter: IpFilter, + /// Client identifier + pub client_version: String, +} + +impl Default for NetworkConfiguration { + fn default() -> Self { + NetworkConfiguration::new() + } +} + +impl NetworkConfiguration { + /// Create a new instance of default settings. + pub fn new() -> Self { + NetworkConfiguration { + config_path: None, + net_config_path: None, + listen_address: None, + public_address: None, + udp_port: None, + nat_enabled: true, + discovery_enabled: true, + boot_nodes: Vec::new(), + use_secret: None, + min_peers: 25, + max_peers: 50, + max_handshakes: 64, + reserved_protocols: HashMap::new(), + ip_filter: IpFilter::default(), + reserved_nodes: Vec::new(), + non_reserved_mode: NonReservedPeerMode::Accept, + client_version: "Parity-network".into(), + } + } + + /// Create new default configuration with specified listen port. + pub fn new_with_port(port: u16) -> NetworkConfiguration { + let mut config = NetworkConfiguration::new(); + config.listen_address = Some(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), port))); + config + } + + /// Create new default configuration for localhost-only connection with random port (usefull for testing) + pub fn new_local() -> NetworkConfiguration { + let mut config = NetworkConfiguration::new(); + config.listen_address = Some(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0))); + config.nat_enabled = false; + config + } +} + +/// The severity of misbehaviour of a peer that is reported. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Severity<'a> { + /// Peer is timing out. Could be bad connectivity of overload of work on either of our sides. + Timeout, + /// Peer has been notably useless. E.g. unable to answer a request that we might reasonably consider + /// it could answer. + Useless(&'a str), + /// Peer has behaved in an invalid manner. This doesn't necessarily need to be Byzantine, but peer + /// must have taken concrete action in order to behave in such a way which is wantanly invalid. + Bad(&'a str), +} + +impl<'a> fmt::Display for Severity<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self { + Severity::Timeout => write!(fmt, "Timeout"), + Severity::Useless(r) => write!(fmt, "Useless ({})", r), + Severity::Bad(r) => write!(fmt, "Bad ({})", r), + } + } +} + +/// IO access point. This is passed to all IO handlers and provides an interface to the IO subsystem. +pub trait NetworkContext { + /// Send a packet over the network to another peer. + fn send(&self, peer: NodeIndex, packet_id: PacketId, data: Vec); + + /// Send a packet over the network to another peer using specified protocol. + fn send_protocol(&self, protocol: ProtocolId, peer: NodeIndex, packet_id: PacketId, data: Vec); + + /// Respond to a current network message. Panics if no there is no packet in the context. If the session is expired returns nothing. + fn respond(&self, packet_id: PacketId, data: Vec); + + /// Report peer. Depending on the report, peer may be disconnected and possibly banned. + fn report_peer(&self, peer: NodeIndex, reason: Severity); + + /// Check if the session is still active. + fn is_expired(&self) -> bool; + + /// Register a new IO timer. 'IoHandler::timeout' will be called with the token. + fn register_timer(&self, token: TimerToken, delay: Duration) -> Result<(), Error>; + + /// Returns peer identification string + fn peer_client_version(&self, peer: NodeIndex) -> String; + + /// Returns information on p2p session + fn session_info(&self, peer: NodeIndex) -> Option; + + /// Returns max version for a given protocol. + fn protocol_version(&self, protocol: ProtocolId, peer: NodeIndex) -> Option; + + /// Returns this object's subprotocol name. + fn subprotocol_name(&self) -> ProtocolId; +} + +impl<'a, T> NetworkContext for &'a T where T: ?Sized + NetworkContext { + fn send(&self, peer: NodeIndex, packet_id: PacketId, data: Vec) { + (**self).send(peer, packet_id, data) + } + + fn send_protocol(&self, protocol: ProtocolId, peer: NodeIndex, packet_id: PacketId, data: Vec) { + (**self).send_protocol(protocol, peer, packet_id, data) + } + + fn respond(&self, packet_id: PacketId, data: Vec) { + (**self).respond(packet_id, data) + } + + fn report_peer(&self, peer: NodeIndex, reason: Severity) { + (**self).report_peer(peer, reason) + } + + fn is_expired(&self) -> bool { + (**self).is_expired() + } + + fn register_timer(&self, token: TimerToken, delay: Duration) -> Result<(), Error> { + (**self).register_timer(token, delay) + } + + fn peer_client_version(&self, peer: NodeIndex) -> String { + (**self).peer_client_version(peer) + } + + fn session_info(&self, peer: NodeIndex) -> Option { + (**self).session_info(peer) + } + + fn protocol_version(&self, protocol: ProtocolId, peer: NodeIndex) -> Option { + (**self).protocol_version(protocol, peer) + } + + fn subprotocol_name(&self) -> ProtocolId { + (**self).subprotocol_name() + } +} + +/// Network IO protocol handler. This needs to be implemented for each new subprotocol. +/// All the handler function are called from within IO event loop. +/// `Message` is the type for message data. +pub trait NetworkProtocolHandler: Sync + Send { + /// Initialize the handler + fn initialize(&self, _io: &NetworkContext) {} + /// Called when new network packet received. + fn read(&self, io: &NetworkContext, peer: &NodeIndex, packet_id: u8, data: &[u8]); + /// Called when new peer is connected. Only called when peer supports the same protocol. + fn connected(&self, io: &NetworkContext, peer: &NodeIndex); + /// Called when a previously connected peer disconnects. + fn disconnected(&self, io: &NetworkContext, peer: &NodeIndex); + /// Timer function called after a timeout created with `NetworkContext::timeout`. + fn timeout(&self, _io: &NetworkContext, _timer: TimerToken) {} +} + +/// Non-reserved peer modes. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum NonReservedPeerMode { + /// Accept them. This is the default. + Accept, + /// Deny them. + Deny, +} + +impl NonReservedPeerMode { + /// Attempt to parse the peer mode from a string. + pub fn parse(s: &str) -> Option { + match s { + "accept" => Some(NonReservedPeerMode::Accept), + "deny" => Some(NonReservedPeerMode::Deny), + _ => None, + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct IpFilter { + pub predefined: AllowIP, + pub custom_allow: Vec, + pub custom_block: Vec, +} + +impl Default for IpFilter { + fn default() -> Self { + IpFilter { + predefined: AllowIP::All, + custom_allow: vec![], + custom_block: vec![], + } + } +} + +impl IpFilter { + /// Attempt to parse the peer mode from a string. + pub fn parse(s: &str) -> Result { + let mut filter = IpFilter::default(); + for f in s.split_whitespace() { + match f { + "all" => filter.predefined = AllowIP::All, + "private" => filter.predefined = AllowIP::Private, + "public" => filter.predefined = AllowIP::Public, + "none" => filter.predefined = AllowIP::None, + custom => { + if custom.starts_with("-") { + filter.custom_block.push(IpNetwork::from_str(&custom.to_owned().split_off(1))?) + } else { + filter.custom_allow.push(IpNetwork::from_str(custom)?) + } + } + } + } + Ok(filter) + } +} + +/// IP fiter +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum AllowIP { + /// Connect to any address + All, + /// Connect to private network only + Private, + /// Connect to public network only + Public, + /// Block all addresses + None, +} diff --git a/substrate/network-libp2p/src/transport.rs b/substrate/network-libp2p/src/transport.rs new file mode 100644 index 0000000000000..95c513ea0c243 --- /dev/null +++ b/substrate/network-libp2p/src/transport.rs @@ -0,0 +1,69 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see .? + +use libp2p::{self, Transport, mplex, secio, yamux}; +use libp2p::core::{MuxedTransport, either, upgrade}; +use libp2p::transport_timeout::TransportTimeout; +use std::time::Duration; +use tokio_io::{AsyncRead, AsyncWrite}; + +/// Builds the transport that serves as a common ground for all connections. +pub fn build_transport( + unencrypted_allowed: UnencryptedAllowed, + local_private_key: secio::SecioKeyPair +) -> impl MuxedTransport + Clone { + let base = libp2p::CommonTransport::new() + .with_upgrade({ + let secio = secio::SecioConfig { + key: local_private_key, + }; + + let mut plaintext = upgrade::toggleable(upgrade::PlainTextConfig); + match unencrypted_allowed { + UnencryptedAllowed::Allowed => plaintext.disable(), + UnencryptedAllowed::Denied => (), + }; + + // TODO: this `EitherOutput` thing shows that libp2p's API could be improved + upgrade::or( + upgrade::map(plaintext, |out| + (either::EitherOutput::First(out), None) + ), + upgrade::map(secio, |out: secio::SecioOutput<_>| + (either::EitherOutput::Second(out.stream), + Some(out.remote_key)) + ), + ) + }) + // TODO: check that the public key matches what is reported by identify + .map(|(socket, _key), _| socket) + // TODO: this `EitherOutput` thing shows that libp2p's API could be improved + .with_upgrade(upgrade::or( + upgrade::map(mplex::MplexConfig::new(), either::EitherOutput::First), + upgrade::map(yamux::Config::default(), either::EitherOutput::Second), + )) + .into_connection_reuse(); + + TransportTimeout::new(base, Duration::from_secs(20)) +} + +/// Specifies whether unencrypted communications are allowed or denied. +#[derive(Debug, Copy, Clone)] +pub enum UnencryptedAllowed { + #[allow(dead_code)] + Allowed, + Denied, +} diff --git a/substrate/network-libp2p/tests/tests.rs b/substrate/network-libp2p/tests/tests.rs new file mode 100644 index 0000000000000..fc07035f9d060 --- /dev/null +++ b/substrate/network-libp2p/tests/tests.rs @@ -0,0 +1,140 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +extern crate parking_lot; +extern crate ethcore_bytes; +extern crate ethcore_io as io; +extern crate ethcore_logger; +extern crate substrate_network_libp2p; +extern crate ethkey; + +use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering}; +use std::sync::Arc; +use std::thread; +use std::time::*; +use parking_lot::Mutex; +use ethcore_bytes::Bytes; +use substrate_network_libp2p::*; +use ethkey::{Random, Generator}; +use io::TimerToken; + +pub struct TestProtocol { + drop_session: bool, + pub packet: Mutex, + pub got_timeout: AtomicBool, + pub got_disconnect: AtomicBool, +} + +impl TestProtocol { + pub fn new(drop_session: bool) -> Self { + TestProtocol { + packet: Mutex::new(Vec::new()), + got_timeout: AtomicBool::new(false), + got_disconnect: AtomicBool::new(false), + drop_session: drop_session, + } + } + + pub fn got_packet(&self) -> bool { + self.packet.lock()[..] == b"hello"[..] + } + + pub fn got_timeout(&self) -> bool { + self.got_timeout.load(AtomicOrdering::Relaxed) + } + + pub fn got_disconnect(&self) -> bool { + self.got_disconnect.load(AtomicOrdering::Relaxed) + } +} + +impl NetworkProtocolHandler for TestProtocol { + fn initialize(&self, io: &NetworkContext) { + io.register_timer(0, Duration::from_millis(10)).unwrap(); + } + + fn read(&self, _io: &NetworkContext, _peer: &NodeIndex, packet_id: u8, data: &[u8]) { + assert_eq!(packet_id, 33); + self.packet.lock().extend(data); + } + + fn connected(&self, io: &NetworkContext, peer: &NodeIndex) { + if self.drop_session { + io.report_peer(*peer, Severity::Bad("We are evil and just want to drop")) + } else { + io.respond(33, "hello".to_owned().into_bytes()); + } + } + + fn disconnected(&self, _io: &NetworkContext, _peer: &NodeIndex) { + self.got_disconnect.store(true, AtomicOrdering::Relaxed); + } + + /// Timer function called after a timeout created with `NetworkContext::timeout`. + fn timeout(&self, _io: &NetworkContext, timer: TimerToken) { + assert_eq!(timer, 0); + self.got_timeout.store(true, AtomicOrdering::Relaxed); + } +} + + +#[test] +fn net_service() { + let service = NetworkService::new(NetworkConfiguration::new_local(), None).expect("Error creating network service"); + service.start(vec![(Arc::new(TestProtocol::new(false)), *b"myp", &[(1u8, 1)])]).unwrap(); +} + +#[test] +fn net_start_stop() { + let config = NetworkConfiguration::new_local(); + let service = NetworkService::new(config, None).unwrap(); + service.start(vec![]).unwrap(); + service.stop(); + service.start(vec![]).unwrap(); +} + +#[test] +#[ignore] // TODO: how is this test even supposed to work? +fn net_disconnect() { + let key1 = Random.generate().unwrap(); + let mut config1 = NetworkConfiguration::new_local(); + config1.use_secret = Some(key1.secret().clone()); + config1.boot_nodes = vec![ ]; + let service1 = NetworkService::new(config1, None).unwrap(); + let handler1 = Arc::new(TestProtocol::new(false)); + service1.start(vec![(handler1.clone(), *b"tst", &[(42u8, 1), (43u8, 1)])]).unwrap(); + let mut config2 = NetworkConfiguration::new_local(); + config2.boot_nodes = vec![ service1.external_url().unwrap() ]; + let service2 = NetworkService::new(config2, None).unwrap(); + let handler2 = Arc::new(TestProtocol::new(true)); + service2.start(vec![(handler2.clone(), *b"tst", &[(42u8, 1), (43u8, 1)])]).unwrap(); + while !(handler1.got_disconnect() && handler2.got_disconnect()) { + thread::sleep(Duration::from_millis(50)); + } + assert!(handler1.got_disconnect()); + assert!(handler2.got_disconnect()); +} + +#[test] +fn net_timeout() { + let config = NetworkConfiguration::new_local(); + let service = NetworkService::new(config, None).unwrap(); + let handler = Arc::new(TestProtocol::new(false)); + service.start(vec![(handler.clone(), *b"tst", &[(42u8, 1), (43u8, 1)])]).unwrap(); + while !handler.got_timeout() { + thread::sleep(Duration::from_millis(50)); + } +} diff --git a/substrate/network/Cargo.toml b/substrate/network/Cargo.toml index dd5011953a47f..7362911ee532f 100644 --- a/substrate/network/Cargo.toml +++ b/substrate/network/Cargo.toml @@ -9,27 +9,19 @@ authors = ["Parity Technologies "] [dependencies] log = "0.3" -rand = "0.3" parking_lot = "0.4" -error-chain = "0.11" +error-chain = "0.12" bitflags = "1.0" -serde = "1.0" -serde_derive = "1.0" -serde_json = "1.0" futures = "0.1.17" linked-hash-map = "0.5" -ethcore-network = { git = "https://github.com/paritytech/parity.git" } -ethcore-network-devp2p = { git = "https://github.com/paritytech/parity.git" } +rustc-hex = "1.0" ethcore-io = { git = "https://github.com/paritytech/parity.git" } ed25519 = { path = "../../substrate/ed25519" } substrate-primitives = { path = "../../substrate/primitives" } substrate-client = { path = "../../substrate/client" } -substrate-state-machine = { path = "../../substrate/state-machine" } -substrate-serializer = { path = "../../substrate/serializer" } -substrate-runtime-support = { path = "../../substrate/runtime-support" } substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" } -substrate-bft = { path = "../../substrate/bft" } substrate-codec = { path = "../../substrate/codec" } +substrate-network-libp2p = { path = "../../substrate/network-libp2p" } [dev-dependencies] env_logger = "0.4" diff --git a/substrate/network/src/blocks.rs b/substrate/network/src/blocks.rs index f5b32ad38739f..ffb95bf1f3f34 100644 --- a/substrate/network/src/blocks.rs +++ b/substrate/network/src/blocks.rs @@ -19,8 +19,8 @@ use std::cmp; use std::ops::Range; use std::collections::{HashMap, BTreeMap}; use std::collections::hash_map::Entry; -use network::PeerId; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; +use network_libp2p::NodeIndex; +use runtime_primitives::traits::{Block as BlockT, NumberFor, As}; use message; const MAX_PARALLEL_DOWNLOADS: u32 = 1; @@ -29,23 +29,23 @@ const MAX_PARALLEL_DOWNLOADS: u32 = 1; #[derive(Debug, Clone, PartialEq, Eq)] pub struct BlockData { pub block: message::BlockData, - pub origin: PeerId, + pub origin: NodeIndex, } #[derive(Debug)] enum BlockRangeState { Downloading { - len: u64, + len: NumberFor, downloading: u32, }, Complete(Vec>), } -impl BlockRangeState where B::Header: HeaderT { - pub fn len(&self) -> u64 { +impl BlockRangeState { + pub fn len(&self) -> NumberFor { match *self { BlockRangeState::Downloading { len, .. } => len, - BlockRangeState::Complete(ref blocks) => blocks.len() as u64, + BlockRangeState::Complete(ref blocks) => As::sa(blocks.len() as u64), } } } @@ -54,11 +54,11 @@ impl BlockRangeState where B::Header: HeaderT { #[derive(Default)] pub struct BlockCollection { /// Downloaded blocks. - blocks: BTreeMap>, - peer_requests: HashMap, + blocks: BTreeMap, BlockRangeState>, + peer_requests: HashMap>, } -impl BlockCollection where B::Header: HeaderT { +impl BlockCollection { /// Create a new instance. pub fn new() -> Self { BlockCollection { @@ -74,7 +74,7 @@ impl BlockCollection where B::Header: HeaderT { } /// Insert a set of blocks into collection. - pub fn insert(&mut self, start: u64, blocks: Vec>, peer_id: PeerId) { + pub fn insert(&mut self, start: NumberFor, blocks: Vec>, who: NodeIndex) { if blocks.is_empty() { return; } @@ -92,26 +92,26 @@ impl BlockCollection where B::Header: HeaderT { _ => (), } - self.blocks.insert(start, BlockRangeState::Complete(blocks.into_iter().map(|b| BlockData { origin: peer_id, block: b }).collect())); + self.blocks.insert(start, BlockRangeState::Complete(blocks.into_iter().map(|b| BlockData { origin: who, block: b }).collect())); } /// Returns a set of block hashes that require a header download. The returned set is marked as being downloaded. - pub fn needed_blocks(&mut self, peer_id: PeerId, count: usize, peer_best: u64, common: u64) -> Option> { + pub fn needed_blocks(&mut self, who: NodeIndex, count: usize, peer_best: NumberFor, common: NumberFor) -> Option>> { // First block number that we need to download - let first_different = common + 1; - let count = count as u64; + let first_different = common + As::sa(1); + let count = As::sa(count as u64); let (mut range, downloading) = { let mut downloading_iter = self.blocks.iter().peekable(); - let mut prev: Option<(&u64, &BlockRangeState)> = None; + let mut prev: Option<(&NumberFor, &BlockRangeState)> = None; loop { let next = downloading_iter.next(); break match &(prev, next) { &(Some((start, &BlockRangeState::Downloading { ref len, downloading })), _) if downloading < MAX_PARALLEL_DOWNLOADS => (*start .. *start + *len, downloading), - &(Some((start, r)), Some((next_start, _))) if start + r.len() < *next_start => + &(Some((start, r)), Some((next_start, _))) if *start + r.len() < *next_start => (*start + r.len() .. cmp::min(*next_start, *start + r.len() + count), 0), // gap &(Some((start, r)), None) => - (start + r.len() .. start + r.len() + count, 0), // last range + (*start + r.len() .. *start + r.len() + count, 0), // last range &(None, None) => (first_different .. first_different + count, 0), // empty &(None, Some((start, _))) if *start > first_different => @@ -125,11 +125,11 @@ impl BlockCollection where B::Header: HeaderT { }; // crop to peers best if range.start > peer_best { - trace!(target: "sync", "Out of range for peer {} ({} vs {})", peer_id, range.start, peer_best); + trace!(target: "sync", "Out of range for peer {} ({} vs {})", who, range.start, peer_best); return None; } - range.end = cmp::min(peer_best + 1, range.end); - self.peer_requests.insert(peer_id, range.start); + range.end = cmp::min(peer_best + As::sa(1), range.end); + self.peer_requests.insert(who, range.start); self.blocks.insert(range.start, BlockRangeState::Downloading{ len: range.end - range.start, downloading: downloading + 1 }); if range.end <= range.start { panic!("Empty range {:?}, count={}, peer_best={}, common={}, blocks={:?}", range, count, peer_best, common, self.blocks); @@ -138,7 +138,7 @@ impl BlockCollection where B::Header: HeaderT { } /// Get a valid chain of blocks ordered in descending order and ready for importing into blockchain. - pub fn drain(&mut self, from: u64) -> Vec> { + pub fn drain(&mut self, from: NumberFor) -> Vec> { let mut drained = Vec::new(); let mut ranges = Vec::new(); { @@ -146,7 +146,7 @@ impl BlockCollection where B::Header: HeaderT { for (start, range_data) in &mut self.blocks { match range_data { &mut BlockRangeState::Complete(ref mut blocks) if *start <= prev => { - prev = *start + blocks.len() as u64; + prev = *start + As::sa(blocks.len() as u64); let mut blocks = mem::replace(blocks, Vec::new()); drained.append(&mut blocks); ranges.push(*start); @@ -162,8 +162,8 @@ impl BlockCollection where B::Header: HeaderT { drained } - pub fn clear_peer_download(&mut self, peer_id: PeerId) { - match self.peer_requests.entry(peer_id) { + pub fn clear_peer_download(&mut self, who: NodeIndex) { + match self.peer_requests.entry(who) { Entry::Occupied(entry) => { let start = entry.remove(); let remove = match self.blocks.get_mut(&start) { diff --git a/substrate/network/src/chain.rs b/substrate/network/src/chain.rs index a2eff9b54d8a5..d698ab0900aa7 100644 --- a/substrate/network/src/chain.rs +++ b/substrate/network/src/chain.rs @@ -1,31 +1,31 @@ // Copyright 2017 Parity Technologies (UK) Ltd. // This file is part of Polkadot. -// Polkadot is free software: you can redistribute it and/or modify +// Substrate 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. -// Polkadot is distributed in the hope that it will be useful, +// Substrate 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 Polkadot. If not, see . +// along with Substrate. If not, see . //! Blockchain access trait -use client::{self, Client as PolkadotClient, ImportResult, ClientInfo, BlockStatus, BlockOrigin, CallExecutor}; +use client::{self, Client as SubstrateClient, ImportResult, ClientInfo, BlockStatus, BlockOrigin, CallExecutor}; use client::error::Error; -use state_machine; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; use runtime_primitives::generic::BlockId; use runtime_primitives::bft::Justification; +/// Local client abstraction for the network. pub trait Client: Send + Sync { /// Import a new block. Parent is supposed to be existing in the blockchain. - fn import(&self, is_best: bool, header: Block::Header, justification: Justification, body: Option>) -> Result; + fn import(&self, origin: BlockOrigin, header: Block::Header, justification: Justification, body: Option>) -> Result; /// Get blockchain info. fn info(&self) -> Result, Error>; @@ -45,48 +45,53 @@ pub trait Client: Send + Sync { /// Get block justification. fn justification(&self, id: &BlockId) -> Result>, Error>; + /// Get storage read execution proof. + fn read_proof(&self, block: &Block::Hash, key: &[u8]) -> Result>, Error>; + /// Get method execution proof. fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec, Vec>), Error>; } -impl Client for PolkadotClient where +impl Client for SubstrateClient where B: client::backend::Backend + Send + Sync + 'static, E: CallExecutor + Send + Sync + 'static, Block: BlockT, - Error: From<<>::State as state_machine::backend::Backend>::Error>, { - - fn import(&self, is_best: bool, header: Block::Header, justification: Justification, body: Option>) -> Result { +{ + fn import(&self, origin: BlockOrigin, header: Block::Header, justification: Justification, body: Option>) -> Result { // TODO: defer justification check. let justified_header = self.check_justification(header, justification.into())?; - let origin = if is_best { BlockOrigin::NetworkBroadcast } else { BlockOrigin::NetworkInitialSync }; - (self as &PolkadotClient).import_block(origin, justified_header, body) + (self as &SubstrateClient).import_block(origin, justified_header, body) } fn info(&self) -> Result, Error> { - (self as &PolkadotClient).info() + (self as &SubstrateClient).info() } fn block_status(&self, id: &BlockId) -> Result { - (self as &PolkadotClient).block_status(id) + (self as &SubstrateClient).block_status(id) } fn block_hash(&self, block_number: ::Number) -> Result, Error> { - (self as &PolkadotClient).block_hash(block_number) + (self as &SubstrateClient).block_hash(block_number) } fn header(&self, id: &BlockId) -> Result, Error> { - (self as &PolkadotClient).header(id) + (self as &SubstrateClient).header(id) } fn body(&self, id: &BlockId) -> Result>, Error> { - (self as &PolkadotClient).body(id) + (self as &SubstrateClient).body(id) } fn justification(&self, id: &BlockId) -> Result>, Error> { - (self as &PolkadotClient).justification(id) + (self as &SubstrateClient).justification(id) + } + + fn read_proof(&self, block: &Block::Hash, key: &[u8]) -> Result>, Error> { + (self as &SubstrateClient).read_proof(&BlockId::Hash(block.clone()), key) } fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec, Vec>), Error> { - (self as &PolkadotClient).execution_proof(&BlockId::Hash(block.clone()), method, data) + (self as &SubstrateClient).execution_proof(&BlockId::Hash(block.clone()), method, data) } } diff --git a/substrate/network/src/config.rs b/substrate/network/src/config.rs index 7e21a5ded3b02..008b662b87291 100644 --- a/substrate/network/src/config.rs +++ b/substrate/network/src/config.rs @@ -14,19 +14,19 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see .? -pub use service::Role; +pub use service::Roles; /// Protocol configuration #[derive(Clone)] pub struct ProtocolConfig { /// Assigned roles. - pub roles: Role, + pub roles: Roles, } impl Default for ProtocolConfig { fn default() -> ProtocolConfig { ProtocolConfig { - roles: Role::FULL, + roles: Roles::FULL, } } } diff --git a/substrate/network/src/consensus.rs b/substrate/network/src/consensus.rs deleted file mode 100644 index 60abb9b2d4277..0000000000000 --- a/substrate/network/src/consensus.rs +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see .? - -//! Consensus related bits of the network service. - -use std::collections::{HashMap, HashSet}; -use futures::sync::mpsc; -use std::time::{Instant, Duration}; -use io::SyncIo; -use protocol::Protocol; -use network::PeerId; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; -use runtime_primitives::generic::BlockId; -use message::{self, generic::Message as GenericMessage}; - -// TODO: Add additional spam/DoS attack protection. -const MESSAGE_LIFETIME: Duration = Duration::from_secs(600); - -struct PeerConsensus { - known_messages: HashSet, -} - -/// Consensus network protocol handler. Manages statements and candidate requests. -pub struct Consensus { - peers: HashMap>, - bft_message_sink: Option<(mpsc::UnboundedSender>, B::Hash)>, - messages: Vec<(B::Hash, Instant, message::Message)>, - message_hashes: HashSet, -} - -impl Consensus where B::Header: HeaderT { - /// Create a new instance. - pub fn new() -> Self { - Consensus { - peers: HashMap::new(), - bft_message_sink: None, - messages: Default::default(), - message_hashes: Default::default(), - } - } - - /// Closes all notification streams. - pub fn restart(&mut self) { - self.bft_message_sink = None; - } - - /// Handle new connected peer. - pub fn new_peer(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, roles: &[message::Role]) { - if roles.iter().any(|r| *r == message::Role::Validator) { - trace!(target:"sync", "Registering validator {}", peer_id); - // Send out all known messages. - // TODO: limit by size - let mut known_messages = HashSet::new(); - for &(ref hash, _, ref message) in self.messages.iter() { - known_messages.insert(hash.clone()); - protocol.send_message(io, peer_id, message.clone()); - } - self.peers.insert(peer_id, PeerConsensus { - known_messages, - }); - } - } - - fn propagate(&mut self, io: &mut SyncIo, protocol: &Protocol, message: message::Message, hash: B::Hash) { - for (id, ref mut peer) in self.peers.iter_mut() { - if peer.known_messages.insert(hash.clone()) { - protocol.send_message(io, *id, message.clone()); - } - } - } - - fn register_message(&mut self, hash: B::Hash, message: message::Message) { - if self.message_hashes.insert(hash) { - self.messages.push((hash, Instant::now(), message)); - } - } - - pub fn on_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, message: message::LocalizedBftMessage, hash: B::Hash) { - if self.message_hashes.contains(&hash) { - trace!(target:"sync", "Ignored already known BFT message from {}", peer_id); - return; - } - - match (protocol.chain().info(), protocol.chain().header(&BlockId::Hash(message.parent_hash))) { - (_, Err(e)) | (Err(e), _) => { - debug!(target:"sync", "Error reading blockchain: {:?}", e); - return; - }, - (Ok(info), Ok(Some(header))) => { - if header.number() < &info.chain.best_number { - trace!(target:"sync", "Ignored ancient BFT message from {}, hash={}", peer_id, message.parent_hash); - return; - } - }, - (Ok(_), Ok(None)) => {}, - } - - if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { - peer.known_messages.insert(hash); - // TODO: validate signature? - if let Some((sink, parent_hash)) = self.bft_message_sink.take() { - if message.parent_hash == parent_hash { - if let Err(e) = sink.unbounded_send(message.clone()) { - trace!(target:"sync", "Error broadcasting BFT message notification: {:?}", e); - } else { - self.bft_message_sink = Some((sink, parent_hash)); - } - } - } - } else { - trace!(target:"sync", "Ignored BFT statement from unregistered peer {}", peer_id); - return; - } - - let message = GenericMessage::BftMessage(message); - self.register_message(hash.clone(), message.clone()); - // Propagate to other peers. - self.propagate(io, protocol, message, hash); - } - - pub fn bft_messages(&mut self, parent_hash: B::Hash) -> mpsc::UnboundedReceiver> { - let (sink, stream) = mpsc::unbounded(); - - for &(_, _, ref message) in self.messages.iter() { - let bft_message = match *message { - GenericMessage::BftMessage(ref msg) => msg, - _ => continue, - }; - - if bft_message.parent_hash == parent_hash { - sink.unbounded_send(bft_message.clone()).expect("receiving end known to be open; qed"); - } - } - - self.bft_message_sink = Some((sink, parent_hash)); - stream - } - - pub fn send_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol, message: message::LocalizedBftMessage) { - // Broadcast message to all validators. - trace!(target:"sync", "Broadcasting BFT message {:?}", message); - let message = GenericMessage::BftMessage(message); - let hash = Protocol::hash_message(&message); - self.register_message(hash.clone(), message.clone()); - self.propagate(io, protocol, message, hash); - } - - pub fn peer_disconnected(&mut self, _io: &mut SyncIo, _protocol: &Protocol, peer_id: PeerId) { - self.peers.remove(&peer_id); - } - - pub fn collect_garbage(&mut self, best_header: Option<&B::Header>) { - let hashes = &mut self.message_hashes; - let before = self.messages.len(); - let now = Instant::now(); - self.messages.retain(|&(ref hash, timestamp, ref message)| { - if timestamp >= now - MESSAGE_LIFETIME && - best_header.map_or(true, |header| - match *message { - GenericMessage::BftMessage(ref msg) => &msg.parent_hash != header.parent_hash(), - _ => true, - }) - { - true - } else { - hashes.remove(hash); - false - } - }); - if self.messages.len() != before { - trace!(target:"sync", "Cleaned up {} stale messages", before - self.messages.len()); - } - for (_, ref mut peer) in self.peers.iter_mut() { - peer.known_messages.retain(|h| hashes.contains(h)); - } - } -} - -#[cfg(test)] -mod tests { - use runtime_primitives::bft::Justification; - use runtime_primitives::testing::{H256, Header, Block as RawBlock}; - use std::time::Instant; - use message::{self, generic::Message as GenericMessage}; - use super::{Consensus, MESSAGE_LIFETIME}; - - type Block = RawBlock; - - #[test] - fn collects_garbage() { - let prev_hash = H256::random(); - let best_hash = H256::random(); - let mut consensus = Consensus::::new(); - let now = Instant::now(); - let m1_hash = H256::random(); - let m2_hash = H256::random(); - let m1 = GenericMessage::BftMessage(message::LocalizedBftMessage { - parent_hash: prev_hash, - message: message::generic::BftMessage::Auxiliary(Justification { - round_number: 0, - hash: Default::default(), - signatures: Default::default(), - }), - }); - let m2 = GenericMessage::BftMessage(message::LocalizedBftMessage { - parent_hash: best_hash, - message: message::generic::BftMessage::Auxiliary(Justification { - round_number: 0, - hash: Default::default(), - signatures: Default::default(), - }), - }); - consensus.messages.push((m1_hash, now, m1)); - consensus.messages.push((m2_hash, now, m2.clone())); - consensus.message_hashes.insert(m1_hash); - consensus.message_hashes.insert(m2_hash); - - // nothing to collect - consensus.collect_garbage(None); - assert_eq!(consensus.messages.len(), 2); - assert_eq!(consensus.message_hashes.len(), 2); - - // random header, nothing should be cleared - let mut header = Header { - parent_hash: H256::default(), - number: 0, - state_root: H256::default(), - extrinsics_root: H256::default(), - digest: Default::default(), - }; - - consensus.collect_garbage(Some(&header)); - assert_eq!(consensus.messages.len(), 2); - assert_eq!(consensus.message_hashes.len(), 2); - - // header that matches one of the messages - header.parent_hash = prev_hash; - consensus.collect_garbage(Some(&header)); - assert_eq!(consensus.messages.len(), 1); - assert_eq!(consensus.message_hashes.len(), 1); - assert!(consensus.message_hashes.contains(&m2_hash)); - - // make timestamp expired - consensus.messages.clear(); - consensus.messages.push((m2_hash, now - MESSAGE_LIFETIME, m2)); - consensus.collect_garbage(None); - assert!(consensus.messages.is_empty()); - assert!(consensus.message_hashes.is_empty()); - } -} diff --git a/substrate/network/src/consensus_gossip.rs b/substrate/network/src/consensus_gossip.rs new file mode 100644 index 0000000000000..8e9065b3a7a46 --- /dev/null +++ b/substrate/network/src/consensus_gossip.rs @@ -0,0 +1,379 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see .? + +//! Utility for gossip of network messages between authorities. +//! Handles chain-specific and standard BFT messages. + +use std::collections::{HashMap, HashSet}; +use futures::sync::mpsc; +use std::time::{Instant, Duration}; +use network_libp2p::NodeIndex; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; +use runtime_primitives::generic::BlockId; +use message::{self, generic::Message as GenericMessage}; +use protocol::Context; +use service::Roles; + +// TODO: Add additional spam/DoS attack protection. +const MESSAGE_LIFETIME: Duration = Duration::from_secs(600); + +struct PeerConsensus { + known_messages: HashSet, +} + +/// Consensus messages. +#[derive(Debug, Clone, PartialEq)] +pub enum ConsensusMessage { + /// A message concerning BFT agreement + Bft(message::LocalizedBftMessage), + /// A message concerning some chain-specific aspect of consensus + ChainSpecific(Vec, B::Hash), +} + +struct MessageEntry { + hash: B::Hash, + message: ConsensusMessage, + instant: Instant, +} + +/// Consensus network protocol handler. Manages statements and candidate requests. +pub struct ConsensusGossip { + peers: HashMap>, + message_sink: Option<(mpsc::UnboundedSender>, B::Hash)>, + messages: Vec>, + message_hashes: HashSet, +} + +impl ConsensusGossip where B::Header: HeaderT { + /// Create a new instance. + pub fn new() -> Self { + ConsensusGossip { + peers: HashMap::new(), + message_sink: None, + messages: Default::default(), + message_hashes: Default::default(), + } + } + + /// Closes all notification streams. + pub fn abort(&mut self) { + self.message_sink = None; + } + + /// Handle new connected peer. + pub fn new_peer(&mut self, protocol: &mut Context, who: NodeIndex, roles: Roles) { + if roles.intersects(Roles::AUTHORITY | Roles::FULL) { + trace!(target:"gossip", "Registering {:?} {}", roles, who); + // Send out all known messages. + // TODO: limit by size + let mut known_messages = HashSet::new(); + for entry in self.messages.iter() { + known_messages.insert(entry.hash); + let message = match entry.message { + ConsensusMessage::Bft(ref bft) => GenericMessage::BftMessage(bft.clone()), + ConsensusMessage::ChainSpecific(ref msg, _) => GenericMessage::ChainSpecific(msg.clone()), + }; + + protocol.send_message(who, message); + } + self.peers.insert(who, PeerConsensus { + known_messages, + }); + } + } + + fn propagate(&mut self, protocol: &mut Context, message: message::Message, hash: B::Hash) { + for (id, ref mut peer) in self.peers.iter_mut() { + if peer.known_messages.insert(hash.clone()) { + trace!(target:"gossip", "Propagating to {}: {:?}", id, message); + protocol.send_message(*id, message.clone()); + } + } + } + + fn register_message(&mut self, hash: B::Hash, message: ConsensusMessage) { + if self.message_hashes.insert(hash) { + self.messages.push(MessageEntry { + hash, + instant: Instant::now(), + message, + }); + } + } + + /// Handles incoming BFT message, passing to stream and repropagating. + pub fn on_bft_message(&mut self, protocol: &mut Context, who: NodeIndex, message: message::LocalizedBftMessage) { + if let Some((hash, message)) = self.handle_incoming(protocol, who, ConsensusMessage::Bft(message)) { + // propagate to other peers. + self.multicast(protocol, message, Some(hash)); + } + } + + /// Handles incoming chain-specific message and repropagates + pub fn on_chain_specific(&mut self, protocol: &mut Context, who: NodeIndex, message: Vec, parent_hash: B::Hash) { + if let Some((hash, message)) = self.handle_incoming(protocol, who, ConsensusMessage::ChainSpecific(message, parent_hash)) { + // propagate to other peers. + self.multicast(protocol, message, Some(hash)); + } + } + + /// Get a stream of messages relevant to consensus on top of a given parent hash. + pub fn messages_for(&mut self, parent_hash: B::Hash) -> mpsc::UnboundedReceiver> { + let (sink, stream) = mpsc::unbounded(); + + for entry in self.messages.iter() { + let message_matches = match entry.message { + ConsensusMessage::Bft(ref msg) => msg.parent_hash == parent_hash, + ConsensusMessage::ChainSpecific(_, ref h) => h == &parent_hash, + }; + + if message_matches { + sink.unbounded_send(entry.message.clone()).expect("receiving end known to be open; qed"); + } + } + + self.message_sink = Some((sink, parent_hash)); + stream + } + + /// Multicast a chain-specific message to other authorities. + pub fn multicast_chain_specific(&mut self, protocol: &mut Context, message: Vec, parent_hash: B::Hash) { + trace!(target:"gossip", "sending chain-specific message"); + self.multicast(protocol, ConsensusMessage::ChainSpecific(message, parent_hash), None); + } + + /// Multicast a BFT message to other authorities + pub fn multicast_bft_message(&mut self, protocol: &mut Context, message: message::LocalizedBftMessage) { + // Broadcast message to all authorities. + trace!(target:"gossip", "Broadcasting BFT message {:?}", message); + self.multicast(protocol, ConsensusMessage::Bft(message), None); + } + + /// Call when a peer has been disconnected to stop tracking gossip status. + pub fn peer_disconnected(&mut self, _protocol: &mut Context, who: NodeIndex) { + self.peers.remove(&who); + } + + /// Prune old or no longer relevant consensus messages. + /// Supply an optional block hash where consensus is known to have concluded. + pub fn collect_garbage(&mut self, best_hash: Option<&B::Hash>) { + let hashes = &mut self.message_hashes; + let before = self.messages.len(); + let now = Instant::now(); + self.messages.retain(|entry| { + if entry.instant + MESSAGE_LIFETIME >= now && + best_hash.map_or(true, |parent_hash| + match entry.message { + ConsensusMessage::Bft(ref msg) => &msg.parent_hash != parent_hash, + ConsensusMessage::ChainSpecific(_, ref h) => h != parent_hash, + }) + { + true + } else { + hashes.remove(&entry.hash); + false + } + }); + if self.messages.len() != before { + trace!(target:"gossip", "Cleaned up {} stale messages", before - self.messages.len()); + } + for (_, ref mut peer) in self.peers.iter_mut() { + peer.known_messages.retain(|h| hashes.contains(h)); + } + } + + fn handle_incoming(&mut self, protocol: &mut Context, who: NodeIndex, message: ConsensusMessage) -> Option<(B::Hash, ConsensusMessage)> { + let (hash, parent, message) = match message { + ConsensusMessage::Bft(msg) => { + let parent = msg.parent_hash; + let generic = GenericMessage::BftMessage(msg); + ( + ::protocol::hash_message(&generic), + parent, + match generic { + GenericMessage::BftMessage(msg) => ConsensusMessage::Bft(msg), + _ => panic!("`generic` is known to be the `BftMessage` variant; qed"), + } + ) + } + ConsensusMessage::ChainSpecific(msg, parent) => { + let generic = GenericMessage::ChainSpecific(msg); + ( + ::protocol::hash_message::(&generic), + parent, + match generic { + GenericMessage::ChainSpecific(msg) => ConsensusMessage::ChainSpecific(msg, parent), + _ => panic!("`generic` is known to be the `ChainSpecific` variant; qed"), + } + ) + } + }; + + if self.message_hashes.contains(&hash) { + trace!(target:"gossip", "Ignored already known message from {}", who); + return None; + } + + match (protocol.client().info(), protocol.client().header(&BlockId::Hash(parent))) { + (_, Err(e)) | (Err(e), _) => { + debug!(target:"gossip", "Error reading blockchain: {:?}", e); + return None; + }, + (Ok(info), Ok(Some(header))) => { + if header.number() < &info.chain.best_number { + trace!(target:"gossip", "Ignored ancient message from {}, hash={}", who, parent); + return None; + } + }, + (Ok(_), Ok(None)) => {}, + } + + if let Some(ref mut peer) = self.peers.get_mut(&who) { + peer.known_messages.insert(hash); + if let Some((sink, parent_hash)) = self.message_sink.take() { + if parent == parent_hash { + if let Err(e) = sink.unbounded_send(message.clone()) { + trace!(target:"gossip", "Error broadcasting message notification: {:?}", e); + } + } + + self.message_sink = Some((sink, parent_hash)); + } + } else { + trace!(target:"gossip", "Ignored statement from unregistered peer {}", who); + return None; + } + + Some((hash, message)) + } + + fn multicast(&mut self, protocol: &mut Context, message: ConsensusMessage, hash: Option) { + let generic = match message { + ConsensusMessage::Bft(ref message) => GenericMessage::BftMessage(message.clone()), + ConsensusMessage::ChainSpecific(ref message, _) => GenericMessage::ChainSpecific(message.clone()), + }; + + let hash = hash.unwrap_or_else(|| ::protocol::hash_message(&generic)); + self.register_message(hash, message); + self.propagate(protocol, generic, hash); + } +} + +#[cfg(test)] +mod tests { + use runtime_primitives::bft::Justification; + use runtime_primitives::testing::{H256, Header, Block as RawBlock}; + use std::time::Instant; + use message::{self, generic}; + use super::*; + + type Block = RawBlock; + + #[test] + fn collects_garbage() { + let prev_hash = H256::random(); + let best_hash = H256::random(); + let mut consensus = ConsensusGossip::::new(); + let now = Instant::now(); + let m1_hash = H256::random(); + let m2_hash = H256::random(); + let m1 = ConsensusMessage::Bft(message::LocalizedBftMessage { + parent_hash: prev_hash, + message: message::generic::BftMessage::Auxiliary(Justification { + round_number: 0, + hash: Default::default(), + signatures: Default::default(), + }), + }); + let m2 = ConsensusMessage::ChainSpecific(vec![1, 2, 3], best_hash); + + macro_rules! push_msg { + ($hash:expr, $now: expr, $m:expr) => { + consensus.messages.push(MessageEntry { + hash: $hash, + instant: $now, + message: $m, + }) + } + } + + push_msg!(m1_hash, now, m1); + push_msg!(m2_hash, now, m2.clone()); + consensus.message_hashes.insert(m1_hash); + consensus.message_hashes.insert(m2_hash); + + // nothing to collect + consensus.collect_garbage(None); + assert_eq!(consensus.messages.len(), 2); + assert_eq!(consensus.message_hashes.len(), 2); + + // random header, nothing should be cleared + let mut header = Header { + parent_hash: H256::default(), + number: 0, + state_root: H256::default(), + extrinsics_root: H256::default(), + digest: Default::default(), + }; + + consensus.collect_garbage(Some(&H256::default())); + assert_eq!(consensus.messages.len(), 2); + assert_eq!(consensus.message_hashes.len(), 2); + + // header that matches one of the messages + header.parent_hash = prev_hash; + consensus.collect_garbage(Some(&prev_hash)); + assert_eq!(consensus.messages.len(), 1); + assert_eq!(consensus.message_hashes.len(), 1); + assert!(consensus.message_hashes.contains(&m2_hash)); + + // make timestamp expired + consensus.messages.clear(); + push_msg!(m2_hash, now - MESSAGE_LIFETIME, m2); + consensus.collect_garbage(None); + assert!(consensus.messages.is_empty()); + assert!(consensus.message_hashes.is_empty()); + } + + #[test] + fn message_stream_include_those_sent_before_asking_for_stream() { + use futures::Stream; + + let mut consensus = ConsensusGossip::new(); + + let bft_message = generic::BftMessage::Consensus(generic::SignedConsensusMessage::Vote(generic::SignedConsensusVote { + vote: generic::ConsensusVote::AdvanceRound(0), + sender: [0; 32].into(), + signature: Default::default(), + })); + + let parent_hash = [1; 32].into(); + + let localized = ::message::LocalizedBftMessage:: { + message: bft_message, + parent_hash: parent_hash, + }; + + let message = generic::Message::BftMessage(localized.clone()); + let message_hash = ::protocol::hash_message::(&message); + + let message = ConsensusMessage::Bft(localized); + consensus.register_message(message_hash, message.clone()); + let stream = consensus.messages_for(parent_hash); + + assert_eq!(stream.wait().next(), Some(Ok(message))); + } +} diff --git a/substrate/network/src/error.rs b/substrate/network/src/error.rs index 120cfe0b4f358..fcf881c68d0a9 100644 --- a/substrate/network/src/error.rs +++ b/substrate/network/src/error.rs @@ -16,12 +16,14 @@ //! Polkadot service possible errors. -use network::Error as NetworkError; +use std::io::Error as IoError; +use network_libp2p::Error as NetworkError; use client; error_chain! { foreign_links { Network(NetworkError) #[doc = "Devp2p error."]; + Io(IoError) #[doc = "IO error."]; } links { diff --git a/substrate/network/src/import_queue.rs b/substrate/network/src/import_queue.rs new file mode 100644 index 0000000000000..9e010c2bee89e --- /dev/null +++ b/substrate/network/src/import_queue.rs @@ -0,0 +1,593 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see .? + +//! Blocks import queue. + +use std::collections::{HashSet, VecDeque}; +use std::sync::{Arc, Weak}; +use std::sync::atomic::{AtomicBool, Ordering}; +use parking_lot::{Condvar, Mutex, RwLock}; + +use client::{BlockOrigin, ImportResult}; +use network_libp2p::{NodeIndex, Severity}; + +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}; + +use blocks::BlockData; +use chain::Client; +use error::{ErrorKind, Error}; +use protocol::Context; +use service::ExecuteInContext; +use sync::ChainSync; + +/// Blocks import queue API. +pub trait ImportQueue: Send + Sync { + /// Clear the queue when sync is restarting. + fn clear(&self); + /// Clears the import queue and stops importing. + fn stop(&self); + /// Get queue status. + fn status(&self) -> ImportQueueStatus; + /// Is block with given hash currently in the queue. + fn is_importing(&self, hash: &B::Hash) -> bool; + /// Import bunch of blocks. + fn import_blocks(&self, sync: &mut ChainSync, protocol: &mut Context, blocks: (BlockOrigin, Vec>)); +} + +/// Import queue status. It isn't completely accurate. +pub struct ImportQueueStatus { + /// Number of blocks that are currently in the queue. + pub importing_count: usize, + /// The number of the best block that was ever in the queue since start/last failure. + pub best_importing_number: <::Header as HeaderT>::Number, +} + +/// Blocks import queue that is importing blocks in the separate thread. +pub struct AsyncImportQueue { + handle: Mutex>>, + data: Arc>, +} + +/// Locks order: queue, queue_blocks, best_importing_number +struct AsyncImportQueueData { + signal: Condvar, + queue: Mutex>)>>, + queue_blocks: RwLock>, + best_importing_number: RwLock<<::Header as HeaderT>::Number>, + is_stopping: AtomicBool, +} + +impl AsyncImportQueue { + pub fn new() -> Self { + Self { + handle: Mutex::new(None), + data: Arc::new(AsyncImportQueueData::new()), + } + } + + pub fn start>(&self, sync: Weak>>, service: Weak, chain: Weak>) -> Result<(), Error> { + debug_assert!(self.handle.lock().is_none()); + + let qdata = self.data.clone(); + *self.handle.lock() = Some(::std::thread::Builder::new().name("ImportQueue".into()).spawn(move || { + import_thread(sync, service, chain, qdata) + }).map_err(|err| Error::from(ErrorKind::Io(err)))?); + Ok(()) + } +} + +impl AsyncImportQueueData { + pub fn new() -> Self { + Self { + signal: Default::default(), + queue: Mutex::new(VecDeque::new()), + queue_blocks: RwLock::new(HashSet::new()), + best_importing_number: RwLock::new(Zero::zero()), + is_stopping: Default::default(), + } + } +} + +impl ImportQueue for AsyncImportQueue { + fn clear(&self) { + let mut queue = self.data.queue.lock(); + let mut queue_blocks = self.data.queue_blocks.write(); + let mut best_importing_number = self.data.best_importing_number.write(); + queue_blocks.clear(); + queue.clear(); + *best_importing_number = Zero::zero(); + } + + fn stop(&self) { + self.clear(); + if let Some(handle) = self.handle.lock().take() { + self.data.is_stopping.store(true, Ordering::SeqCst); + self.data.signal.notify_one(); + + let _ = handle.join(); + } + } + + fn status(&self) -> ImportQueueStatus { + ImportQueueStatus { + importing_count: self.data.queue_blocks.read().len(), + best_importing_number: *self.data.best_importing_number.read(), + } + } + + fn is_importing(&self, hash: &B::Hash) -> bool { + self.data.queue_blocks.read().contains(hash) + } + + fn import_blocks(&self, _sync: &mut ChainSync, _protocol: &mut Context, blocks: (BlockOrigin, Vec>)) { + if blocks.1.is_empty() { + return; + } + + trace!(target:"sync", "Scheduling {} blocks for import", blocks.1.len()); + + let mut queue = self.data.queue.lock(); + let mut queue_blocks = self.data.queue_blocks.write(); + let mut best_importing_number = self.data.best_importing_number.write(); + let new_best_importing_number = blocks.1.last().and_then(|b| b.block.header.as_ref().map(|h| h.number().clone())).unwrap_or_else(|| Zero::zero()); + queue_blocks.extend(blocks.1.iter().map(|b| b.block.hash.clone())); + if new_best_importing_number > *best_importing_number { + *best_importing_number = new_best_importing_number; + } + queue.push_back(blocks); + self.data.signal.notify_one(); + } +} + +impl Drop for AsyncImportQueue { + fn drop(&mut self) { + self.stop(); + } +} + +/// Blocks import thread. +fn import_thread>(sync: Weak>>, service: Weak, chain: Weak>, qdata: Arc>) { + trace!(target: "sync", "Starting import thread"); + loop { + if qdata.is_stopping.load(Ordering::SeqCst) { + break; + } + + let new_blocks = { + let mut queue_lock = qdata.queue.lock(); + if queue_lock.is_empty() { + qdata.signal.wait(&mut queue_lock); + } + + match queue_lock.pop_front() { + Some(new_blocks) => new_blocks, + None => break, + } + }; + + match (sync.upgrade(), service.upgrade(), chain.upgrade()) { + (Some(sync), Some(service), Some(chain)) => { + let blocks_hashes: Vec = new_blocks.1.iter().map(|b| b.block.hash.clone()).collect(); + if !import_many_blocks(&mut SyncLink::Indirect(&sync, &*chain, &*service), Some(&*qdata), new_blocks) { + break; + } + + let mut queue_blocks = qdata.queue_blocks.write(); + for blocks_hash in blocks_hashes { + queue_blocks.remove(&blocks_hash); + } + }, + _ => break, + } + } + + trace!(target: "sync", "Stopping import thread"); +} + +/// ChainSync link trait. +trait SyncLinkApi { + /// Get chain reference. + fn chain(&self) -> &Client; + /// Block imported. + fn block_imported(&mut self, hash: &B::Hash, number: NumberFor); + /// Maintain sync. + fn maintain_sync(&mut self); + /// Disconnect from peer. + fn useless_peer(&mut self, who: NodeIndex, reason: &str); + /// Disconnect from peer and restart sync. + fn note_useless_and_restart_sync(&mut self, who: NodeIndex, reason: &str); + /// Restart sync. + fn restart(&mut self); +} + +/// Link with the ChainSync service. +enum SyncLink<'a, B: 'a + BlockT, E: 'a + ExecuteInContext> { + /// Indirect link (through service). + Indirect(&'a RwLock>, &'a Client, &'a E), + /// Direct references are given. + #[cfg(test)] + Direct(&'a mut ChainSync, &'a mut Context), +} + +/// Block import successful result. +#[derive(Debug, PartialEq)] +enum BlockImportResult { + /// Imported known block. + ImportedKnown(H, N), + /// Imported unknown block. + ImportedUnknown(H, N), +} + +/// Block import error. +#[derive(Debug, PartialEq)] +enum BlockImportError { + /// Disconnect from peer and continue import of next bunch of blocks. + Disconnect(NodeIndex), + /// Disconnect from peer and restart sync. + DisconnectAndRestart(NodeIndex), + /// Restart sync. + Restart, +} + +/// Import a bunch of blocks. +fn import_many_blocks<'a, B: BlockT>( + link: &mut SyncLinkApi, + qdata: Option<&AsyncImportQueueData>, + blocks: (BlockOrigin, Vec>) +) -> bool +{ + let (blocks_origin, blocks) = blocks; + let count = blocks.len(); + let mut imported = 0; + + let blocks_range = match ( + blocks.first().and_then(|b| b.block.header.as_ref().map(|h| h.number())), + blocks.last().and_then(|b| b.block.header.as_ref().map(|h| h.number())), + ) { + (Some(first), Some(last)) if first != last => format!(" ({}..{})", first, last), + (Some(first), Some(_)) => format!(" ({})", first), + _ => Default::default(), + }; + trace!(target:"sync", "Starting import of {} blocks{}", count, blocks_range); + + // Blocks in the response/drain should be in ascending order. + for block in blocks { + let import_result = import_single_block(link.chain(), blocks_origin.clone(), block); + let is_import_failed = import_result.is_err(); + imported += process_import_result(link, import_result); + if is_import_failed { + qdata.map(|qdata| *qdata.best_importing_number.write() = Zero::zero()); + return true; + } + + if qdata.map(|qdata| qdata.is_stopping.load(Ordering::SeqCst)).unwrap_or_default() { + return false; + } + } + + trace!(target: "sync", "Imported {} of {}", imported, count); + link.maintain_sync(); + true +} + +/// Single block import function. +fn import_single_block( + chain: &Client, + block_origin: BlockOrigin, + block: BlockData +) -> Result::Header as HeaderT>::Number>, BlockImportError> +{ + let origin = block.origin; + let block = block.block; + match (block.header, block.justification) { + (Some(header), Some(justification)) => { + let number = header.number().clone(); + let hash = header.hash(); + let parent = header.parent_hash().clone(); + + let result = chain.import( + block_origin, + header, + justification, + block.body, + ); + match result { + Ok(ImportResult::AlreadyInChain) => { + trace!(target: "sync", "Block already in chain {}: {:?}", number, hash); + Ok(BlockImportResult::ImportedKnown(hash, number)) + }, + Ok(ImportResult::AlreadyQueued) => { + trace!(target: "sync", "Block already queued {}: {:?}", number, hash); + Ok(BlockImportResult::ImportedKnown(hash, number)) + }, + Ok(ImportResult::Queued) => { + trace!(target: "sync", "Block queued {}: {:?}", number, hash); + Ok(BlockImportResult::ImportedUnknown(hash, number)) + }, + Ok(ImportResult::UnknownParent) => { + debug!(target: "sync", "Block with unknown parent {}: {:?}, parent: {:?}", number, hash, parent); + Err(BlockImportError::Restart) + }, + Ok(ImportResult::KnownBad) => { + debug!(target: "sync", "Peer gave us a bad block {}: {:?}", number, hash); + Err(BlockImportError::DisconnectAndRestart(origin)) //TODO: use persistent ID + } + Err(e) => { + debug!(target: "sync", "Error importing block {}: {:?}: {:?}", number, hash, e); + Err(BlockImportError::Restart) + } + } + }, + (None, _) => { + debug!(target: "sync", "Header {} was not provided by {} ", block.hash, origin); + Err(BlockImportError::Disconnect(origin)) //TODO: use persistent ID + }, + (_, None) => { + debug!(target: "sync", "Justification set for block {} was not provided by {} ", block.hash, origin); + Err(BlockImportError::Disconnect(origin)) //TODO: use persistent ID + } + } +} + +/// Process single block import result. +fn process_import_result<'a, B: BlockT>( + link: &mut SyncLinkApi, + result: Result::Header as HeaderT>::Number>, BlockImportError> +) -> usize +{ + match result { + Ok(BlockImportResult::ImportedKnown(hash, number)) => { + link.block_imported(&hash, number); + 1 + }, + Ok(BlockImportResult::ImportedUnknown(hash, number)) => { + link.block_imported(&hash, number); + 1 + }, + Err(BlockImportError::Disconnect(who)) => { + // TODO: FIXME: @arkpar BlockImport shouldn't be trying to manage the peer set. + // This should contain an actual reason. + link.useless_peer(who, "Import result was stated Disconnect"); + 0 + }, + Err(BlockImportError::DisconnectAndRestart(who)) => { + // TODO: FIXME: @arkpar BlockImport shouldn't be trying to manage the peer set. + // This should contain an actual reason. + link.note_useless_and_restart_sync(who, "Import result was stated DisconnectAndRestart"); + 0 + }, + Err(BlockImportError::Restart) => { + link.restart(); + 0 + }, + } +} + +impl<'a, B: 'static + BlockT, E: 'a + ExecuteInContext> SyncLink<'a, B, E> { + /// Execute closure with locked ChainSync. + fn with_sync, &mut Context)>(&mut self, closure: F) { + match *self { + #[cfg(test)] + SyncLink::Direct(ref mut sync, ref mut protocol) => + closure(*sync, *protocol), + SyncLink::Indirect(ref sync, _, ref service) => + service.execute_in_context(move |protocol| { + let mut sync = sync.write(); + closure(&mut *sync, protocol) + }), + } + } +} + +impl<'a, B: 'static + BlockT, E: ExecuteInContext> SyncLinkApi for SyncLink<'a, B, E> { + fn chain(&self) -> &Client { + match *self { + #[cfg(test)] + SyncLink::Direct(_, ref protocol) => protocol.client(), + SyncLink::Indirect(_, ref chain, _) => *chain, + } + } + + fn block_imported(&mut self, hash: &B::Hash, number: NumberFor) { + self.with_sync(|sync, _| sync.block_imported(&hash, number)) + } + + fn maintain_sync(&mut self) { + self.with_sync(|sync, protocol| sync.maintain_sync(protocol)) + } + + fn useless_peer(&mut self, who: NodeIndex, reason: &str) { + self.with_sync(|_, protocol| protocol.report_peer(who, Severity::Useless(reason))) + } + + fn note_useless_and_restart_sync(&mut self, who: NodeIndex, reason: &str) { + self.with_sync(|sync, protocol| { + protocol.report_peer(who, Severity::Useless(reason)); // is this actually malign or just useless? + sync.restart(protocol); + }) + } + + fn restart(&mut self) { + self.with_sync(|sync, protocol| sync.restart(protocol)) + } +} + +#[cfg(test)] +pub mod tests { + use client; + use message; + use test_client::{self, TestClient}; + use test_client::runtime::{Block, Hash}; + use on_demand::tests::DummyExecutor; + use runtime_primitives::generic::BlockId; + use super::*; + + /// Blocks import queue that is importing blocks in the same thread. + pub struct SyncImportQueue; + struct DummyExecuteInContext; + + impl ExecuteInContext for DummyExecuteInContext { + fn execute_in_context)>(&self, _closure: F) { } + } + + impl ImportQueue for SyncImportQueue { + fn clear(&self) { } + + fn stop(&self) { } + + fn status(&self) -> ImportQueueStatus { + ImportQueueStatus { + importing_count: 0, + best_importing_number: Zero::zero(), + } + } + + fn is_importing(&self, _hash: &B::Hash) -> bool { + false + } + + fn import_blocks(&self, sync: &mut ChainSync, protocol: &mut Context, blocks: (BlockOrigin, Vec>)) { + import_many_blocks(&mut SyncLink::Direct::<_, DummyExecuteInContext>(sync, protocol), None, blocks); + } + } + + struct TestLink { + chain: Arc>, + imported: usize, + maintains: usize, + disconnects: usize, + restarts: usize, + } + + impl TestLink { + fn new() -> TestLink { + TestLink { + chain: Arc::new(test_client::new()), + imported: 0, + maintains: 0, + disconnects: 0, + restarts: 0, + } + } + + fn total(&self) -> usize { + self.imported + self.maintains + self.disconnects + self.restarts + } + } + + impl SyncLinkApi for TestLink { + fn chain(&self) -> &Client { &*self.chain } + fn block_imported(&mut self, _hash: &Hash, _number: NumberFor) { self.imported += 1; } + fn maintain_sync(&mut self) { self.maintains += 1; } + fn useless_peer(&mut self, _: NodeIndex, _: &str) { self.disconnects += 1; } + fn note_useless_and_restart_sync(&mut self, _: NodeIndex, _: &str) { self.disconnects += 1; self.restarts += 1; } + fn restart(&mut self) { self.restarts += 1; } + } + + fn prepare_good_block() -> (client::Client, Hash, u64, BlockData) { + let client = test_client::new(); + let block = client.new_block().unwrap().bake().unwrap(); + client.justify_and_import(BlockOrigin::File, block).unwrap(); + + let (hash, number) = (client.block_hash(1).unwrap().unwrap(), 1); + let block = message::BlockData:: { + hash: client.block_hash(1).unwrap().unwrap(), + header: client.header(&BlockId::Number(1)).unwrap(), + body: None, + receipt: None, + message_queue: None, + justification: client.justification(&BlockId::Number(1)).unwrap(), + }; + + (client, hash, number, BlockData { block, origin: 0 }) + } + + #[test] + fn import_single_good_block_works() { + let (_, hash, number, block) = prepare_good_block(); + assert_eq!(import_single_block(&test_client::new(), BlockOrigin::File, block), Ok(BlockImportResult::ImportedUnknown(hash, number))); + } + + #[test] + fn import_single_good_known_block_is_ignored() { + let (client, hash, number, block) = prepare_good_block(); + assert_eq!(import_single_block(&client, BlockOrigin::File, block), Ok(BlockImportResult::ImportedKnown(hash, number))); + } + + #[test] + fn import_single_good_block_without_header_fails() { + let (_, _, _, mut block) = prepare_good_block(); + block.block.header = None; + assert_eq!(import_single_block(&test_client::new(), BlockOrigin::File, block), Err(BlockImportError::Disconnect(0))); + } + + #[test] + fn import_single_good_block_without_justification_fails() { + let (_, _, _, mut block) = prepare_good_block(); + block.block.justification = None; + assert_eq!(import_single_block(&test_client::new(), BlockOrigin::File, block), Err(BlockImportError::Disconnect(0))); + } + + #[test] + fn process_import_result_works() { + let mut link = TestLink::new(); + assert_eq!(process_import_result::(&mut link, Ok(BlockImportResult::ImportedKnown(Default::default(), 0))), 1); + assert_eq!(link.total(), 1); + + let mut link = TestLink::new(); + assert_eq!(process_import_result::(&mut link, Ok(BlockImportResult::ImportedKnown(Default::default(), 0))), 1); + assert_eq!(link.total(), 1); + assert_eq!(link.imported, 1); + + let mut link = TestLink::new(); + assert_eq!(process_import_result::(&mut link, Ok(BlockImportResult::ImportedUnknown(Default::default(), 0))), 1); + assert_eq!(link.total(), 1); + assert_eq!(link.imported, 1); + + let mut link = TestLink::new(); + assert_eq!(process_import_result::(&mut link, Err(BlockImportError::Disconnect(0))), 0); + assert_eq!(link.total(), 1); + assert_eq!(link.disconnects, 1); + + let mut link = TestLink::new(); + assert_eq!(process_import_result::(&mut link, Err(BlockImportError::DisconnectAndRestart(0))), 0); + assert_eq!(link.total(), 2); + assert_eq!(link.disconnects, 1); + assert_eq!(link.restarts, 1); + + let mut link = TestLink::new(); + assert_eq!(process_import_result::(&mut link, Err(BlockImportError::Restart)), 0); + assert_eq!(link.total(), 1); + assert_eq!(link.restarts, 1); + } + + #[test] + fn import_many_blocks_stops_when_stopping() { + let (_, _, _, block) = prepare_good_block(); + let qdata = AsyncImportQueueData::new(); + qdata.is_stopping.store(true, Ordering::SeqCst); + assert!(!import_many_blocks(&mut TestLink::new(), Some(&qdata), (BlockOrigin::File, vec![block.clone(), block]))); + } + + #[test] + fn async_import_queue_drops() { + let queue = AsyncImportQueue::new(); + let service = Arc::new(DummyExecutor); + let chain = Arc::new(test_client::new()); + queue.start(Weak::new(), Arc::downgrade(&service), Arc::downgrade(&chain) as Weak>).unwrap(); + drop(queue); + } +} diff --git a/substrate/network/src/io.rs b/substrate/network/src/io.rs index 2a67888b657af..2ea5e4ffaf64d 100644 --- a/substrate/network/src/io.rs +++ b/substrate/network/src/io.rs @@ -14,23 +14,21 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see .? -use network::{NetworkContext, PeerId, Error as NetworkError, SessionInfo}; +use network_libp2p::{NetworkContext, Severity, NodeIndex, SessionInfo}; /// IO interface for the syncing handler. /// Provides peer connection management and an interface to the blockchain client. pub trait SyncIo { - /// Disable a peer - fn disable_peer(&mut self, peer_id: PeerId); - /// Disconnect peer - fn disconnect_peer(&mut self, peer_id: PeerId); + /// Report a peer for misbehaviour. + fn report_peer(&mut self, who: NodeIndex, reason: Severity); /// Send a packet to a peer. - fn send(&mut self, peer_id: PeerId, data: Vec) -> Result<(), NetworkError>; + fn send(&mut self, who: NodeIndex, data: Vec); /// Returns peer identifier string - fn peer_info(&self, peer_id: PeerId) -> String { - peer_id.to_string() + fn peer_info(&self, who: NodeIndex) -> String { + who.to_string() } /// Returns information on p2p session - fn peer_session_info(&self, peer_id: PeerId) -> Option; + fn peer_session_info(&self, who: NodeIndex) -> Option; /// Check if the session is expired fn is_expired(&self) -> bool; } @@ -50,28 +48,24 @@ impl<'s> NetSyncIo<'s> { } impl<'s> SyncIo for NetSyncIo<'s> { - fn disable_peer(&mut self, peer_id: PeerId) { - self.network.disable_peer(peer_id); + fn report_peer(&mut self, who: NodeIndex, reason: Severity) { + self.network.report_peer(who, reason); } - fn disconnect_peer(&mut self, peer_id: PeerId) { - self.network.disconnect_peer(peer_id); + fn send(&mut self, who: NodeIndex, data: Vec) { + self.network.send(who, 0, data) } - fn send(&mut self, peer_id: PeerId, data: Vec) -> Result<(), NetworkError>{ - self.network.send(peer_id, 0, data) - } - - fn peer_session_info(&self, peer_id: PeerId) -> Option { - self.network.session_info(peer_id) + fn peer_session_info(&self, who: NodeIndex) -> Option { + self.network.session_info(who) } fn is_expired(&self) -> bool { self.network.is_expired() } - fn peer_info(&self, peer_id: PeerId) -> String { - self.network.peer_client_version(peer_id) + fn peer_info(&self, who: NodeIndex) -> String { + self.network.peer_client_version(who) } } diff --git a/substrate/network/src/lib.rs b/substrate/network/src/lib.rs index 15779ea6522cd..8d5f2bc5ffd49 100644 --- a/substrate/network/src/lib.rs +++ b/substrate/network/src/lib.rs @@ -14,30 +14,23 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see .? +#![warn(unused_extern_crates)] #![warn(missing_docs)] -//! Implements polkadot protocol version as specified here: -//! https://github.com/paritytech/polkadot/wiki/Network-protocol +//! Substrate-specific P2P networking: synchronizing blocks, propagating BFT messages. +//! Allows attachment of an optional subprotocol for chain-specific requests. -extern crate ethcore_network_devp2p as network_devp2p; -extern crate ethcore_network as network; extern crate ethcore_io as core_io; extern crate linked_hash_map; -extern crate rand; extern crate parking_lot; extern crate substrate_primitives as primitives; -extern crate substrate_state_machine as state_machine; -extern crate substrate_serializer as ser; extern crate substrate_client as client; -extern crate substrate_runtime_support as runtime_support; extern crate substrate_runtime_primitives as runtime_primitives; -extern crate substrate_bft; +extern crate substrate_network_libp2p as network_libp2p; extern crate substrate_codec as codec; -extern crate serde; -extern crate serde_json; extern crate futures; extern crate ed25519; -#[macro_use] extern crate serde_derive; +extern crate rustc_hex; #[macro_use] extern crate log; #[macro_use] extern crate bitflags; #[macro_use] extern crate error_chain; @@ -50,22 +43,25 @@ mod service; mod sync; mod protocol; mod io; -mod message; mod config; mod chain; mod blocks; -mod consensus; mod on_demand; +mod import_queue; +pub mod consensus_gossip; pub mod error; +pub mod message; +pub mod specialization; #[cfg(test)] mod test; +pub use chain::Client as ClientHandle; pub use service::{Service, FetchFuture, ConsensusService, BftMessageStream, TransactionPool, Params, ManageNetwork, SyncProvider}; -pub use protocol::{ProtocolStatus}; +pub use protocol::{ProtocolStatus, PeerInfo, Context}; pub use sync::{Status as SyncStatus, SyncState}; -pub use network::{NonReservedPeerMode, NetworkConfiguration, ConnectionFilter, ConnectionDirection}; -pub use message::{generic as generic_message, BftMessage, LocalizedBftMessage, ConsensusVote, SignedConsensusVote, SignedConsensusMessage, SignedConsensusProposal}; +pub use network_libp2p::{NonReservedPeerMode, NetworkConfiguration, NodeIndex, ProtocolId, ConnectionFilter, ConnectionDirection, Severity}; +pub use message::{generic as generic_message, RequestId, BftMessage, LocalizedBftMessage, ConsensusVote, SignedConsensusVote, SignedConsensusMessage, SignedConsensusProposal, Status as StatusMessage}; pub use error::Error; -pub use config::{Role, ProtocolConfig}; -pub use on_demand::{OnDemand, OnDemandService, Response as OnDemandResponse}; +pub use config::{Roles, ProtocolConfig}; +pub use on_demand::{OnDemand, OnDemandService, RemoteResponse}; diff --git a/substrate/network/src/message.rs b/substrate/network/src/message.rs index b2c44cdf96e8f..d2bbcdf3e7581 100644 --- a/substrate/network/src/message.rs +++ b/substrate/network/src/message.rs @@ -1,26 +1,29 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. +// This file is part of Substrate. -// Polkadot is free software: you can redistribute it and/or modify +// Substrate 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. -// Polkadot is distributed in the hope that it will be useful, +// Substrate 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 Polkadot. If not, see .? +// along with Substrate. If not, see . //! Network packet message types. These get serialized and put into the lower level protocol payload. use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; -use service::Role as RoleFlags; - -pub use self::generic::{BlockAnnounce, RemoteCallRequest, ConsensusVote, SignedConsensusVote, FromBlock, Body}; +use codec::{Encode, Decode, Input, Output}; +pub use self::generic::{ + BlockAnnounce, RemoteCallRequest, RemoteReadRequest, + ConsensusVote, SignedConsensusVote, FromBlock +}; +/// A unique ID of a request. pub type RequestId = u64; /// Type alias for using the message type using block type parameters. @@ -85,80 +88,34 @@ pub type SignedConsensusMessage = generic::SignedConsensusProposal< /// A set of transactions. pub type Transactions = Vec; -/// Configured node role. -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -pub enum Role { - /// Full relay chain client with no additional responsibilities. - Full, - /// Relay chain light client. - Light, - /// Parachain validator. - Validator, - /// Parachain collator. - Collator, -} - -impl Role { - /// Convert enum to service flags. - pub fn as_flags(roles: &[Role]) -> RoleFlags { - let mut flags = RoleFlags::NONE; - for r in roles { - match *r { - Role::Full => flags = flags | RoleFlags::FULL, - Role::Light => flags = flags | RoleFlags::LIGHT, - Role::Validator => flags = flags | RoleFlags::VALIDATOR, - Role::Collator => flags = flags | RoleFlags::COLLATOR, - } - } - flags - } -} - -impl From for Vec where { - fn from(flags: RoleFlags) -> Vec { - let mut roles = Vec::new(); - if !(flags & RoleFlags::FULL).is_empty() { - roles.push(Role::Full); - } - if !(flags & RoleFlags::LIGHT).is_empty() { - roles.push(Role::Light); - } - if !(flags & RoleFlags::VALIDATOR).is_empty() { - roles.push(Role::Validator); - } - if !(flags & RoleFlags::COLLATOR).is_empty() { - roles.push(Role::Collator); - } - roles - } -} - /// Bits of block data and associated artefacts to request. -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Copy, Clone)] -pub enum BlockAttribute { - /// Include block header. - Header, - /// Include block body. - Body, - /// Include block receipt. - Receipt, - /// Include block message queue. - MessageQueue, - /// Include a justification for the block. - Justification, +bitflags! { + /// Node roles bitmask. + pub struct BlockAttributes: u8 { + /// Include block header. + const HEADER = 0b00000001; + /// Include block body. + const BODY = 0b00000010; + /// Include block receipt. + const RECEIPT = 0b00000100; + /// Include block message queue. + const MESSAGE_QUEUE = 0b00001000; + /// Include a justification for the block. + const JUSTIFICATION = 0b00010000; + } } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] /// Block enumeration direction. pub enum Direction { /// Enumerate in ascending order (from child to parent). - Ascending, + Ascending = 0, /// Enumerate in descendfing order (from parent to canonical child). - Descending, + Descending = 1, } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] /// Remote call response. +#[derive(Debug, PartialEq, Eq, Clone)] pub struct RemoteCallResponse { /// Id of a request this response was made for. pub id: RequestId, @@ -166,56 +123,68 @@ pub struct RemoteCallResponse { pub proof: Vec>, } +impl Encode for RemoteCallResponse { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.id); + dest.push(&self.proof); + } +} + +impl Decode for RemoteCallResponse { + fn decode(input: &mut I) -> Option { + Some(RemoteCallResponse { + id: Decode::decode(input)?, + proof: Decode::decode(input)?, + }) + } +} + +#[derive(Debug, PartialEq, Eq, Clone)] +/// Remote read response. +pub struct RemoteReadResponse { + /// Id of a request this response was made for. + pub id: RequestId, + /// Read proof. + pub proof: Vec>, +} + +impl Encode for RemoteReadResponse { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.id); + dest.push(&self.proof); + } +} + +impl Decode for RemoteReadResponse { + fn decode(input: &mut I) -> Option { + Some(RemoteReadResponse { + id: Decode::decode(input)?, + proof: Decode::decode(input)?, + }) + } +} + /// Generic types. pub mod generic { use primitives::AuthorityId; - use codec::Slicable; + use codec::{Decode, Encode, Input, Output}; use runtime_primitives::bft::Justification; use ed25519; - - use super::{Role, BlockAttribute, RemoteCallResponse, RequestId, Transactions, Direction}; - - use primitives::bytes; - - /// Emulates Poc-1 extrinsic primitive. - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] - pub struct V1Extrinsic(#[serde(with="bytes")] pub Vec); - // Alternative block format for poc-1 compatibility. - // TODO: remove this after poc-2 - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] - #[serde(untagged)] - /// Serialized block body type. - pub enum Body { - /// Poc-1. Extrinsics as bytes. - V1(Vec), - /// Poc-2 or later. A structured type. - Extrinsics(Vec), - } - - impl Body where Extrinsic: Slicable { - /// Extracts extrinsic from the body. - pub fn to_extrinsics(self) -> Vec { - match self { - Body::Extrinsics(e) => e, - Body::V1(e) => { - e.into_iter().filter_map(|bytes| { - let bytes = bytes.0.encode(); - Slicable::decode(&mut bytes.as_slice()) - }).collect() - } - } - } - } + use service::Roles; + use super::{ + BlockAttributes, RemoteCallResponse, RemoteReadResponse, + RequestId, Transactions, Direction + }; /// Block data sent in the response. - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] + #[derive(Debug, PartialEq, Eq, Clone)] pub struct BlockData { /// Block header hash. pub hash: Hash, /// Block header if requested. pub header: Option

, /// Block body if requested. - pub body: Option>, + pub body: Option>, /// Block receipt if requested. pub receipt: Option>, /// Block message queue if requested. @@ -224,9 +193,32 @@ pub mod generic { pub justification: Option>, } + impl Encode for BlockData { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.hash); + dest.push(&self.header); + dest.push(&self.body); + dest.push(&self.receipt); + dest.push(&self.message_queue); + dest.push(&self.justification); + } + } + + impl Decode for BlockData { + fn decode(input: &mut I) -> Option { + Some(BlockData { + hash: Decode::decode(input)?, + header: Decode::decode(input)?, + body: Decode::decode(input)?, + receipt: Decode::decode(input)?, + message_queue: Decode::decode(input)?, + justification: Decode::decode(input)?, + }) + } + } + /// Identifies starting point of a block sequence. - #[serde(untagged)] - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] + #[derive(Debug, PartialEq, Eq, Clone)] pub enum FromBlock { /// Start with given hash. Hash(Hash), @@ -234,8 +226,33 @@ pub mod generic { Number(Number), } + impl Encode for FromBlock { + fn encode_to(&self, dest: &mut T) { + match *self { + FromBlock::Hash(ref h) => { + dest.push_byte(0); + dest.push(h); + } + FromBlock::Number(ref n) => { + dest.push_byte(1); + dest.push(n); + } + } + } + } + + impl Decode for FromBlock { + fn decode(input: &mut I) -> Option { + match input.read_byte()? { + 0 => Some(FromBlock::Hash(Decode::decode(input)?)), + 1 => Some(FromBlock::Number(Decode::decode(input)?)), + _ => None, + } + } + } + /// Communication that can occur between participants in consensus. - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] + #[derive(Debug, PartialEq, Eq, Clone)] pub enum BftMessage { /// A consensus message (proposal or vote) Consensus(SignedConsensusMessage), @@ -243,8 +260,33 @@ pub mod generic { Auxiliary(Justification), } + impl Encode for BftMessage { + fn encode_to(&self, dest: &mut T) { + match *self { + BftMessage::Consensus(ref h) => { + dest.push_byte(0); + dest.push(h); + } + BftMessage::Auxiliary(ref n) => { + dest.push_byte(1); + dest.push(n); + } + } + } + } + + impl Decode for BftMessage { + fn decode(input: &mut I) -> Option { + match input.read_byte()? { + 0 => Some(BftMessage::Consensus(Decode::decode(input)?)), + 1 => Some(BftMessage::Auxiliary(Decode::decode(input)?)), + _ => None, + } + } + } + /// BFT Consensus message with parent header hash attached to it. - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] + #[derive(Debug, PartialEq, Eq, Clone)] pub struct LocalizedBftMessage { /// Consensus message. pub message: BftMessage, @@ -252,8 +294,24 @@ pub mod generic { pub parent_hash: Hash, } + impl Encode for LocalizedBftMessage { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.message); + dest.push(&self.parent_hash); + } + } + + impl Decode for LocalizedBftMessage { + fn decode(input: &mut I) -> Option { + Some(LocalizedBftMessage { + message: Decode::decode(input)?, + parent_hash: Decode::decode(input)?, + }) + } + } + /// A localized proposal message. Contains two signed pieces of data. - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] + #[derive(Debug, PartialEq, Eq, Clone)] pub struct SignedConsensusProposal { /// The round number. pub round_number: u32, @@ -269,8 +327,32 @@ pub mod generic { pub full_signature: ed25519::Signature, } + impl Encode for SignedConsensusProposal { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.round_number); + dest.push(&self.proposal); + dest.push(&self.digest); + dest.push(&self.sender); + dest.push(&self.digest_signature); + dest.push(&self.full_signature); + } + } + + impl Decode for SignedConsensusProposal { + fn decode(input: &mut I) -> Option { + Some(SignedConsensusProposal { + round_number: Decode::decode(input)?, + proposal: Decode::decode(input)?, + digest: Decode::decode(input)?, + sender: Decode::decode(input)?, + digest_signature: Decode::decode(input)?, + full_signature: Decode::decode(input)?, + }) + } + } + /// A localized vote message, including the sender. - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] + #[derive(Debug, PartialEq, Eq, Clone)] pub struct SignedConsensusVote { /// The message sent. pub vote: ConsensusVote, @@ -280,8 +362,26 @@ pub mod generic { pub signature: ed25519::Signature, } + impl Encode for SignedConsensusVote { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.vote); + dest.push(&self.sender); + dest.push(&self.signature); + } + } + + impl Decode for SignedConsensusVote { + fn decode(input: &mut I) -> Option { + Some(SignedConsensusVote { + vote: Decode::decode(input)?, + sender: Decode::decode(input)?, + signature: Decode::decode(input)?, + }) + } + } + /// Votes during a consensus round. - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] + #[derive(Debug, PartialEq, Eq, Clone)] pub enum ConsensusVote { /// Prepare to vote for proposal with digest D. Prepare(u32, H), @@ -291,8 +391,40 @@ pub mod generic { AdvanceRound(u32), } + impl Encode for ConsensusVote { + fn encode_to(&self, dest: &mut T) { + match *self { + ConsensusVote::Prepare(ref r, ref h) => { + dest.push_byte(0); + dest.push(r); + dest.push(h); + } + ConsensusVote::Commit(ref r, ref h) => { + dest.push_byte(1); + dest.push(r); + dest.push(h); + } + ConsensusVote::AdvanceRound(ref r) => { + dest.push_byte(2); + dest.push(r); + } + } + } + } + + impl Decode for ConsensusVote { + fn decode(input: &mut I) -> Option { + match input.read_byte()? { + 0 => Some(ConsensusVote::Prepare(Decode::decode(input)?, Decode::decode(input)?)), + 1 => Some(ConsensusVote::Commit(Decode::decode(input)?, Decode::decode(input)?)), + 2 => Some(ConsensusVote::AdvanceRound(Decode::decode(input)?)), + _ => None, + } + } + } + /// A localized message. - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] + #[derive(Debug, PartialEq, Eq, Clone)] pub enum SignedConsensusMessage { /// A proposal. Propose(SignedConsensusProposal), @@ -300,8 +432,33 @@ pub mod generic { Vote(SignedConsensusVote), } + impl Encode for SignedConsensusMessage { + fn encode_to(&self, dest: &mut T) { + match *self { + SignedConsensusMessage::Propose(ref m) => { + dest.push_byte(0); + dest.push(m); + } + SignedConsensusMessage::Vote(ref m) => { + dest.push_byte(1); + dest.push(m); + } + } + } + } + + impl Decode for SignedConsensusMessage { + fn decode(input: &mut I) -> Option { + match input.read_byte()? { + 0 => Some(SignedConsensusMessage::Propose(Decode::decode(input)?)), + 1 => Some(SignedConsensusMessage::Vote(Decode::decode(input)?)), + _ => None, + } + } + } + /// A network message. - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] + #[derive(Debug, PartialEq, Eq, Clone)] pub enum Message { /// Status packet. Status(Status), @@ -319,36 +476,136 @@ pub mod generic { RemoteCallRequest(RemoteCallRequest), /// Remote method call response. RemoteCallResponse(RemoteCallResponse), + /// Remote storage read request. + RemoteReadRequest(RemoteReadRequest), + /// Remote storage read response. + RemoteReadResponse(RemoteReadResponse), + /// Chain-specific message + ChainSpecific(Vec), + } + + impl Encode + for Message + { + fn encode_to(&self, dest: &mut T) { + match *self { + Message::Status(ref m) => { + dest.push_byte(0); + dest.push(m); + } + Message::BlockRequest(ref m) => { + dest.push_byte(1); + dest.push(m); + } + Message::BlockResponse(ref m) => { + dest.push_byte(2); + dest.push(m); + } + Message::BlockAnnounce(ref m) => { + dest.push_byte(3); + dest.push(m); + } + Message::Transactions(ref m) => { + dest.push_byte(4); + dest.push(m); + } + Message::BftMessage(ref m) => { + dest.push_byte(5); + dest.push(m); + } + Message::RemoteCallRequest(ref m) => { + dest.push_byte(6); + dest.push(m); + } + Message::RemoteCallResponse(ref m) => { + dest.push_byte(7); + dest.push(m); + } + Message::RemoteReadRequest(ref m) => { + dest.push_byte(8); + dest.push(m); + } + Message::RemoteReadResponse(ref m) => { + dest.push_byte(9); + dest.push(m); + } + Message::ChainSpecific(ref m) => { + dest.push_byte(255); + dest.push(m); + } + } + } + } + + impl Decode + for Message + { + fn decode(input: &mut I) -> Option { + match input.read_byte()? { + 0 => Some(Message::Status(Decode::decode(input)?)), + 1 => Some(Message::BlockRequest(Decode::decode(input)?)), + 2 => Some(Message::BlockResponse(Decode::decode(input)?)), + 3 => Some(Message::BlockAnnounce(Decode::decode(input)?)), + 4 => Some(Message::Transactions(Decode::decode(input)?)), + 5 => Some(Message::BftMessage(Decode::decode(input)?)), + 6 => Some(Message::RemoteCallRequest(Decode::decode(input)?)), + 7 => Some(Message::RemoteCallResponse(Decode::decode(input)?)), + 8 => Some(Message::RemoteReadRequest(Decode::decode(input)?)), + 9 => Some(Message::RemoteReadResponse(Decode::decode(input)?)), + 255 => Some(Message::ChainSpecific(Decode::decode(input)?)), + _ => None, + } + } } /// Status sent on connection. - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] + #[derive(Debug, PartialEq, Eq, Clone)] pub struct Status { /// Protocol version. pub version: u32, /// Supported roles. - pub roles: Vec, + pub roles: Roles, /// Best block number. pub best_number: Number, /// Best block hash. pub best_hash: Hash, /// Genesis block hash. pub genesis_hash: Hash, - /// Signatue of `best_hash` made with validator address. Required for the validator role. - pub validator_signature: Option, - /// Validator address. Required for the validator role. - pub validator_id: Option, - /// Parachain id. Required for the collator role. - pub parachain_id: Option, + /// Chain-specific status. + pub chain_status: Vec, + } + + impl Encode for Status { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.version); + dest.push_byte(self.roles.bits()); + dest.push(&self.best_number); + dest.push(&self.best_hash); + dest.push(&self.genesis_hash); + dest.push(&self.chain_status); + } } + impl Decode for Status { + fn decode(input: &mut I) -> Option { + Some(Status { + version: Decode::decode(input)?, + roles: Roles::from_bits(input.read_byte()?)?, + best_number: Decode::decode(input)?, + best_hash: Decode::decode(input)?, + genesis_hash: Decode::decode(input)?, + chain_status: Decode::decode(input)?, + }) + } + } + /// Request block data from a peer. - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] + #[derive(Debug, PartialEq, Eq, Clone)] pub struct BlockRequest { /// Unique request id. pub id: RequestId, /// Bits of block data to request. - pub fields: Vec, + pub fields: BlockAttributes, /// Start from this block. pub from: FromBlock, /// End at this block. An implementation defined maximum is used when unspecified. @@ -359,8 +616,36 @@ pub mod generic { pub max: Option, } + impl Encode for BlockRequest { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.id); + dest.push_byte(self.fields.bits()); + dest.push(&self.from); + dest.push(&self.to); + dest.push_byte(self.direction as u8); + dest.push(&self.max); + } + } + + impl Decode for BlockRequest { + fn decode(input: &mut I) -> Option { + Some(BlockRequest { + id: Decode::decode(input)?, + fields: BlockAttributes::from_bits(input.read_byte()?)?, + from: Decode::decode(input)?, + to: Decode::decode(input)?, + direction: match input.read_byte()? { + x if x == Direction::Ascending as u8 => Some(Direction::Ascending), + x if x == Direction::Descending as u8 => Some(Direction::Descending), + _ => None, + }?, + max: Decode::decode(input)?, + }) + } + } + /// Response to `BlockRequest` - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] + #[derive(Debug, PartialEq, Eq, Clone)] pub struct BlockResponse { /// Id of a request this response was made for. pub id: RequestId, @@ -368,14 +653,44 @@ pub mod generic { pub blocks: Vec>, } + impl Encode for BlockResponse { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.id); + dest.push(&self.blocks) + } + } + + impl Decode for BlockResponse { + fn decode(input: &mut I) -> Option { + Some(BlockResponse { + id: Decode::decode(input)?, + blocks: Decode::decode(input)?, + }) + } + } + /// Announce a new complete relay chain block on the network. - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] + #[derive(Debug, PartialEq, Eq, Clone)] pub struct BlockAnnounce { /// New block header. pub header: H, } - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] + impl Encode for BlockAnnounce
{ + fn encode_to(&self, dest: &mut T) { + dest.push(&self.header); + } + } + + impl Decode for BlockAnnounce
{ + fn decode(input: &mut I) -> Option { + Some(BlockAnnounce { + header: Decode::decode(input)?, + }) + } + } + + #[derive(Debug, PartialEq, Eq, Clone)] /// Remote call request. pub struct RemoteCallRequest { /// Unique request id. @@ -387,4 +702,53 @@ pub mod generic { /// Call data. pub data: Vec, } + + impl Encode for RemoteCallRequest { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.id); + dest.push(&self.block); + dest.push(self.method.as_bytes()); + dest.push(&self.data); + } + } + + impl Decode for RemoteCallRequest { + fn decode(input: &mut I) -> Option { + Some(RemoteCallRequest { + id: Decode::decode(input)?, + block: Decode::decode(input)?, + method: String::from_utf8_lossy(&Vec::decode(input)?).into(), + data: Decode::decode(input)?, + }) + } + } + + #[derive(Debug, PartialEq, Eq, Clone)] + /// Remote storage read request. + pub struct RemoteReadRequest { + /// Unique request id. + pub id: RequestId, + /// Block at which to perform call. + pub block: H, + /// Storage key. + pub key: Vec, + } + + impl Encode for RemoteReadRequest { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.id); + dest.push(&self.block); + dest.push(&self.key); + } + } + + impl Decode for RemoteReadRequest { + fn decode(input: &mut I) -> Option { + Some(RemoteReadRequest { + id: Decode::decode(input)?, + block: Decode::decode(input)?, + key: Decode::decode(input)?, + }) + } + } } diff --git a/substrate/network/src/on_demand.rs b/substrate/network/src/on_demand.rs index 67c5adf923da0..069cd84c5c658 100644 --- a/substrate/network/src/on_demand.rs +++ b/substrate/network/src/on_demand.rs @@ -19,16 +19,16 @@ use std::collections::VecDeque; use std::sync::{Arc, Weak}; use std::time::{Instant, Duration}; -use futures::{Future, Poll}; +use futures::{Async, Future, Poll}; use futures::sync::oneshot::{channel, Receiver, Sender}; use linked_hash_map::LinkedHashMap; use linked_hash_map::Entry; use parking_lot::Mutex; use client; -use client::light::{Fetcher, FetchChecker, RemoteCallRequest}; +use client::light::fetcher::{Fetcher, FetchChecker, RemoteCallRequest, RemoteReadRequest}; use io::SyncIo; use message; -use network::PeerId; +use network_libp2p::{Severity, NodeIndex}; use service; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; @@ -36,18 +36,21 @@ use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; const REQUEST_TIMEOUT: Duration = Duration::from_secs(15); /// On-demand service API. -pub trait OnDemandService: Send + Sync { +pub trait OnDemandService: Send + Sync { /// When new node is connected. - fn on_connect(&self, peer: PeerId, role: service::Role); + fn on_connect(&self, peer: NodeIndex, role: service::Roles); /// When node is disconnected. - fn on_disconnect(&self, peer: PeerId); + fn on_disconnect(&self, peer: NodeIndex); /// Maintain peers requests. fn maintain_peers(&self, io: &mut SyncIo); - /// When response is received from remote node. - fn on_remote_response(&self, io: &mut SyncIo, peer: PeerId, response: message::RemoteCallResponse); + /// When read response is received from remote node. + fn on_remote_read_response(&self, io: &mut SyncIo, peer: NodeIndex, response: message::RemoteReadResponse); + + /// When call response is received from remote node. + fn on_remote_call_response(&self, io: &mut SyncIo, peer: NodeIndex, response: message::RemoteCallResponse); } /// On-demand requests service. Dispatches requests to appropriate peers. @@ -56,40 +59,55 @@ pub struct OnDemand> { checker: Arc>, } -/// On-demand response. -pub struct Response { - receiver: Receiver, +/// On-demand remote call response. +pub struct RemoteResponse { + receiver: Receiver>, } #[derive(Default)] struct OnDemandCore> { service: Weak, next_request_id: u64, - pending_requests: VecDeque>, - active_peers: LinkedHashMap>, - idle_peers: VecDeque, + pending_requests: VecDeque>, + active_peers: LinkedHashMap>, + idle_peers: VecDeque, } -struct Request { +struct Request { id: u64, timestamp: Instant, - sender: Sender, - request: RemoteCallRequest, + data: RequestData, +} + +enum RequestData { + RemoteRead(RemoteReadRequest, Sender>, client::error::Error>>), + RemoteCall(RemoteCallRequest, Sender>), } -impl Future for Response { - type Item = client::CallResult; +enum Accept { + Ok, + CheckFailed(client::error::Error, RequestData), + Unexpected(RequestData), +} + +impl Future for RemoteResponse { + type Item = T; type Error = client::error::Error; fn poll(&mut self) -> Poll { self.receiver.poll() .map_err(|_| client::error::ErrorKind::RemoteFetchCancelled.into()) + .and_then(|r| match r { + Async::Ready(Ok(ready)) => Ok(Async::Ready(ready)), + Async::Ready(Err(error)) => Err(error), + Async::NotReady => Ok(Async::NotReady), + }) } } impl OnDemand where E: service::ExecuteInContext, - B::Header: HeaderT, + B::Header: HeaderT, { /// Creates new on-demand service. pub fn new(checker: Arc>) -> Self { @@ -110,30 +128,54 @@ impl OnDemand where self.core.lock().service = service; } - /// Execute method call on remote node, returning execution result and proof. - pub fn remote_call(&self, request: RemoteCallRequest) -> Response { - let (sender, receiver) = channel(); - let result = Response { - receiver: receiver, + /// Schedule && dispatch all scheduled requests. + fn schedule_request(&self, data: RequestData, result: R) -> R { + let mut core = self.core.lock(); + core.insert(data); + core.dispatch(); + result + } + + /// Try to accept response from given peer. + fn accept_response) -> Accept>(&self, rtype: &str, io: &mut SyncIo, peer: NodeIndex, request_id: u64, try_accept: F) { + let mut core = self.core.lock(); + let request = match core.remove(peer, request_id) { + Some(request) => request, + None => { + io.report_peer(peer, Severity::Bad(&format!("Invalid remote {} response from peer", rtype))); + core.remove_peer(peer); + return; + }, + }; + + let retry_request_data = match try_accept(request) { + Accept::Ok => None, + Accept::CheckFailed(error, retry_request_data) => { + io.report_peer(peer, Severity::Bad(&format!("Failed to check remote {} response from peer: {}", rtype, error))); + core.remove_peer(peer); + Some(retry_request_data) + }, + Accept::Unexpected(retry_request_data) => { + trace!(target: "sync", "Unexpected response to remote {} from peer {}", rtype, peer); + Some(retry_request_data) + }, }; - { - let mut core = self.core.lock(); - core.insert(sender, request); - core.dispatch(); + if let Some(request_data) = retry_request_data { + core.insert(request_data); } - result + core.dispatch(); } } -impl OnDemandService for OnDemand where +impl OnDemandService for OnDemand where B: BlockT, E: service::ExecuteInContext, - B::Header: HeaderT, + B::Header: HeaderT, { - fn on_connect(&self, peer: PeerId, role: service::Role) { - if !role.intersects(service::Role::FULL | service::Role::COLLATOR | service::Role::VALIDATOR) { // TODO: correct? + fn on_connect(&self, peer: NodeIndex, role: service::Roles) { + if !role.intersects(service::Roles::FULL | service::Roles::AUTHORITY) { // TODO: correct? return; } @@ -142,7 +184,7 @@ impl OnDemandService for OnDemand where core.dispatch(); } - fn on_disconnect(&self, peer: PeerId) { + fn on_disconnect(&self, peer: NodeIndex) { let mut core = self.core.lock(); core.remove_peer(peer); core.dispatch(); @@ -151,60 +193,71 @@ impl OnDemandService for OnDemand where fn maintain_peers(&self, io: &mut SyncIo) { let mut core = self.core.lock(); for bad_peer in core.maintain_peers() { - trace!(target: "sync", "Remote request timeout for peer {}", bad_peer); - io.disconnect_peer(bad_peer); + io.report_peer(bad_peer, Severity::Timeout); } core.dispatch(); } - fn on_remote_response(&self, io: &mut SyncIo, peer: PeerId, response: message::RemoteCallResponse) { - let mut core = self.core.lock(); - match core.remove(peer, response.id) { - Some(request) => match self.checker.check_execution_proof(&request.request, response.proof) { + fn on_remote_read_response(&self, io: &mut SyncIo, peer: NodeIndex, response: message::RemoteReadResponse) { + self.accept_response("read", io, peer, response.id, |request| match request.data { + RequestData::RemoteRead(request, sender) => match self.checker.check_read_proof(&request, response.proof) { Ok(response) => { // we do not bother if receiver has been dropped already - let _ = request.sender.send(response); + let _ = sender.send(Ok(response)); + Accept::Ok }, - Err(error) => { - trace!(target: "sync", "Failed to check remote response from peer {}: {}", peer, error); - io.disconnect_peer(peer); - core.remove_peer(peer); - core.insert(request.sender, request.request); - }, - }, - None => { - trace!(target: "sync", "Invalid remote response from peer {}", peer); - io.disconnect_peer(peer); - core.remove_peer(peer); + Err(error) => Accept::CheckFailed(error, RequestData::RemoteRead(request, sender)), }, - } + data @ _ => Accept::Unexpected(data), + }) + } - core.dispatch(); + fn on_remote_call_response(&self, io: &mut SyncIo, peer: NodeIndex, response: message::RemoteCallResponse) { + self.accept_response("call", io, peer, response.id, |request| match request.data { + RequestData::RemoteCall(request, sender) => match self.checker.check_execution_proof(&request, response.proof) { + Ok(response) => { + // we do not bother if receiver has been dropped already + let _ = sender.send(Ok(response)); + Accept::Ok + }, + Err(error) => Accept::CheckFailed(error, RequestData::RemoteCall(request, sender)), + }, + data @ _ => Accept::Unexpected(data), + }) } } impl Fetcher for OnDemand where B: BlockT, E: service::ExecuteInContext, - B::Header: HeaderT, + B::Header: HeaderT, { - type RemoteCallResult = Response; + type RemoteReadResult = RemoteResponse>>; + type RemoteCallResult = RemoteResponse; + + fn remote_read(&self, request: RemoteReadRequest) -> Self::RemoteReadResult { + let (sender, receiver) = channel(); + self.schedule_request(RequestData::RemoteRead(request, sender), + RemoteResponse { receiver }) + } fn remote_call(&self, request: RemoteCallRequest) -> Self::RemoteCallResult { - OnDemand::remote_call(self, request) + let (sender, receiver) = channel(); + self.schedule_request(RequestData::RemoteCall(request, sender), + RemoteResponse { receiver }) } } impl OnDemandCore where B: BlockT, - E: service::ExecuteInContext , - B::Header: HeaderT + E: service::ExecuteInContext, + B::Header: HeaderT, { - pub fn add_peer(&mut self, peer: PeerId) { + pub fn add_peer(&mut self, peer: NodeIndex) { self.idle_peers.push_back(peer); } - pub fn remove_peer(&mut self, peer: PeerId) { + pub fn remove_peer(&mut self, peer: NodeIndex) { if let Some(request) = self.active_peers.remove(&peer) { self.pending_requests.push_front(request); return; @@ -215,7 +268,7 @@ impl OnDemandCore where } } - pub fn maintain_peers(&mut self) -> Vec { + pub fn maintain_peers(&mut self) -> Vec { let now = Instant::now(); let mut bad_peers = Vec::new(); loop { @@ -230,19 +283,18 @@ impl OnDemandCore where } } - pub fn insert(&mut self, sender: Sender, request: RemoteCallRequest) { + pub fn insert(&mut self, data: RequestData) { let request_id = self.next_request_id; self.next_request_id += 1; self.pending_requests.push_back(Request { id: request_id, timestamp: Instant::now(), - sender, - request, + data, }); } - pub fn remove(&mut self, peer: PeerId, id: u64) -> Option> { + pub fn remove(&mut self, peer: NodeIndex, id: u64) -> Option> { match self.active_peers.entry(peer) { Entry::Occupied(entry) => match entry.get().id == id { true => { @@ -271,47 +323,63 @@ impl OnDemandCore where request.timestamp = Instant::now(); trace!(target: "sync", "Dispatching remote request {} to peer {}", request.id, peer); - service.execute_in_context(|ctx, protocol| { - let message = message::RemoteCallRequest { - id: request.id, - block: request.request.block, - method: request.request.method.clone(), - data: request.request.call_data.clone(), - }; - - protocol.send_message(ctx, peer, message::generic::Message::RemoteCallRequest(message)) - }); + service.execute_in_context(|ctx| ctx.send_message(peer, request.message())); self.active_peers.insert(peer, request); } } } +impl Request { + pub fn message(&self) -> message::Message { + match self.data { + RequestData::RemoteRead(ref data, _) => message::generic::Message::RemoteReadRequest( + message::RemoteReadRequest { + id: self.id, + block: data.block, + key: data.key.clone(), + }), + RequestData::RemoteCall(ref data, _) => message::generic::Message::RemoteCallRequest( + message::RemoteCallRequest { + id: self.id, + block: data.block, + method: data.method.clone(), + data: data.call_data.clone(), + }), + } + } +} + #[cfg(test)] -mod tests { +pub mod tests { use std::collections::VecDeque; use std::sync::Arc; use std::time::Instant; use futures::Future; use parking_lot::RwLock; use client; - use client::light::{FetchChecker, RemoteCallRequest}; - use io::NetSyncIo; + use client::light::fetcher::{Fetcher, FetchChecker, RemoteCallRequest, RemoteReadRequest}; use message; - use network::PeerId; - use protocol::Protocol; - use service::{Role, ExecuteInContext}; + use network_libp2p::NodeIndex; + use service::{Roles, ExecuteInContext}; use test::TestIo; use super::{REQUEST_TIMEOUT, OnDemand, OnDemandService}; use test_client::runtime::{Block, Hash}; - struct DummyExecutor; + pub struct DummyExecutor; struct DummyFetchChecker { ok: bool } impl ExecuteInContext for DummyExecutor { - fn execute_in_context)>(&self, _closure: F) {} + fn execute_in_context)>(&self, _closure: F) {} } impl FetchChecker for DummyFetchChecker { + fn check_read_proof(&self, _request: &RemoteReadRequest, _remote_proof: Vec>) -> client::error::Result>> { + match self.ok { + true => Ok(Some(vec![42])), + false => Err(client::error::ErrorKind::Backend("Test error".into()).into()), + } + } + fn check_execution_proof(&self, _request: &RemoteCallRequest, _remote_proof: Vec>) -> client::error::Result { match self.ok { true => Ok(client::CallResult { @@ -335,8 +403,8 @@ mod tests { core.idle_peers.len() + core.active_peers.len() } - fn receive_response(on_demand: &OnDemand, network: &mut TestIo, peer: PeerId, id: message::RequestId) { - on_demand.on_remote_response(network, peer, message::RemoteCallResponse { + fn receive_call_response(on_demand: &OnDemand, network: &mut TestIo, peer: NodeIndex, id: message::RequestId) { + on_demand.on_remote_call_response(network, peer, message::RemoteCallResponse { id: id, proof: vec![vec![2]], }); @@ -345,17 +413,16 @@ mod tests { #[test] fn knows_about_peers_roles() { let (_, on_demand) = dummy(true); - on_demand.on_connect(0, Role::LIGHT); - on_demand.on_connect(1, Role::FULL); - on_demand.on_connect(2, Role::COLLATOR); - on_demand.on_connect(3, Role::VALIDATOR); - assert_eq!(vec![1, 2, 3], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); + on_demand.on_connect(0, Roles::LIGHT); + on_demand.on_connect(1, Roles::FULL); + on_demand.on_connect(2, Roles::AUTHORITY); + assert_eq!(vec![1, 2], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); } #[test] fn disconnects_from_idle_peer() { let (_, on_demand) = dummy(true); - on_demand.on_connect(0, Role::FULL); + on_demand.on_connect(0, Roles::FULL); assert_eq!(1, total_peers(&*on_demand)); on_demand.on_disconnect(0); assert_eq!(0, total_peers(&*on_demand)); @@ -367,8 +434,8 @@ mod tests { let queue = RwLock::new(VecDeque::new()); let mut network = TestIo::new(&queue, None); - on_demand.on_connect(0, Role::FULL); - on_demand.on_connect(1, Role::FULL); + on_demand.on_connect(0, Roles::FULL); + on_demand.on_connect(1, Roles::FULL); assert_eq!(vec![0, 1], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); assert!(on_demand.core.lock().active_peers.is_empty()); @@ -388,10 +455,10 @@ mod tests { let (_x, on_demand) = dummy(true); let queue = RwLock::new(VecDeque::new()); let mut network = TestIo::new(&queue, None); - on_demand.on_connect(0, Role::FULL); + on_demand.on_connect(0, Roles::FULL); on_demand.remote_call(RemoteCallRequest { block: Default::default(), method: "test".into(), call_data: vec![] }); - receive_response(&*on_demand, &mut network, 0, 1); + receive_call_response(&*on_demand, &mut network, 0, 1); assert!(network.to_disconnect.contains(&0)); assert_eq!(on_demand.core.lock().pending_requests.len(), 1); } @@ -401,10 +468,10 @@ mod tests { let (_x, on_demand) = dummy(false); let queue = RwLock::new(VecDeque::new()); let mut network = TestIo::new(&queue, None); - on_demand.on_connect(0, Role::FULL); - on_demand.remote_call(RemoteCallRequest { block: Default::default(), method: "test".into(), call_data: vec![] }); - receive_response(&*on_demand, &mut network, 0, 0); + + on_demand.on_connect(0, Roles::FULL); + receive_call_response(&*on_demand, &mut network, 0, 0); assert!(network.to_disconnect.contains(&0)); assert_eq!(on_demand.core.lock().pending_requests.len(), 1); } @@ -414,9 +481,9 @@ mod tests { let (_x, on_demand) = dummy(true); let queue = RwLock::new(VecDeque::new()); let mut network = TestIo::new(&queue, None); - on_demand.on_connect(0, Role::FULL); + on_demand.on_connect(0, Roles::FULL); - receive_response(&*on_demand, &mut network, 0, 0); + receive_call_response(&*on_demand, &mut network, 0, 0); assert!(network.to_disconnect.contains(&0)); } @@ -425,7 +492,7 @@ mod tests { let (_x, on_demand) = dummy(true); let queue = RwLock::new(VecDeque::new()); let mut network = TestIo::new(&queue, None); - on_demand.on_connect(0, Role::FULL); + on_demand.on_connect(0, Roles::FULL); let response = on_demand.remote_call(RemoteCallRequest { block: Default::default(), method: "test".into(), call_data: vec![] }); let thread = ::std::thread::spawn(move || { @@ -433,7 +500,7 @@ mod tests { assert_eq!(result.return_data, vec![42]); }); - receive_response(&*on_demand, &mut network, 0, 0); + receive_call_response(&*on_demand, &mut network, 0, 0); thread.join().unwrap(); } } diff --git a/substrate/network/src/protocol.rs b/substrate/network/src/protocol.rs index 6113ab735730e..545fcc06bc934 100644 --- a/substrate/network/src/protocol.rs +++ b/substrate/network/src/protocol.rs @@ -18,17 +18,19 @@ use std::collections::{HashMap, HashSet}; use std::{mem, cmp}; use std::sync::Arc; use std::time; -use parking_lot::{RwLock, Mutex}; -use serde_json; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hashing, HashingFor}; +use parking_lot::RwLock; +use rustc_hex::ToHex; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hash, HashFor, As}; use runtime_primitives::generic::BlockId; -use network::PeerId; +use network_libp2p::{NodeIndex, Severity}; +use codec::{Encode, Decode}; use message::{self, Message}; use message::generic::Message as GenericMessage; +use specialization::Specialization; use sync::{ChainSync, Status as SyncStatus, SyncState}; -use consensus::Consensus; -use service::{Role, TransactionPool, BftMessageStream}; +use service::{Roles, TransactionPool}; +use import_queue::ImportQueue; use config::ProtocolConfig; use chain::Client; use on_demand::OnDemandService; @@ -36,26 +38,27 @@ use io::SyncIo; use error; const REQUEST_TIMEOUT_SEC: u64 = 40; -const PROTOCOL_VERSION: u32 = 0; + +/// Current protocol version. +pub (crate) const CURRENT_VERSION: u32 = 1; +/// Current packet count. +pub (crate) const CURRENT_PACKET_COUNT: u8 = 1; // Maximum allowed entries in `BlockResponse` const MAX_BLOCK_DATA_RESPONSE: u32 = 128; // Lock must always be taken in order declared here. -pub struct Protocol { +pub struct Protocol> { config: ProtocolConfig, - chain: Arc>, - on_demand: Option>, + on_demand: Option>>, genesis_hash: B::Hash, - sync: RwLock>, - consensus: Mutex>, - // All connected peers - peers: RwLock>>, + sync: Arc>>, + specialization: RwLock, + context_data: ContextData, // Connected peers pending Status message. - handshaking_peers: RwLock>, + handshaking_peers: RwLock>, transaction_pool: Arc>, } - /// Syncing status and statistics #[derive(Clone)] pub struct ProtocolStatus { @@ -72,7 +75,7 @@ struct Peer { /// Protocol version protocol_version: u32, /// Roles - roles: Role, + roles: Roles, /// Peer best block hash best_hash: B::Hash, /// Peer best block number @@ -82,17 +85,18 @@ struct Peer { /// Request timestamp request_timestamp: Option, /// Holds a set of transactions known to this peer. - known_transactions: HashSet, + known_extrinsics: HashSet, /// Holds a set of blocks known to this peer. known_blocks: HashSet, /// Request counter, next_request_id: message::RequestId, } +/// Info about a peer's known state. #[derive(Debug)] pub struct PeerInfo { /// Roles - pub roles: Role, + pub roles: Roles, /// Protocol version pub protocol_version: u32, /// Peer best block hash @@ -101,36 +105,123 @@ pub struct PeerInfo { pub best_number: ::Number, } -impl Protocol where - B::Header: HeaderT -{ +/// Context for a network-specific handler. +pub trait Context { + /// Get a reference to the client. + fn client(&self) -> &::chain::Client; + + /// Point out that a peer has been malign or irresponsible or appeared lazy. + fn report_peer(&mut self, who: NodeIndex, reason: Severity); + + /// Get peer info. + fn peer_info(&self, peer: NodeIndex) -> Option>; + + /// Send a message to a peer. + fn send_message(&mut self, who: NodeIndex, data: ::message::Message); +} + +/// Protocol context. +pub(crate) struct ProtocolContext<'a, B: 'a + BlockT> { + io: &'a mut SyncIo, + context_data: &'a ContextData, +} + +impl<'a, B: BlockT + 'a> ProtocolContext<'a, B> { + pub(crate) fn new(context_data: &'a ContextData, io: &'a mut SyncIo) -> Self { + ProtocolContext { + io, + context_data, + } + } + + /// Send a message to a peer. + pub fn send_message(&mut self, who: NodeIndex, message: Message) { + send_message(&self.context_data.peers, self.io, who, message) + } + + /// Point out that a peer has been malign or irresponsible or appeared lazy. + pub fn report_peer(&mut self, who: NodeIndex, reason: Severity) { + self.io.report_peer(who, reason); + } + + /// Get peer info. + pub fn peer_info(&self, peer: NodeIndex) -> Option> { + self.context_data.peers.read().get(&peer).map(|p| { + PeerInfo { + roles: p.roles, + protocol_version: p.protocol_version, + best_hash: p.best_hash, + best_number: p.best_number, + } + }) + } +} + +impl<'a, B: BlockT + 'a> Context for ProtocolContext<'a, B> { + fn send_message(&mut self, who: NodeIndex, message: Message) { + ProtocolContext::send_message(self, who, message); + } + + fn report_peer(&mut self, who: NodeIndex, reason: Severity) { + ProtocolContext::report_peer(self, who, reason); + } + + fn peer_info(&self, who: NodeIndex) -> Option> { + ProtocolContext::peer_info(self, who) + } + + fn client(&self) -> &Client { + &*self.context_data.chain + } +} + +/// Data necessary to create a context. +pub(crate) struct ContextData { + // All connected peers + peers: RwLock>>, + chain: Arc>, +} + +impl> Protocol { /// Create a new instance. pub fn new( config: ProtocolConfig, chain: Arc>, - on_demand: Option>, - transaction_pool: Arc> + import_queue: Arc>, + on_demand: Option>>, + transaction_pool: Arc>, + specialization: S, ) -> error::Result { let info = chain.info()?; - let sync = ChainSync::new(config.roles, &info); + let sync = ChainSync::new(config.roles, &info, import_queue); let protocol = Protocol { config: config, - chain: chain, - on_demand: on_demand, + context_data: ContextData { + peers: RwLock::new(HashMap::new()), + chain, + }, + on_demand, genesis_hash: info.chain.genesis_hash, - sync: RwLock::new(sync), - consensus: Mutex::new(Consensus::new()), - peers: RwLock::new(HashMap::new()), + sync: Arc::new(RwLock::new(sync)), + specialization: RwLock::new(specialization), handshaking_peers: RwLock::new(HashMap::new()), transaction_pool: transaction_pool, }; Ok(protocol) } + pub(crate) fn context_data(&self) -> &ContextData { + &self.context_data + } + + pub(crate) fn sync(&self) -> &Arc>> { + &self.sync + } + /// Returns protocol status pub fn status(&self) -> ProtocolStatus { let sync = self.sync.read(); - let peers = self.peers.read(); + let peers = self.context_data.peers.read(); ProtocolStatus { sync: sync.status(), num_peers: peers.values().count(), @@ -138,103 +229,86 @@ impl Protocol where } } - pub fn handle_packet(&self, io: &mut SyncIo, peer_id: PeerId, data: &[u8]) { - let message: Message = match serde_json::from_slice(data) { - Ok(m) => m, - Err(e) => { - debug!("Invalid packet from {}: {}", peer_id, e); - io.disable_peer(peer_id); + pub fn handle_packet(&self, io: &mut SyncIo, who: NodeIndex, mut data: &[u8]) { + let message: Message = match Decode::decode(&mut data) { + Some(m) => m, + None => { + trace!(target: "sync", "Invalid packet from {}", who); + io.report_peer(who, Severity::Bad("Peer sent us a packet with invalid format")); return; } }; match message { - GenericMessage::Status(s) => self.on_status_message(io, peer_id, s), - GenericMessage::BlockRequest(r) => self.on_block_request(io, peer_id, r), + GenericMessage::Status(s) => self.on_status_message(io, who, s), + GenericMessage::BlockRequest(r) => self.on_block_request(io, who, r), GenericMessage::BlockResponse(r) => { let request = { - let mut peers = self.peers.write(); - if let Some(ref mut peer) = peers.get_mut(&peer_id) { + let mut peers = self.context_data.peers.write(); + if let Some(ref mut peer) = peers.get_mut(&who) { peer.request_timestamp = None; match mem::replace(&mut peer.block_request, None) { Some(r) => r, None => { - debug!("Unexpected response packet from {}", peer_id); - io.disable_peer(peer_id); + io.report_peer(who, Severity::Bad("Unexpected response packet received from peer")); return; } } } else { - debug!("Unexpected packet from {}", peer_id); - io.disable_peer(peer_id); + io.report_peer(who, Severity::Bad("Unexpected packet received from peer")); return; } }; if request.id != r.id { - trace!(target: "sync", "Ignoring mismatched response packet from {} (expected {} got {})", peer_id, request.id, r.id); + trace!(target: "sync", "Ignoring mismatched response packet from {} (expected {} got {})", who, request.id, r.id); return; } - self.on_block_response(io, peer_id, request, r); + self.on_block_response(io, who, request, r); }, - GenericMessage::BlockAnnounce(announce) => { - self.on_block_announce(io, peer_id, announce); - }, - GenericMessage::BftMessage(m) => self.on_bft_message(io, peer_id, m, HashingFor::::hash(data)), - GenericMessage::Transactions(m) => self.on_transactions(io, peer_id, m), - GenericMessage::RemoteCallRequest(request) => self.on_remote_call_request(io, peer_id, request), - GenericMessage::RemoteCallResponse(response) => self.on_remote_call_response(io, peer_id, response) + GenericMessage::BlockAnnounce(announce) => self.on_block_announce(io, who, announce), + GenericMessage::Transactions(m) => self.on_extrinsics(io, who, m), + GenericMessage::RemoteCallRequest(request) => self.on_remote_call_request(io, who, request), + GenericMessage::RemoteCallResponse(response) => self.on_remote_call_response(io, who, response), + GenericMessage::RemoteReadRequest(request) => self.on_remote_read_request(io, who, request), + GenericMessage::RemoteReadResponse(response) => self.on_remote_read_response(io, who, response), + other => self.specialization.write().on_message(&mut ProtocolContext::new(&self.context_data, io), who, other), } } - pub fn send_message(&self, io: &mut SyncIo, peer_id: PeerId, mut message: Message) { - match &mut message { - &mut GenericMessage::BlockRequest(ref mut r) => { - let mut peers = self.peers.write(); - if let Some(ref mut peer) = peers.get_mut(&peer_id) { - r.id = peer.next_request_id; - peer.next_request_id = peer.next_request_id + 1; - peer.block_request = Some(r.clone()); - peer.request_timestamp = Some(time::Instant::now()); - } - }, - _ => (), - } - let data = serde_json::to_vec(&message).expect("Serializer is infallible; qed"); - if let Err(e) = io.send(peer_id, data) { - debug!(target:"sync", "Error sending message: {:?}", e); - io.disconnect_peer(peer_id); - } - } - - pub fn hash_message(message: &Message) -> B::Hash { - let data = serde_json::to_vec(&message).expect("Serializer is infallible; qed"); - HashingFor::::hash(&data) + pub fn send_message(&self, io: &mut SyncIo, who: NodeIndex, message: Message) { + send_message::(&self.context_data.peers, io, who, message) } /// Called when a new peer is connected - pub fn on_peer_connected(&self, io: &mut SyncIo, peer_id: PeerId) { - trace!(target: "sync", "Connected {}: {}", peer_id, io.peer_info(peer_id)); - self.handshaking_peers.write().insert(peer_id, time::Instant::now()); - self.send_status(io, peer_id); + pub fn on_peer_connected(&self, io: &mut SyncIo, who: NodeIndex) { + trace!(target: "sync", "Connected {}: {}", who, io.peer_info(who)); + self.handshaking_peers.write().insert(who, time::Instant::now()); + self.send_status(io, who); } /// Called by peer when it is disconnecting - pub fn on_peer_disconnected(&self, io: &mut SyncIo, peer: PeerId) { + pub fn on_peer_disconnected(&self, io: &mut SyncIo, peer: NodeIndex) { trace!(target: "sync", "Disconnecting {}: {}", peer, io.peer_info(peer)); + + // lock all the the peer lists so that add/remove peer events are in order + let mut sync = self.sync.write(); + let mut spec = self.specialization.write(); + let removed = { - let mut peers = self.peers.write(); + let mut peers = self.context_data.peers.write(); let mut handshaking_peers = self.handshaking_peers.write(); handshaking_peers.remove(&peer); peers.remove(&peer).is_some() }; if removed { - self.consensus.lock().peer_disconnected(io, self, peer); - self.sync.write().peer_disconnected(io, self, peer); + let mut context = ProtocolContext::new(&self.context_data, io); + sync.peer_disconnected(&mut context, peer); + spec.on_disconnect(&mut context, peer); self.on_demand.as_ref().map(|s| s.on_disconnect(peer)); } } - fn on_block_request(&self, io: &mut SyncIo, peer: PeerId, request: message::BlockRequest) { + fn on_block_request(&self, io: &mut SyncIo, peer: NodeIndex, request: message::BlockRequest) { trace!(target: "sync", "BlockRequest {} from {}: from {:?} to {:?} max {:?}", request.id, peer, request.from, request.to, request.max); let mut blocks = Vec::new(); let mut id = match request.from { @@ -243,38 +317,32 @@ impl Protocol where }; let max = cmp::min(request.max.unwrap_or(u32::max_value()), MAX_BLOCK_DATA_RESPONSE) as usize; // TODO: receipts, etc. - let (mut get_header, mut get_body, mut get_justification) = (false, false, false); - for a in request.fields { - match a { - message::BlockAttribute::Header => get_header = true, - message::BlockAttribute::Body => get_body = true, - message::BlockAttribute::Receipt => unimplemented!(), - message::BlockAttribute::MessageQueue => unimplemented!(), - message::BlockAttribute::Justification => get_justification = true, - } - } - while let Some(header) = self.chain.header(&id).unwrap_or(None) { + let get_header = request.fields.contains(message::BlockAttributes::HEADER); + let get_body = request.fields.contains(message::BlockAttributes::BODY); + let get_justification = request.fields.contains(message::BlockAttributes::JUSTIFICATION); + while let Some(header) = self.context_data.chain.header(&id).unwrap_or(None) { if blocks.len() >= max{ break; } let number = header.number().clone(); let hash = header.hash(); + let justification = if get_justification { self.context_data.chain.justification(&BlockId::Hash(hash)).unwrap_or(None) } else { None }; let block_data = message::generic::BlockData { hash: hash, header: if get_header { Some(header) } else { None }, - body: (if get_body { self.chain.body(&BlockId::Hash(hash)).unwrap_or(None) } else { None }).map(|body| message::Body::Extrinsics(body)), + body: if get_body { self.context_data.chain.body(&BlockId::Hash(hash)).unwrap_or(None) } else { None }, receipt: None, message_queue: None, - justification: if get_justification { self.chain.justification(&BlockId::Hash(hash)).unwrap_or(None) } else { None }, + justification, }; blocks.push(block_data); match request.direction { - message::Direction::Ascending => id = BlockId::Number(number + 1), + message::Direction::Ascending => id = BlockId::Number(number + As::sa(1)), message::Direction::Descending => { - if number == 0 { + if number == As::sa(0) { break; } - id = BlockId::Number(number - 1) + id = BlockId::Number(number - As::sa(1)) } } } @@ -286,57 +354,52 @@ impl Protocol where self.send_message(io, peer, GenericMessage::BlockResponse(response)) } - fn on_block_response(&self, io: &mut SyncIo, peer: PeerId, request: message::BlockRequest, response: message::BlockResponse) { + fn on_block_response(&self, io: &mut SyncIo, peer: NodeIndex, request: message::BlockRequest, response: message::BlockResponse) { // TODO: validate response - trace!(target: "sync", "BlockResponse {} from {} with {} blocks", response.id, peer, response.blocks.len()); - self.sync.write().on_block_data(io, self, peer, request, response); - } - - fn on_bft_message(&self, io: &mut SyncIo, peer: PeerId, message: message::LocalizedBftMessage, hash: B::Hash) { - trace!(target: "sync", "BFT message from {}: {:?}", peer, message); - self.consensus.lock().on_bft_message(io, self, peer, message, hash); - } - - /// See `ConsensusService` trait. - pub fn send_bft_message(&self, io: &mut SyncIo, message: message::LocalizedBftMessage) { - self.consensus.lock().send_bft_message(io, self, message) - } + let blocks_range = match ( + response.blocks.first().and_then(|b| b.header.as_ref().map(|h| h.number())), + response.blocks.last().and_then(|b| b.header.as_ref().map(|h| h.number())), + ) { + (Some(first), Some(last)) if first != last => format!(" ({}..{})", first, last), + (Some(first), Some(_)) => format!(" ({})", first), + _ => Default::default(), + }; + trace!(target: "sync", "BlockResponse {} from {} with {} blocks{}", + response.id, peer, response.blocks.len(), blocks_range); - /// See `ConsensusService` trait. - pub fn bft_messages(&self, parent_hash: B::Hash) -> BftMessageStream { - self.consensus.lock().bft_messages(parent_hash) + self.sync.write().on_block_data(&mut ProtocolContext::new(&self.context_data, io), peer, request, response); } /// Perform time based maintenance. pub fn tick(&self, io: &mut SyncIo) { self.maintain_peers(io); self.on_demand.as_ref().map(|s| s.maintain_peers(io)); - self.consensus.lock().collect_garbage(None); } fn maintain_peers(&self, io: &mut SyncIo) { let tick = time::Instant::now(); let mut aborting = Vec::new(); { - let peers = self.peers.read(); + let peers = self.context_data.peers.read(); let handshaking_peers = self.handshaking_peers.read(); - for (peer_id, timestamp) in peers.iter() + for (who, timestamp) in peers.iter() .filter_map(|(id, peer)| peer.request_timestamp.as_ref().map(|r| (id, r))) .chain(handshaking_peers.iter()) { if (tick - *timestamp).as_secs() > REQUEST_TIMEOUT_SEC { - trace!(target: "sync", "Timeout {}", peer_id); - io.disconnect_peer(*peer_id); - aborting.push(*peer_id); + trace!(target: "sync", "Timeout {}", who); + aborting.push(*who); } } } + + self.specialization.write().maintain_peers(&mut ProtocolContext::new(&self.context_data, io)); for p in aborting { - self.on_peer_disconnected(io, p); + io.report_peer(p, Severity::Timeout); } } - pub fn peer_info(&self, peer: PeerId) -> Option> { - self.peers.read().get(&peer).map(|p| { + pub fn peer_info(&self, peer: NodeIndex) -> Option> { + self.context_data.peers.read().get(&peer).map(|p| { PeerInfo { roles: p.roles, protocol_version: p.protocol_version, @@ -347,92 +410,91 @@ impl Protocol where } /// Called by peer to report status - fn on_status_message(&self, io: &mut SyncIo, peer_id: PeerId, status: message::Status) { - trace!(target: "sync", "New peer {} {:?}", peer_id, status); + fn on_status_message(&self, io: &mut SyncIo, who: NodeIndex, status: message::Status) { + trace!(target: "sync", "New peer {} {:?}", who, status); 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 {}:{}", who, io.peer_info(who)); return; } { - let mut peers = self.peers.write(); + let mut peers = self.context_data.peers.write(); let mut handshaking_peers = self.handshaking_peers.write(); - if peers.contains_key(&peer_id) { - debug!(target: "sync", "Unexpected status packet from {}:{}", peer_id, io.peer_info(peer_id)); + if peers.contains_key(&who) { + debug!(target: "sync", "Unexpected status packet from {}:{}", who, io.peer_info(who)); return; } if status.genesis_hash != self.genesis_hash { - io.disable_peer(peer_id); - trace!(target: "sync", "Peer {} genesis hash mismatch (ours: {}, theirs: {})", peer_id, self.genesis_hash, status.genesis_hash); + io.report_peer(who, Severity::Bad(&format!("Peer is on different chain (our genesis: {} theirs: {})", self.genesis_hash, status.genesis_hash))); return; } - if status.version != PROTOCOL_VERSION { - io.disable_peer(peer_id); - trace!(target: "sync", "Peer {} unsupported eth protocol ({})", peer_id, status.version); + if status.version != CURRENT_VERSION { + io.report_peer(who, Severity::Bad(&format!("Peer using unsupported protocol version {}", status.version))); return; } let peer = Peer { protocol_version: status.version, - roles: message::Role::as_flags(&status.roles), + roles: status.roles, best_hash: status.best_hash, best_number: status.best_number, block_request: None, request_timestamp: None, - known_transactions: HashSet::new(), + known_extrinsics: HashSet::new(), known_blocks: HashSet::new(), next_request_id: 0, }; - peers.insert(peer_id.clone(), peer); - handshaking_peers.remove(&peer_id); - debug!(target: "sync", "Connected {} {}", peer_id, io.peer_info(peer_id)); + peers.insert(who.clone(), peer); + handshaking_peers.remove(&who); + debug!(target: "sync", "Connected {} {}", who, io.peer_info(who)); } - self.sync.write().new_peer(io, self, peer_id); - self.consensus.lock().new_peer(io, self, peer_id, &status.roles); - self.on_demand.as_ref().map(|s| s.on_connect(peer_id, message::Role::as_flags(&status.roles))); + let mut context = ProtocolContext::new(&self.context_data, io); + self.sync.write().new_peer(&mut context, who); + self.specialization.write().on_connect(&mut context, who, status.clone()); + self.on_demand.as_ref().map(|s| s.on_connect(who, status.roles)); } - /// Called when peer sends us new transactions - fn on_transactions(&self, _io: &mut SyncIo, peer_id: PeerId, transactions: message::Transactions) { - // Accept transactions only when fully synced + /// Called when peer sends us new extrinsics + fn on_extrinsics(&self, _io: &mut SyncIo, who: NodeIndex, extrinsics: message::Transactions) { + // Accept extrinsics only when fully synced if self.sync.read().status().state != SyncState::Idle { - trace!(target: "sync", "{} Ignoring transactions while syncing", peer_id); + trace!(target: "sync", "{} Ignoring extrinsics while syncing", who); return; } - trace!(target: "sync", "Received {} transactions from {}", transactions.len(), peer_id); - let mut peers = self.peers.write(); - if let Some(ref mut peer) = peers.get_mut(&peer_id) { - for t in transactions { + trace!(target: "sync", "Received {} extrinsics from {}", extrinsics.len(), who); + let mut peers = self.context_data.peers.write(); + if let Some(ref mut peer) = peers.get_mut(&who) { + for t in extrinsics { if let Some(hash) = self.transaction_pool.import(&t) { - peer.known_transactions.insert(hash); + peer.known_extrinsics.insert(hash); } } } } - /// Called when we propagate ready transactions to peers. - pub fn propagate_transactions(&self, io: &mut SyncIo) { - debug!(target: "sync", "Propagating transactions"); + /// Called when we propagate ready extrinsics to peers. + pub fn propagate_extrinsics(&self, io: &mut SyncIo) { + debug!(target: "sync", "Propagating extrinsics"); // Accept transactions only when fully synced if self.sync.read().status().state != SyncState::Idle { return; } - let transactions = self.transaction_pool.transactions(); + let extrinsics = self.transaction_pool.transactions(); let mut propagated_to = HashMap::new(); - let mut peers = self.peers.write(); - for (peer_id, ref mut peer) in peers.iter_mut() { - let (hashes, to_send): (Vec<_>, Vec<_>) = transactions + let mut peers = self.context_data.peers.write(); + for (who, ref mut peer) in peers.iter_mut() { + let (hashes, to_send): (Vec<_>, Vec<_>) = extrinsics .iter() .cloned() - .filter(|&(hash, _)| peer.known_transactions.insert(hash)) + .filter(|&(hash, _)| peer.known_extrinsics.insert(hash)) .unzip(); if !to_send.is_empty() { - let node_id = io.peer_session_info(*peer_id).map(|info| match info.id { + let node_id = io.peer_session_info(*who).map(|info| match info.id { Some(id) => format!("{}@{:x}", info.remote_address, id), None => info.remote_address.clone(), }); @@ -442,97 +504,153 @@ impl Protocol where propagated_to.entry(hash).or_insert_with(Vec::new).push(id.clone()); } } - trace!(target: "sync", "Sending {} transactions to {}", to_send.len(), peer_id); - self.send_message(io, *peer_id, GenericMessage::Transactions(to_send)); + trace!(target: "sync", "Sending {} transactions to {}", to_send.len(), who); + self.send_message(io, *who, GenericMessage::Transactions(to_send)); } } self.transaction_pool.on_broadcasted(propagated_to); } /// Send Status message - fn send_status(&self, io: &mut SyncIo, peer_id: PeerId) { - if let Ok(info) = self.chain.info() { + fn send_status(&self, io: &mut SyncIo, who: NodeIndex) { + if let Ok(info) = self.context_data.chain.info() { let status = message::generic::Status { - version: PROTOCOL_VERSION, + version: CURRENT_VERSION, genesis_hash: info.chain.genesis_hash, roles: self.config.roles.into(), best_number: info.chain.best_number, best_hash: info.chain.best_hash, - validator_signature: None, - validator_id: None, - parachain_id: None, + chain_status: self.specialization.read().status(), }; - self.send_message(io, peer_id, GenericMessage::Status(status)) + self.send_message(io, who, GenericMessage::Status(status)) } } pub fn abort(&self) { let mut sync = self.sync.write(); - let mut peers = self.peers.write(); + let mut spec = self.specialization.write(); + let mut peers = self.context_data.peers.write(); let mut handshaking_peers = self.handshaking_peers.write(); sync.clear(); + spec.on_abort(); peers.clear(); handshaking_peers.clear(); - self.consensus.lock().restart(); } - pub fn on_block_announce(&self, io: &mut SyncIo, peer_id: PeerId, announce: message::BlockAnnounce) { + pub fn stop(&self) { + // stop processing import requests first (without holding a sync lock) + let import_queue = self.sync.read().import_queue(); + import_queue.stop(); + + // and then clear all the sync data + self.abort(); + } + + pub fn on_block_announce(&self, io: &mut SyncIo, who: NodeIndex, announce: message::BlockAnnounce) { let header = announce.header; let hash = header.hash(); { - let mut peers = self.peers.write(); - if let Some(ref mut peer) = peers.get_mut(&peer_id) { + let mut peers = self.context_data.peers.write(); + if let Some(ref mut peer) = peers.get_mut(&who) { peer.known_blocks.insert(hash.clone()); } } - self.sync.write().on_block_announce(io, self, peer_id, hash, &header); + self.sync.write().on_block_announce(&mut ProtocolContext::new(&self.context_data, io), who, hash, &header); } pub fn on_block_imported(&self, io: &mut SyncIo, hash: B::Hash, header: &B::Header) { self.sync.write().update_chain_info(&header); + self.specialization.write().on_block_imported( + &mut ProtocolContext::new(&self.context_data, io), + hash.clone(), + header + ); // blocks are not announced by light clients - if self.config.roles & Role::LIGHT == Role::LIGHT { + if self.config.roles & Roles::LIGHT == Roles::LIGHT { return; } // send out block announcements - let mut peers = self.peers.write(); + let mut peers = self.context_data.peers.write(); - for (peer_id, ref mut peer) in peers.iter_mut() { + for (who, ref mut peer) in peers.iter_mut() { if peer.known_blocks.insert(hash.clone()) { - trace!(target: "sync", "Announcing block {:?} to {}", hash, peer_id); - self.send_message(io, *peer_id, GenericMessage::BlockAnnounce(message::BlockAnnounce { + trace!(target: "sync", "Announcing block {:?} to {}", hash, who); + self.send_message(io, *who, GenericMessage::BlockAnnounce(message::BlockAnnounce { header: header.clone() })); } } - - self.consensus.lock().collect_garbage(Some(&header)); } - fn on_remote_call_request(&self, io: &mut SyncIo, peer_id: PeerId, request: message::RemoteCallRequest) { - trace!(target: "sync", "Remote request {} from {} ({} at {})", request.id, peer_id, request.method, request.block); - let proof = match self.chain.execution_proof(&request.block, &request.method, &request.data) { + fn on_remote_call_request(&self, io: &mut SyncIo, who: NodeIndex, request: message::RemoteCallRequest) { + trace!(target: "sync", "Remote call request {} from {} ({} at {})", request.id, who, request.method, request.block); + let proof = match self.context_data.chain.execution_proof(&request.block, &request.method, &request.data) { Ok((_, proof)) => proof, Err(error) => { - trace!(target: "sync", "Remote request {} from {} ({} at {}) failed with: {}", - request.id, peer_id, request.method, request.block, error); + trace!(target: "sync", "Remote call request {} from {} ({} at {}) failed with: {}", + request.id, who, request.method, request.block, error); Default::default() }, }; - self.send_message(io, peer_id, GenericMessage::RemoteCallResponse(message::RemoteCallResponse { + self.send_message(io, who, GenericMessage::RemoteCallResponse(message::RemoteCallResponse { id: request.id, proof, })); } - fn on_remote_call_response(&self, io: &mut SyncIo, peer_id: PeerId, response: message::RemoteCallResponse) { - trace!(target: "sync", "Remote response {} from {}", response.id, peer_id); - self.on_demand.as_ref().map(|s| s.on_remote_response(io, peer_id, response)); + fn on_remote_call_response(&self, io: &mut SyncIo, who: NodeIndex, response: message::RemoteCallResponse) { + trace!(target: "sync", "Remote call response {} from {}", response.id, who); + self.on_demand.as_ref().map(|s| s.on_remote_call_response(io, who, response)); } - pub fn chain(&self) -> &Client { - &*self.chain + fn on_remote_read_request(&self, io: &mut SyncIo, who: NodeIndex, request: message::RemoteReadRequest) { + trace!(target: "sync", "Remote read request {} from {} ({} at {})", + request.id, who, request.key.to_hex(), request.block); + let proof = match self.context_data.chain.read_proof(&request.block, &request.key) { + Ok(proof) => proof, + Err(error) => { + trace!(target: "sync", "Remote read request {} from {} ({} at {}) failed with: {}", + request.id, who, request.key.to_hex(), request.block, error); + Default::default() + }, + }; + self.send_message(io, who, GenericMessage::RemoteReadResponse(message::RemoteReadResponse { + id: request.id, proof, + })); + } + fn on_remote_read_response(&self, io: &mut SyncIo, who: NodeIndex, response: message::RemoteReadResponse) { + trace!(target: "sync", "Remote read response {} from {}", response.id, who); + self.on_demand.as_ref().map(|s| s.on_remote_read_response(io, who, response)); + } + + /// Execute a closure with access to a network context and specialization. + pub fn with_spec(&self, io: &mut SyncIo, f: F) -> U + where F: FnOnce(&mut S, &mut Context) -> U + { + f(&mut* self.specialization.write(), &mut ProtocolContext::new(&self.context_data, io)) + } +} + +fn send_message(peers: &RwLock>>, io: &mut SyncIo, who: NodeIndex, mut message: Message) { + match &mut message { + &mut GenericMessage::BlockRequest(ref mut r) => { + let mut peers = peers.write(); + if let Some(ref mut peer) = peers.get_mut(&who) { + r.id = peer.next_request_id; + peer.next_request_id = peer.next_request_id + 1; + peer.block_request = Some(r.clone()); + peer.request_timestamp = Some(time::Instant::now()); + } + }, + _ => (), } + io.send(who, message.encode()); +} + +/// Hash a message. +pub(crate) fn hash_message(message: &Message) -> B::Hash { + let data = message.encode(); + HashFor::::hash(&data) } diff --git a/substrate/network/src/service.rs b/substrate/network/src/service.rs index 06af3c52cc7ad..77114e9d079c3 100644 --- a/substrate/network/src/service.rs +++ b/substrate/network/src/service.rs @@ -1,41 +1,38 @@ // Copyright 2017 Parity Technologies (UK) Ltd. // This file is part of Polkadot. -// Polkadot is free software: you can redistribute it and/or modify +// Substrate 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. -// Polkadot is distributed in the hope that it will be useful, +// Substrate 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 Polkadot. If not, see .? +// along with Substrate. If not, see . use std::collections::HashMap; use std::sync::Arc; use std::io; use std::time::Duration; use futures::sync::{oneshot, mpsc}; -use network::{NetworkProtocolHandler, NetworkContext, HostInfo, PeerId, ProtocolId, +use network_libp2p::{NetworkProtocolHandler, NetworkContext, NodeIndex, ProtocolId, NetworkConfiguration , NonReservedPeerMode, ErrorKind}; -use network_devp2p::{NetworkService}; +use network_libp2p::{NetworkService}; use core_io::{TimerToken}; use io::NetSyncIo; -use protocol::{Protocol, ProtocolStatus, PeerInfo as ProtocolPeerInfo}; +use protocol::{Protocol, ProtocolContext, Context, ProtocolStatus, PeerInfo as ProtocolPeerInfo}; use config::{ProtocolConfig}; use error::Error; use chain::Client; use message::LocalizedBftMessage; +use specialization::Specialization; use on_demand::OnDemandService; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; - -/// Polkadot devp2p protocol id -pub const DOT_PROTOCOL_ID: ProtocolId = *b"dot"; - -const V0_PACKET_COUNT: u8 = 1; +use import_queue::AsyncImportQueue; +use runtime_primitives::traits::{Block as BlockT}; /// Type that represents fetch completion future. pub type FetchFuture = oneshot::Receiver>; @@ -50,17 +47,15 @@ const PROPAGATE_TIMEOUT: Duration = Duration::from_millis(5000); bitflags! { /// Node roles bitmask. - pub struct Role: u32 { + pub struct Roles: u8 { /// No network. const NONE = 0b00000000; - /// Full node, doe not participate in consensus. + /// Full node, does not participate in consensus. const FULL = 0b00000001; /// Light client node. const LIGHT = 0b00000010; - /// Act as a validator. - const VALIDATOR = 0b00000100; - /// Act as a collator. - const COLLATOR = 0b00001000; + /// Act as an authority + const AUTHORITY = 0b00000100; } } @@ -99,12 +94,12 @@ pub trait ConsensusService: Send + Sync { /// Service able to execute closure in the network context. pub trait ExecuteInContext: Send + Sync { /// Execute closure in network context. - fn execute_in_context)>(&self, closure: F); + fn execute_in_context)>(&self, closure: F); } /// devp2p Protocol handler -struct ProtocolHandler { - protocol: Protocol, +struct ProtocolHandler> { + protocol: Protocol, } /// Peer connection information @@ -125,7 +120,7 @@ pub struct PeerInfo { } /// Service initialization parameters. -pub struct Params { +pub struct Params { /// Configuration. pub config: ProtocolConfig, /// Network layer configuration. @@ -133,79 +128,112 @@ pub struct Params { /// Polkadot relay chain access point. pub chain: Arc>, /// On-demand service reference. - pub on_demand: Option>, + pub on_demand: Option>>, /// Transaction pool. pub transaction_pool: Arc>, + /// Protocol specialization. + pub specialization: S, } /// Polkadot network service. Handles network IO and manages connectivity. -pub struct Service where B::Header: HeaderT { +pub struct Service> { /// Network service network: NetworkService, /// Devp2p protocol handler - handler: Arc>, + handler: Arc>, + /// Devp2p protocol ID. + protocol_id: ProtocolId, } -impl Service where B::Header: HeaderT { +impl> Service { /// Creates and register protocol with the network service - pub fn new(params: Params) -> Result>, Error> { + pub fn new(params: Params, protocol_id: ProtocolId) -> Result>, Error> { + let chain = params.chain.clone(); let service = NetworkService::new(params.network_config.clone(), None)?; + let import_queue = Arc::new(AsyncImportQueue::new()); let sync = Arc::new(Service { network: service, + protocol_id, handler: Arc::new(ProtocolHandler { - protocol: Protocol::new(params.config, params.chain, params.on_demand, params.transaction_pool)?, + protocol: Protocol::new( + params.config, + params.chain, + import_queue.clone(), + params.on_demand, + params.transaction_pool, + params.specialization, + )?, }), }); + import_queue.start( + Arc::downgrade(sync.handler.protocol.sync()), + Arc::downgrade(&sync), + Arc::downgrade(&chain) + )?; + Ok(sync) } /// Called when a new block is imported by the client. pub fn on_block_imported(&self, hash: B::Hash, header: &B::Header) { - self.network.with_context(DOT_PROTOCOL_ID, |context| { + self.network.with_context(self.protocol_id, |context| { self.handler.protocol.on_block_imported(&mut NetSyncIo::new(context), hash, header) }); } /// Called when new transactons are imported by the client. pub fn trigger_repropagate(&self) { - self.network.with_context(DOT_PROTOCOL_ID, |context| { - self.handler.protocol.propagate_transactions(&mut NetSyncIo::new(context)); + self.network.with_context(self.protocol_id, |context| { + self.handler.protocol.propagate_extrinsics(&mut NetSyncIo::new(context)); + }); + } + + /// Execute a closure with the chain-specific network specialization. + /// If the network is unavailable, this will return `None`. + pub fn with_spec(&self, f: F) -> Option + where F: FnOnce(&mut S, &mut Context) -> U + { + let mut res = None; + self.network.with_context(self.protocol_id, |context| { + res = Some(self.handler.protocol.with_spec(&mut NetSyncIo::new(context), f)) }); + + res } fn start(&self) { - match self.network.start().map_err(Into::into) { + let versions = [(::protocol::CURRENT_VERSION as u8, ::protocol::CURRENT_PACKET_COUNT)]; + let protocols = vec![(self.handler.clone() as Arc<_>, self.protocol_id, &versions[..])]; + match self.network.start(protocols).map_err(|e| e.0.into()) { Err(ErrorKind::Io(ref e)) if e.kind() == io::ErrorKind::AddrInUse => - warn!("Network port {:?} is already in use, make sure that another instance of Polkadot client is not running or change the port using the --port option.", self.network.config().listen_address.expect("Listen address is not set.")), + warn!("Network port is already in use, make sure that another instance of Polkadot client is not running or change the port using the --port option."), Err(err) => warn!("Error starting network: {}", err), _ => {}, }; - self.network.register_protocol(self.handler.clone(), DOT_PROTOCOL_ID, &[(0, V0_PACKET_COUNT)]) - .unwrap_or_else(|e| warn!("Error registering polkadot protocol: {:?}", e)); } fn stop(&self) { - self.handler.protocol.abort(); + self.handler.protocol.stop(); self.network.stop(); } } -impl Drop for Service where B::Header: HeaderT { +impl> Drop for Service { fn drop(&mut self) { self.stop(); } } -impl ExecuteInContext for Service where B::Header: HeaderT { - fn execute_in_context)>(&self, closure: F) { - self.network.with_context(DOT_PROTOCOL_ID, |context| { - closure(&mut NetSyncIo::new(context), &self.handler.protocol) +impl> ExecuteInContext for Service { + fn execute_in_context)>(&self, closure: F) { + self.network.with_context(self.protocol_id, |context| { + closure(&mut ProtocolContext::new(self.handler.protocol.context_data(), &mut NetSyncIo::new(context))) }); } } -impl SyncProvider for Service where B::Header: HeaderT { +impl> SyncProvider for Service { /// Get sync status fn status(&self) -> ProtocolStatus { self.handler.protocol.status() @@ -213,11 +241,11 @@ impl SyncProvider for Service where B::Header: Header /// Get sync peers fn peers(&self) -> Vec> { - self.network.with_context_eval(DOT_PROTOCOL_ID, |ctx| { + self.network.with_context_eval(self.protocol_id, |ctx| { let peer_ids = self.network.connected_peers(); - peer_ids.into_iter().filter_map(|peer_id| { - let session_info = match ctx.session_info(peer_id) { + peer_ids.into_iter().filter_map(|who| { + let session_info = match ctx.session_info(who) { None => return None, Some(info) => info, }; @@ -228,7 +256,7 @@ impl SyncProvider for Service where B::Header: Header capabilities: session_info.peer_capabilities.into_iter().map(|c| c.to_string()).collect(), remote_address: session_info.remote_address, local_address: session_info.local_address, - dot_info: self.handler.protocol.peer_info(peer_id), + dot_info: self.handler.protocol.peer_info(who), }) }).collect() }).unwrap_or_else(Vec::new) @@ -239,25 +267,8 @@ impl SyncProvider for Service where B::Header: Header } } -/// ConsensusService -impl ConsensusService for Service where B::Header: HeaderT { - fn connect_to_authorities(&self, _addresses: &[String]) { - //TODO: implement me - } - - fn bft_messages(&self, parent_hash: B::Hash) -> BftMessageStream { - self.handler.protocol.bft_messages(parent_hash) - } - - fn send_bft_message(&self, message: LocalizedBftMessage) { - self.network.with_context(DOT_PROTOCOL_ID, |context| { - self.handler.protocol.send_bft_message(&mut NetSyncIo::new(context), message); - }); - } -} - -impl NetworkProtocolHandler for ProtocolHandler where B::Header: HeaderT { - fn initialize(&self, io: &NetworkContext, _host_info: &HostInfo) { +impl> NetworkProtocolHandler for ProtocolHandler { + fn initialize(&self, io: &NetworkContext) { io.register_timer(TICK_TOKEN, TICK_TIMEOUT) .expect("Error registering sync timer"); @@ -265,22 +276,22 @@ impl NetworkProtocolHandler for ProtocolHandler where B: .expect("Error registering transaction propagation timer"); } - fn read(&self, io: &NetworkContext, peer: &PeerId, _packet_id: u8, data: &[u8]) { + fn read(&self, io: &NetworkContext, peer: &NodeIndex, _packet_id: u8, data: &[u8]) { self.protocol.handle_packet(&mut NetSyncIo::new(io), *peer, data); } - fn connected(&self, io: &NetworkContext, peer: &PeerId) { + fn connected(&self, io: &NetworkContext, peer: &NodeIndex) { self.protocol.on_peer_connected(&mut NetSyncIo::new(io), *peer); } - fn disconnected(&self, io: &NetworkContext, peer: &PeerId) { + fn disconnected(&self, io: &NetworkContext, peer: &NodeIndex) { self.protocol.on_peer_disconnected(&mut NetSyncIo::new(io), *peer); } fn timeout(&self, io: &NetworkContext, timer: TimerToken) { match timer { TICK_TOKEN => self.protocol.tick(&mut NetSyncIo::new(io)), - PROPAGATE_TOKEN => self.protocol.propagate_transactions(&mut NetSyncIo::new(io)), + PROPAGATE_TOKEN => self.protocol.propagate_extrinsics(&mut NetSyncIo::new(io)), _ => {} } } @@ -303,7 +314,7 @@ pub trait ManageNetwork: Send + Sync { } -impl ManageNetwork for Service where B::Header: HeaderT { +impl> ManageNetwork for Service { fn accept_unreserved_peers(&self) { self.network.set_non_reserved_mode(NonReservedPeerMode::Accept); } diff --git a/substrate/network/src/specialization.rs b/substrate/network/src/specialization.rs new file mode 100644 index 0000000000000..3c04a367059cd --- /dev/null +++ b/substrate/network/src/specialization.rs @@ -0,0 +1,48 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +//! Specializations of the substrate network protocol to allow more complex forms of communication. + +use ::NodeIndex; +use runtime_primitives::traits::Block as BlockT; +use protocol::Context; + +/// A specialization of the substrate network protocol. Handles events and sends messages. +pub trait Specialization: Send + Sync + 'static { + /// Get the current specialization-status. + fn status(&self) -> Vec; + + /// Called on start-up. + fn on_start(&mut self) { } + + /// Called when a peer successfully handshakes. + fn on_connect(&mut self, ctx: &mut Context, who: NodeIndex, status: ::message::Status); + + /// Called when a peer is disconnected. If the peer ID is unknown, it should be ignored. + fn on_disconnect(&mut self, ctx: &mut Context, who: NodeIndex); + + /// Called when a network-specific message arrives. + fn on_message(&mut self, ctx: &mut Context, who: NodeIndex, message: ::message::Message); + + /// Called on abort. + fn on_abort(&mut self) { } + + /// Called periodically to maintain peers and handle timeouts. + fn maintain_peers(&mut self, _ctx: &mut Context) { } + + /// Called when a block is _imported_ at the head of the chain (not during major sync). + fn on_block_imported(&mut self, _ctx: &mut Context, _hash: B::Hash, _header: &B::Header) { } +} diff --git a/substrate/network/src/sync.rs b/substrate/network/src/sync.rs index 8a296d4534f4f..3cfcf07ef340f 100644 --- a/substrate/network/src/sync.rs +++ b/substrate/network/src/sync.rs @@ -15,43 +15,48 @@ // along with Polkadot. If not, see .? use std::collections::HashMap; -use io::SyncIo; -use protocol::Protocol; -use network::PeerId; -use client::{ImportResult, BlockStatus, ClientInfo}; +use std::sync::Arc; +use protocol::Context; +use network_libp2p::{Severity, NodeIndex}; +use client::{BlockStatus, BlockOrigin, ClientInfo}; +use client::error::Error as ClientError; use blocks::{self, BlockCollection}; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, NumberFor}; use runtime_primitives::generic::BlockId; use message::{self, generic::Message as GenericMessage}; -use service::Role; +use service::Roles; +use import_queue::ImportQueue; // Maximum blocks to request in a single packet. const MAX_BLOCKS_TO_REQUEST: usize = 128; +// Maximum blocks to store in the import queue. +const MAX_IMPORING_BLOCKS: usize = 2048; struct PeerSync { pub common_hash: B::Hash, - pub common_number: ::Number, + pub common_number: NumberFor, pub best_hash: B::Hash, - pub best_number: ::Number, + pub best_number: NumberFor, pub state: PeerSyncState, } #[derive(Copy, Clone, Eq, PartialEq, Debug)] enum PeerSyncState { - AncestorSearch(::Number), + AncestorSearch(NumberFor), Available, - DownloadingNew(::Number), + DownloadingNew(NumberFor), DownloadingStale(B::Hash), } /// Relay chain sync strategy. pub struct ChainSync { genesis_hash: B::Hash, - peers: HashMap>, + peers: HashMap>, blocks: BlockCollection, - best_queued_number: u64, + best_queued_number: NumberFor, best_queued_hash: B::Hash, - required_block_attributes: Vec, + required_block_attributes: message::BlockAttributes, + import_queue: Arc>, } /// Reported sync state. @@ -69,20 +74,15 @@ pub struct Status { /// Current global sync state. pub state: SyncState, /// Target sync block number. - pub best_seen_block: Option<::Number>, + pub best_seen_block: Option>, } -impl ChainSync where - B::Header: HeaderT, -{ +impl ChainSync { /// Create a new instance. - pub fn new(role: Role, info: &ClientInfo) -> Self { - let mut required_block_attributes = vec![ - message::BlockAttribute::Header, - message::BlockAttribute::Justification - ]; - if role.intersects(Role::FULL | Role::VALIDATOR | Role::COLLATOR) { - required_block_attributes.push(message::BlockAttribute::Body); + pub(crate) fn new(role: Roles, info: &ClientInfo, import_queue: Arc>) -> Self { + let mut required_block_attributes = message::BlockAttributes::HEADER | message::BlockAttributes::JUSTIFICATION; + if role.intersects(Roles::FULL | Roles::AUTHORITY) { + required_block_attributes |= message::BlockAttributes::BODY; } ChainSync { @@ -91,19 +91,25 @@ impl ChainSync where blocks: BlockCollection::new(), best_queued_hash: info.best_queued_hash.unwrap_or(info.chain.best_hash), best_queued_number: info.best_queued_number.unwrap_or(info.chain.best_number), - required_block_attributes: required_block_attributes, + required_block_attributes, + import_queue, } } - fn best_seen_block(&self) -> Option { + fn best_seen_block(&self) -> Option> { self.peers.values().max_by_key(|p| p.best_number).map(|p| p.best_number) } - /// Returns sync status - pub fn status(&self) -> Status { + /// Returns import queue reference. + pub(crate) fn import_queue(&self) -> Arc> { + self.import_queue.clone() + } + + /// Returns sync status. + pub(crate) fn status(&self) -> Status { let best_seen = self.best_seen_block(); let state = match &best_seen { - &Some(n) if n > self.best_queued_number && n - self.best_queued_number > 5 => SyncState::Downloading, + &Some(n) if n > self.best_queued_number && n - self.best_queued_number > As::sa(5) => SyncState::Downloading, _ => SyncState::Idle, }; Status { @@ -113,49 +119,47 @@ impl ChainSync where } /// Handle new connected peer. - pub fn new_peer(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId) { - if let Some(info) = protocol.peer_info(peer_id) { - match (protocol.chain().block_status(&BlockId::Hash(info.best_hash)), info.best_number) { + pub(crate) fn new_peer(&mut self, protocol: &mut Context, who: NodeIndex) { + if let Some(info) = protocol.peer_info(who) { + match (block_status(&*protocol.client(), &*self.import_queue, info.best_hash), info.best_number) { (Err(e), _) => { debug!(target:"sync", "Error reading blockchain: {:?}", e); - io.disconnect_peer(peer_id); + protocol.report_peer(who, Severity::Useless(&format!("Error legimimately reading blockchain status: {:?}", e))); }, (Ok(BlockStatus::KnownBad), _) => { - debug!(target:"sync", "New peer with known bad best block {} ({}).", info.best_hash, info.best_number); - io.disable_peer(peer_id); + protocol.report_peer(who, Severity::Bad(&format!("New peer with known bad best block {} ({}).", info.best_hash, info.best_number))); }, - (Ok(BlockStatus::Unknown), 0) => { - debug!(target:"sync", "New peer with unknown genesis hash {} ({}).", info.best_hash, info.best_number); - io.disable_peer(peer_id); + (Ok(BlockStatus::Unknown), b) if b == As::sa(0) => { + protocol.report_peer(who, Severity::Bad(&format!("New peer with unknown genesis hash {} ({}).", info.best_hash, info.best_number))); }, (Ok(BlockStatus::Unknown), _) => { let our_best = self.best_queued_number; - if our_best > 0 { + if our_best > As::sa(0) { debug!(target:"sync", "New peer with unknown best hash {} ({}), searching for common ancestor.", info.best_hash, info.best_number); - self.peers.insert(peer_id, PeerSync { + self.peers.insert(who, PeerSync { common_hash: self.genesis_hash, - common_number: 0, + common_number: As::sa(0), best_hash: info.best_hash, best_number: info.best_number, state: PeerSyncState::AncestorSearch(our_best), }); - Self::request_ancestry(io, protocol, peer_id, our_best) + Self::request_ancestry(protocol, who, our_best) } else { // We are at genesis, just start downloading debug!(target:"sync", "New peer with best hash {} ({}).", info.best_hash, info.best_number); - self.peers.insert(peer_id, PeerSync { + self.peers.insert(who, PeerSync { common_hash: self.genesis_hash, - common_number: 0, + common_number: As::sa(0), best_hash: info.best_hash, best_number: info.best_number, state: PeerSyncState::Available, }); - self.download_new(io, protocol, peer_id) + self.download_new(protocol, who) } }, (Ok(BlockStatus::Queued), _) | (Ok(BlockStatus::InChain), _) => { debug!(target:"sync", "New peer with known best hash {} ({}).", info.best_hash, info.best_number); - self.peers.insert(peer_id, PeerSync { + self.peers.insert(who, PeerSync { common_hash: info.best_hash, common_number: info.best_number, best_hash: info.best_hash, @@ -167,61 +171,58 @@ impl ChainSync where } } - pub fn on_block_data(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, _request: message::BlockRequest, response: message::BlockResponse) { - let count = response.blocks.len(); - let mut imported: usize = 0; - let new_blocks = if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { + pub(crate) fn on_block_data(&mut self, protocol: &mut Context, who: NodeIndex, _request: message::BlockRequest, response: message::BlockResponse) { + let new_blocks = if let Some(ref mut peer) = self.peers.get_mut(&who) { match peer.state { PeerSyncState::DownloadingNew(start_block) => { - self.blocks.clear_peer_download(peer_id); + self.blocks.clear_peer_download(who); peer.state = PeerSyncState::Available; - self.blocks.insert(start_block, response.blocks, peer_id); - self.blocks.drain(self.best_queued_number + 1) + self.blocks.insert(start_block, response.blocks, who); + self.blocks.drain(self.best_queued_number + As::sa(1)) }, PeerSyncState::DownloadingStale(_) => { peer.state = PeerSyncState::Available; response.blocks.into_iter().map(|b| blocks::BlockData { - origin: peer_id, + origin: who, block: b }).collect() }, PeerSyncState::AncestorSearch(n) => { match response.blocks.get(0) { Some(ref block) => { - trace!(target: "sync", "Got ancestry block #{} ({}) from peer {}", n, block.hash, peer_id); - match protocol.chain().block_hash(n) { + trace!(target: "sync", "Got ancestry block #{} ({}) from peer {}", n, block.hash, who); + match protocol.client().block_hash(n) { Ok(Some(block_hash)) if block_hash == block.hash => { if peer.common_number < n { peer.common_hash = block.hash; peer.common_number = n; } peer.state = PeerSyncState::Available; - trace!(target:"sync", "Found common ancestor for peer {}: {} ({})", peer_id, block.hash, n); + trace!(target:"sync", "Found common ancestor for peer {}: {} ({})", who, block.hash, n); vec![] }, - Ok(our_best) if n > 0 => { - trace!(target:"sync", "Ancestry block mismatch for peer {}: theirs: {} ({}), ours: {:?}", peer_id, block.hash, n, our_best); - let n = n - 1; + Ok(our_best) if n > As::sa(0) => { + trace!(target:"sync", "Ancestry block mismatch for peer {}: theirs: {} ({}), ours: {:?}", who, block.hash, n, our_best); + let n = n - As::sa(1); peer.state = PeerSyncState::AncestorSearch(n); - Self::request_ancestry(io, protocol, peer_id, n); + Self::request_ancestry(protocol, who, n); return; }, Ok(_) => { // genesis mismatch - trace!(target:"sync", "Ancestry search: genesis mismatch for peer {}", peer_id); - io.disable_peer(peer_id); + trace!(target:"sync", "Ancestry search: genesis mismatch for peer {}", who); + protocol.report_peer(who, Severity::Bad("Ancestry search: genesis mismatch for peer")); return; }, Err(e) => { - debug!(target:"sync", "Error reading blockchain: {:?}", e); - io.disconnect_peer(peer_id); + protocol.report_peer(who, Severity::Useless(&format!("Error answering legitimate blockchain query: {:?}", e))); return; } } }, None => { - trace!(target:"sync", "Invalid response when searching for ancestor from {}", peer_id); - io.disconnect_peer(peer_id); + trace!(target:"sync", "Invalid response when searching for ancestor from {}", who); + protocol.report_peer(who, Severity::Bad("Invalid response when searching for ancestor")); return; } } @@ -233,90 +234,20 @@ impl ChainSync where }; let best_seen = self.best_seen_block(); - // Blocks in the response/drain should be in ascending order. - for block in new_blocks { - let origin = block.origin; - let block = block.block; - match (block.header, block.justification) { - (Some(header), Some(justification)) => { - let number = header.number().clone(); - let hash = header.hash(); - let parent = header.parent_hash().clone(); - let is_best = best_seen.as_ref().map_or(false, |n| number >= *n); - - // check whether the block is known before importing. - match protocol.chain().block_status(&BlockId::Hash(hash)) { - Ok(BlockStatus::InChain) => continue, - Ok(_) => {}, - Err(e) => { - debug!(target: "sync", "Error importing block {}: {:?}: {:?}", number, hash, e); - self.restart(io, protocol); - return; - } - } - - let result = protocol.chain().import( - is_best, - header, - justification, - block.body.map(|b| b.to_extrinsics()), - ); - match result { - Ok(ImportResult::AlreadyInChain) => { - trace!(target: "sync", "Block already in chain {}: {:?}", number, hash); - self.block_imported(&hash, number); - }, - Ok(ImportResult::AlreadyQueued) => { - trace!(target: "sync", "Block already queued {}: {:?}", number, hash); - self.block_imported(&hash, number); - }, - Ok(ImportResult::Queued) => { - trace!(target: "sync", "Block queued {}: {:?}", number, hash); - self.block_imported(&hash, number); - imported = imported + 1; - }, - Ok(ImportResult::UnknownParent) => { - debug!(target: "sync", "Block with unknown parent {}: {:?}, parent: {:?}", number, hash, parent); - self.restart(io, protocol); - return; - }, - Ok(ImportResult::KnownBad) => { - debug!(target: "sync", "Bad block {}: {:?}", number, hash); - io.disable_peer(origin); //TODO: use persistent ID - self.restart(io, protocol); - return; - } - Err(e) => { - debug!(target: "sync", "Error importing block {}: {:?}: {:?}", number, hash, e); - self.restart(io, protocol); - return; - } - } - }, - (None, _) => { - debug!(target: "sync", "Header {} was not provided by {} ", block.hash, origin); - io.disable_peer(origin); //TODO: use persistent ID - return; - }, - (_, None) => { - debug!(target: "sync", "Justification set for block {} was not provided by {} ", block.hash, origin); - io.disable_peer(origin); //TODO: use persistent ID - return; - } - } - } - trace!(target: "sync", "Imported {} of {}", imported, count); - self.maintain_sync(io, protocol); + let is_best = new_blocks.first().and_then(|b| b.block.header.as_ref()).map(|h| best_seen.as_ref().map_or(false, |n| h.number() >= n)); + let origin = if is_best.unwrap_or_default() { BlockOrigin::NetworkBroadcast } else { BlockOrigin::NetworkInitialSync }; + let import_queue = self.import_queue.clone(); + import_queue.import_blocks(self, protocol, (origin, new_blocks)) } - fn maintain_sync(&mut self, io: &mut SyncIo, protocol: &Protocol) { - let peers: Vec = self.peers.keys().map(|p| *p).collect(); + pub fn maintain_sync(&mut self, protocol: &mut Context) { + let peers: Vec = self.peers.keys().map(|p| *p).collect(); for peer in peers { - self.download_new(io, protocol, peer); + self.download_new(protocol, peer); } } - fn block_imported(&mut self, hash: &B::Hash, number: u64) { + pub fn block_imported(&mut self, hash: &B::Hash, number: NumberFor) { if number > self.best_queued_number { self.best_queued_number = number; self.best_queued_hash = *hash; @@ -331,14 +262,14 @@ impl ChainSync where } } - pub fn update_chain_info(&mut self, best_header: &B::Header) { + pub(crate) fn update_chain_info(&mut self, best_header: &B::Header) { let hash = best_header.hash(); self.block_imported(&hash, best_header.number().clone()) } - pub fn on_block_announce(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, hash: B::Hash, header: &B::Header) { + pub(crate) fn on_block_announce(&mut self, protocol: &mut Context, who: NodeIndex, hash: B::Hash, header: &B::Header) { let number = *header.number(); - if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { + if let Some(ref mut peer) = self.peers.get_mut(&who) { if number > peer.best_number { peer.best_number = number; peer.best_hash = hash; @@ -354,38 +285,39 @@ impl ChainSync where let stale = number <= self.best_queued_number; if stale { if !self.is_known_or_already_downloading(protocol, header.parent_hash()) { - trace!(target: "sync", "Ignoring unknown stale block announce from {}: {} {:?}", peer_id, hash, header); + trace!(target: "sync", "Ignoring unknown stale block announce from {}: {} {:?}", who, hash, header); } else { - trace!(target: "sync", "Downloading new stale block announced from {}: {} {:?}", peer_id, hash, header); - self.download_stale(io, protocol, peer_id, &hash); + trace!(target: "sync", "Downloading new stale block announced from {}: {} {:?}", who, hash, header); + self.download_stale(protocol, who, &hash); } } else { - trace!(target: "sync", "Downloading new block announced from {}: {} {:?}", peer_id, hash, header); - self.download_new(io, protocol, peer_id); + trace!(target: "sync", "Downloading new block announced from {}: {} {:?}", who, hash, header); + self.download_new(protocol, who); } } else { - trace!(target: "sync", "Known block announce from {}: {}", peer_id, hash); + trace!(target: "sync", "Known block announce from {}: {}", who, hash); } } - fn is_known_or_already_downloading(&self, protocol: &Protocol, hash: &B::Hash) -> bool { + fn is_known_or_already_downloading(&self, protocol: &mut Context, hash: &B::Hash) -> bool { self.peers.iter().any(|(_, p)| p.state == PeerSyncState::DownloadingStale(*hash)) - || protocol.chain().block_status(&BlockId::Hash(*hash)).ok().map_or(false, |s| s != BlockStatus::Unknown) + || block_status(&*protocol.client(), &*self.import_queue, *hash).ok().map_or(false, |s| s != BlockStatus::Unknown) } - pub fn peer_disconnected(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId) { - self.blocks.clear_peer_download(peer_id); - self.peers.remove(&peer_id); - self.maintain_sync(io, protocol); + pub(crate) fn peer_disconnected(&mut self, protocol: &mut Context, who: NodeIndex) { + self.blocks.clear_peer_download(who); + self.peers.remove(&who); + self.maintain_sync(protocol); } - pub fn restart(&mut self, io: &mut SyncIo, protocol: &Protocol) { + pub(crate) fn restart(&mut self, protocol: &mut Context) { + self.import_queue.clear(); self.blocks.clear(); - let ids: Vec = self.peers.keys().map(|p| *p).collect(); + let ids: Vec = self.peers.keys().map(|p| *p).collect(); for id in ids { - self.new_peer(io, protocol, id); + self.new_peer(protocol, id); } - match protocol.chain().info() { + match protocol.client().info() { Ok(info) => { self.best_queued_hash = info.best_queued_hash.unwrap_or(info.chain.best_hash); self.best_queued_number = info.best_queued_number.unwrap_or(info.chain.best_number); @@ -393,19 +325,19 @@ impl ChainSync where Err(e) => { debug!(target:"sync", "Error reading blockchain: {:?}", e); self.best_queued_hash = self.genesis_hash; - self.best_queued_number = 0; + self.best_queued_number = As::sa(0); } } } - pub fn clear(&mut self) { + pub(crate) fn clear(&mut self) { self.blocks.clear(); self.peers.clear(); } // Download old block. - fn download_stale(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, hash: &B::Hash) { - if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { + fn download_stale(&mut self, protocol: &mut Context, who: NodeIndex, hash: &B::Hash) { + if let Some(ref mut peer) = self.peers.get_mut(&who) { match peer.state { PeerSyncState::Available => { let request = message::generic::BlockRequest { @@ -417,7 +349,7 @@ impl ChainSync where max: Some(1), }; peer.state = PeerSyncState::DownloadingStale(*hash); - protocol.send_message(io, peer_id, GenericMessage::BlockRequest(request)); + protocol.send_message(who, GenericMessage::BlockRequest(request)); }, _ => (), } @@ -425,23 +357,31 @@ impl ChainSync where } // Issue a request for a peer to download new blocks, if any are available - fn download_new(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId) { - if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { - trace!(target: "sync", "Considering new block download from {}, common block is {}, best is {:?}", peer_id, peer.common_number, peer.best_number); + fn download_new(&mut self, protocol: &mut Context, who: NodeIndex) { + if let Some(ref mut peer) = self.peers.get_mut(&who) { + let import_status = self.import_queue.status(); + // when there are too many blocks in the queue => do not try to download new blocks + if import_status.importing_count > MAX_IMPORING_BLOCKS { + return; + } + // we should not download already queued blocks + let common_number = ::std::cmp::max(peer.common_number, import_status.best_importing_number); + + trace!(target: "sync", "Considering new block download from {}, common block is {}, best is {:?}", who, common_number, peer.best_number); match peer.state { PeerSyncState::Available => { - if let Some(range) = self.blocks.needed_blocks(peer_id, MAX_BLOCKS_TO_REQUEST, peer.best_number, peer.common_number) { - trace!(target: "sync", "Requesting blocks from {}, ({} to {})", peer_id, range.start, range.end); + if let Some(range) = self.blocks.needed_blocks(who, MAX_BLOCKS_TO_REQUEST, peer.best_number, common_number) { + trace!(target: "sync", "Requesting blocks from {}, ({} to {})", who, range.start, range.end); let request = message::generic::BlockRequest { id: 0, fields: self.required_block_attributes.clone(), from: message::FromBlock::Number(range.start), to: None, direction: message::Direction::Ascending, - max: Some((range.end - range.start) as u32), + max: Some((range.end - range.start).as_() as u32), }; peer.state = PeerSyncState::DownloadingNew(range.start); - protocol.send_message(io, peer_id, GenericMessage::BlockRequest(request)); + protocol.send_message(who, GenericMessage::BlockRequest(request)); } else { trace!(target: "sync", "Nothing to request"); } @@ -451,16 +391,29 @@ impl ChainSync where } } - fn request_ancestry(io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, block: u64) { - trace!(target: "sync", "Requesting ancestry block #{} from {}", block, peer_id); + fn request_ancestry(protocol: &mut Context, who: NodeIndex, block: NumberFor) { + trace!(target: "sync", "Requesting ancestry block #{} from {}", block, who); let request = message::generic::BlockRequest { id: 0, - fields: vec![message::BlockAttribute::Header, message::BlockAttribute::Justification], + fields: message::BlockAttributes::HEADER | message::BlockAttributes::JUSTIFICATION, from: message::FromBlock::Number(block), to: None, direction: message::Direction::Ascending, max: Some(1), }; - protocol.send_message(io, peer_id, GenericMessage::BlockRequest(request)); + protocol.send_message(who, GenericMessage::BlockRequest(request)); } } + +/// Get block status, taking into account import queue. +fn block_status( + chain: &::chain::Client, + queue: &ImportQueue, + hash: B::Hash) -> Result +{ + if queue.is_importing(&hash) { + return Ok(BlockStatus::Queued); + } + + chain.block_status(&BlockId::Hash(hash)) +} diff --git a/substrate/network/src/test/consensus.rs b/substrate/network/src/test/consensus.rs deleted file mode 100644 index 56bb6510552fc..0000000000000 --- a/substrate/network/src/test/consensus.rs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -use super::*; -use message::{Message, generic}; -use futures::Stream; -use test_client::runtime::Block; - -#[test] -fn bft_messages_include_those_sent_before_asking_for_stream() { - let mut config = ::config::ProtocolConfig::default(); - config.roles = ::service::Role::VALIDATOR | ::service::Role::FULL; - - let mut net = TestNet::new_with_config(2, config); - net.sync(); // necessary for handshaking - - let peer = net.peer(0); - let mut io = TestIo::new(&peer.queue, None); - let bft_message = generic::BftMessage::Consensus(generic::SignedConsensusMessage::Vote(generic::SignedConsensusVote { - vote: generic::ConsensusVote::AdvanceRound(0), - sender: [0; 32], - signature: Default::default(), - })); - - let parent_hash = peer.genesis_hash(); - - let localized = ::message::LocalizedBftMessage:: { - message: bft_message, - parent_hash: parent_hash, - }; - - let message: Message = generic::Message::BftMessage(localized.clone()); - - let as_bytes = ::serde_json::to_vec(&message).unwrap(); - peer.sync.handle_packet(&mut io, 1, &as_bytes[..]); - - let stream = peer.sync.bft_messages(parent_hash); - - assert_eq!(stream.wait().next(), Some(Ok(localized))); -} diff --git a/substrate/network/src/test/mod.rs b/substrate/network/src/test/mod.rs index 104bb8b9814cf..5a8d82d448398 100644 --- a/substrate/network/src/test/mod.rs +++ b/substrate/network/src/test/mod.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -mod consensus; mod sync; use std::collections::{VecDeque, HashSet, HashMap}; @@ -26,28 +25,48 @@ use client::block_builder::BlockBuilder; use runtime_primitives::traits::Block as BlockT; use runtime_primitives::generic::BlockId; use io::SyncIo; -use protocol::Protocol; +use protocol::{Context, Protocol}; use config::ProtocolConfig; use service::TransactionPool; -use network::{PeerId, SessionInfo, Error as NetworkError}; +use network_libp2p::{NodeIndex, SessionInfo, Severity}; use keyring::Keyring; -use codec::Slicable; +use codec::Encode; +use import_queue::tests::SyncImportQueue; use test_client::{self, TestClient}; use test_client::runtime::{Block, Hash, Transfer, Extrinsic}; +use specialization::Specialization; + +pub struct DummySpecialization; + +impl Specialization for DummySpecialization { + fn status(&self) -> Vec { vec![] } + + fn on_connect(&mut self, _ctx: &mut Context, _peer_id: NodeIndex, _status: ::message::Status) { + + } + + fn on_disconnect(&mut self, _ctx: &mut Context, _peer_id: NodeIndex) { + + } + + fn on_message(&mut self, _ctx: &mut Context, _peer_id: NodeIndex, _message: ::message::Message) { + + } +} pub struct TestIo<'p> { - pub queue: &'p RwLock>, - pub sender: Option, - pub to_disconnect: HashSet, - pub packets: Vec, - pub peers_info: HashMap, + queue: &'p RwLock>, + pub to_disconnect: HashSet, + packets: Vec, + peers_info: HashMap, + _sender: Option, } impl<'p> TestIo<'p> where { - pub fn new(queue: &'p RwLock>, sender: Option) -> TestIo<'p> { + pub fn new(queue: &'p RwLock>, sender: Option) -> TestIo<'p> { TestIo { queue: queue, - sender: sender, + _sender: sender, to_disconnect: HashSet::new(), packets: Vec::new(), peers_info: HashMap::new(), @@ -62,46 +81,41 @@ impl<'p> Drop for TestIo<'p> { } impl<'p> SyncIo for TestIo<'p> { - fn disable_peer(&mut self, peer_id: PeerId) { - self.disconnect_peer(peer_id); - } - - fn disconnect_peer(&mut self, peer_id: PeerId) { - self.to_disconnect.insert(peer_id); + fn report_peer(&mut self, who: NodeIndex, _reason: Severity) { + self.to_disconnect.insert(who); } fn is_expired(&self) -> bool { false } - fn send(&mut self, peer_id: PeerId, data: Vec) -> Result<(), NetworkError> { + fn send(&mut self, who: NodeIndex, data: Vec) { self.packets.push(TestPacket { data: data, - recipient: peer_id, + recipient: who, }); - Ok(()) } - fn peer_info(&self, peer_id: PeerId) -> String { - self.peers_info.get(&peer_id) + fn peer_info(&self, who: NodeIndex) -> String { + self.peers_info.get(&who) .cloned() - .unwrap_or_else(|| peer_id.to_string()) + .unwrap_or_else(|| who.to_string()) } - fn peer_session_info(&self, _peer_id: PeerId) -> Option { + fn peer_session_info(&self, _peer_id: NodeIndex) -> Option { None } } /// Mocked subprotocol packet pub struct TestPacket { - pub data: Vec, - pub recipient: PeerId, + data: Vec, + recipient: NodeIndex, } pub struct Peer { client: Arc>, - pub sync: Protocol, + pub sync: Protocol, pub queue: RwLock>, } @@ -115,18 +129,18 @@ impl Peer { } /// Called on connection to other indicated peer. - fn on_connect(&self, other: PeerId) { + fn on_connect(&self, other: NodeIndex) { self.sync.on_peer_connected(&mut TestIo::new(&self.queue, Some(other)), other); } /// Called on disconnect from other indicated peer. - fn on_disconnect(&self, other: PeerId) { + fn on_disconnect(&self, other: NodeIndex) { let mut io = TestIo::new(&self.queue, Some(other)); self.sync.on_peer_disconnected(&mut io, other); } /// Receive a message from another peer. Return a set of peers to disconnect. - fn receive_message(&self, from: PeerId, msg: TestPacket) -> HashSet { + fn receive_message(&self, from: NodeIndex, msg: TestPacket) -> HashSet { let mut io = TestIo::new(&self.queue, Some(from)); self.sync.handle_packet(&mut io, from, &msg.data); self.flush(); @@ -186,14 +200,9 @@ impl Peer { self.generate_blocks(count, |_| ()); } } - - pub fn genesis_hash(&self) -> Hash { - let info = self.client.info().expect("In-mem client does not fail"); - info.chain.genesis_hash - } } -struct EmptyTransactionPool; +pub struct EmptyTransactionPool; impl TransactionPool for EmptyTransactionPool { fn transactions(&self) -> Vec<(Hash, Extrinsic)> { @@ -208,17 +217,17 @@ impl TransactionPool for EmptyTransactionPool { } pub struct TestNet { - pub peers: Vec>, - pub started: bool, - pub disconnect_events: Vec<(PeerId, PeerId)>, //disconnected (initiated by, to) + peers: Vec>, + started: bool, + disconnect_events: Vec<(NodeIndex, NodeIndex)>, //disconnected (initiated by, to) } impl TestNet { - pub fn new(n: usize) -> Self { + fn new(n: usize) -> Self { Self::new_with_config(n, ProtocolConfig::default()) } - pub fn new_with_config(n: usize, config: ProtocolConfig) -> Self { + fn new_with_config(n: usize, config: ProtocolConfig) -> Self { let mut net = TestNet { peers: Vec::new(), started: false, @@ -234,7 +243,8 @@ impl TestNet { pub fn add_peer(&mut self, config: &ProtocolConfig) { let client = Arc::new(test_client::new()); let tx_pool = Arc::new(EmptyTransactionPool); - let sync = Protocol::new(config.clone(), client.clone(), None, tx_pool).unwrap(); + let import_queue = Arc::new(SyncImportQueue); + let sync = Protocol::new(config.clone(), client.clone(), import_queue, None, tx_pool, DummySpecialization).unwrap(); self.peers.push(Arc::new(Peer { sync: sync, client: client, @@ -246,7 +256,7 @@ impl TestNet { &self.peers[i] } - pub fn start(&mut self) { + fn start(&mut self) { if self.started { return; } @@ -254,31 +264,31 @@ impl TestNet { self.peers[peer].start(); for client in 0..self.peers.len() { if peer != client { - self.peers[peer].on_connect(client as PeerId); + self.peers[peer].on_connect(client as NodeIndex); } } } self.started = true; } - pub fn sync_step(&mut self) { + fn sync_step(&mut self) { for peer in 0..self.peers.len() { let packet = self.peers[peer].pending_message(); if let Some(packet) = packet { let disconnecting = { let recipient = packet.recipient; trace!("--- {} -> {} ---", peer, recipient); - let to_disconnect = self.peers[recipient].receive_message(peer as PeerId, packet); + let to_disconnect = self.peers[recipient].receive_message(peer as NodeIndex, packet); for d in &to_disconnect { // notify this that disconnecting peers are disconnecting - self.peers[recipient].on_disconnect(*d as PeerId); + self.peers[recipient].on_disconnect(*d as NodeIndex); self.disconnect_events.push((peer, *d)); } to_disconnect }; for d in &disconnecting { // notify other peers that this peer is disconnecting - self.peers[*d].on_disconnect(peer as PeerId); + self.peers[*d].on_disconnect(peer as NodeIndex); } } @@ -286,15 +296,15 @@ impl TestNet { } } - pub fn sync_step_peer(&mut self, peer_num: usize) { + fn sync_step_peer(&mut self, peer_num: usize) { self.peers[peer_num].sync_step(); } - pub fn restart_peer(&mut self, i: usize) { + fn restart_peer(&mut self, i: usize) { self.peers[i].restart_sync(); } - pub fn sync(&mut self) -> u32 { + fn sync(&mut self) -> u32 { self.start(); let mut total_steps = 0; while !self.done() { @@ -304,14 +314,14 @@ impl TestNet { total_steps } - pub fn sync_steps(&mut self, count: usize) { + fn sync_steps(&mut self, count: usize) { self.start(); for _ in 0..count { self.sync_step(); } } - pub fn done(&self) -> bool { + fn done(&self) -> bool { self.peers.iter().all(|p| p.is_done()) } } diff --git a/substrate/network/src/test/sync.rs b/substrate/network/src/test/sync.rs index dfab41a5e1030..7297c239f3968 100644 --- a/substrate/network/src/test/sync.rs +++ b/substrate/network/src/test/sync.rs @@ -15,13 +15,12 @@ // along with Polkadot. If not, see . use client::backend::Backend; -use client::blockchain::Backend as BlockchainBackend; +use client::blockchain::HeaderBackend as BlockchainHeaderBackend; use sync::SyncState; -use {Role}; +use Roles; use super::*; #[test] -#[ignore] fn sync_from_two_peers_works() { ::env_logger::init().ok(); let mut net = TestNet::new(3); @@ -34,7 +33,6 @@ fn sync_from_two_peers_works() { } #[test] -#[ignore] fn sync_from_two_peers_with_ancestry_search_works() { ::env_logger::init().ok(); let mut net = TestNet::new(3); @@ -47,7 +45,6 @@ fn sync_from_two_peers_with_ancestry_search_works() { } #[test] -#[ignore] fn sync_long_chain_works() { let mut net = TestNet::new(2); net.peer(1).push_blocks(500, false); @@ -68,7 +65,6 @@ fn sync_no_common_longer_chain_fails() { } #[test] -#[ignore] fn sync_after_fork_works() { ::env_logger::init().ok(); let mut net = TestNet::new(3); @@ -99,7 +95,7 @@ fn blocks_are_not_announced_by_light_nodes() { // full peer0 is connected to light peer // light peer1 is connected to full peer2 let mut light_config = ProtocolConfig::default(); - light_config.roles = Role::LIGHT; + light_config.roles = Roles::LIGHT; net.add_peer(&ProtocolConfig::default()); net.add_peer(&light_config); net.add_peer(&ProtocolConfig::default()); diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml index f5c8eb1d95eee..9d844a938b554 100644 --- a/substrate/primitives/Cargo.toml +++ b/substrate/primitives/Cargo.toml @@ -15,7 +15,7 @@ uint = { git = "https://github.com/rphmeier/primitives.git", branch = "compile-f twox-hash = { version = "1.1.0", optional = true } byteorder = { version = "1.1", default_features = false } blake2-rfc = { version = "0.2.18", optional = true } -wasmi = { version = "0.1", optional = true } +wasmi = { version = "0.3", optional = true } [dev-dependencies] substrate-serializer = { path = "../serializer" } diff --git a/substrate/primitives/src/authority_id.rs b/substrate/primitives/src/authority_id.rs new file mode 100644 index 0000000000000..f7bf815b515ef --- /dev/null +++ b/substrate/primitives/src/authority_id.rs @@ -0,0 +1,120 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + + +#[cfg(feature = "std")] +use serde::{Serialize, Serializer, Deserialize, Deserializer}; +use codec; +use H256; + +/// An identifier for an authority in the consensus algorithm. The same size as ed25519::Public. +#[derive(Clone, Copy, PartialEq, Eq, Default)] +pub struct AuthorityId(pub [u8; 32]); + +impl AuthorityId { + /// Create an id from a 32-byte slice. Panics with other lengths. + #[cfg(feature = "std")] + fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 32]; + r.copy_from_slice(data); + AuthorityId(r) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Display for AuthorityId { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", ::hexdisplay::HexDisplay::from(&self.0)) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Debug for AuthorityId { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", ::hexdisplay::HexDisplay::from(&self.0)) + } +} + +#[cfg(feature = "std")] +impl ::std::hash::Hash for AuthorityId { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} + +impl AsRef<[u8; 32]> for AuthorityId { + fn as_ref(&self) -> &[u8; 32] { + &self.0 + } +} + +impl AsRef<[u8]> for AuthorityId { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + +impl Into<[u8; 32]> for AuthorityId { + fn into(self) -> [u8; 32] { + self.0 + } +} + +impl From<[u8; 32]> for AuthorityId { + fn from(a: [u8; 32]) -> Self { + AuthorityId(a) + } +} + +impl AsRef for AuthorityId { + fn as_ref(&self) -> &AuthorityId { + &self + } +} + +impl Into for AuthorityId { + fn into(self) -> H256 { + self.0.into() + } +} + +#[cfg(feature = "std")] +impl Serialize for AuthorityId { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + ::bytes::serialize(&self.0, serializer) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for AuthorityId { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + ::bytes::deserialize_check_len(deserializer, ::bytes::ExpectedLen::Exact(32)) + .map(|x| AuthorityId::from_slice(&x)) + } +} + +impl codec::Encode for AuthorityId { + fn using_encoded R>(&self, f: F) -> R { + self.0.using_encoded(f) + } +} + +impl codec::Decode for AuthorityId { + fn decode(input: &mut I) -> Option { + <[u8; 32] as codec::Decode>::decode(input).map(AuthorityId) + } +} + diff --git a/substrate/primitives/src/bytes.rs b/substrate/primitives/src/bytes.rs index a8dc902310c5d..c7e5b9817f9f9 100644 --- a/substrate/primitives/src/bytes.rs +++ b/substrate/primitives/src/bytes.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! Simply type for representing Vec with regards to serde. +//! Simple type for representing Vec with regards to serde. use core::fmt; diff --git a/substrate/primitives/src/hash.rs b/substrate/primitives/src/hash.rs index 8556f649bba67..a0dc5f4c1cc75 100644 --- a/substrate/primitives/src/hash.rs +++ b/substrate/primitives/src/hash.rs @@ -39,15 +39,16 @@ macro_rules! impl_rest { } } - impl ::codec::Slicable for $name { - fn decode(input: &mut I) -> Option { - <[u8; $len] as ::codec::Slicable>::decode(input).map($name) - } - + impl ::codec::Encode for $name { fn using_encoded R>(&self, f: F) -> R { self.0.using_encoded(f) } } + impl ::codec::Decode for $name { + fn decode(input: &mut I) -> Option { + <[u8; $len] as ::codec::Decode>::decode(input).map($name) + } + } } } diff --git a/substrate/primitives/src/hexdisplay.rs b/substrate/primitives/src/hexdisplay.rs index 42db2212870f0..b1746727aed04 100644 --- a/substrate/primitives/src/hexdisplay.rs +++ b/substrate/primitives/src/hexdisplay.rs @@ -26,8 +26,18 @@ impl<'a> HexDisplay<'a> { impl<'a> ::core::fmt::Display for HexDisplay<'a> { fn fmt(&self, fmtr: &mut ::core::fmt::Formatter) -> Result<(), ::core::fmt::Error> { - for byte in self.0 { - try!( fmtr.write_fmt(format_args!("{:02x}", byte))); + if self.0.len() < 1027 { + for byte in self.0 { + fmtr.write_fmt(format_args!("{:02x}", byte))?; + } + } else { + for byte in &self.0[0..512] { + fmtr.write_fmt(format_args!("{:02x}", byte))?; + } + fmtr.write_str("...")?; + for byte in &self.0[self.0.len() - 512..] { + fmtr.write_fmt(format_args!("{:02x}", byte))?; + } } Ok(()) } @@ -62,3 +72,23 @@ macro_rules! impl_non_endians { impl_non_endians!([u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], [u8; 10], [u8; 12], [u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40], [u8; 48], [u8; 56], [u8; 64], [u8; 80], [u8; 96], [u8; 112], [u8; 128]); + +/// Format into ASCII + # + hex, suitable for storage key preimages. +pub fn ascii_format(asciish: &[u8]) -> String { + let mut r = String::new(); + let mut latch = false; + for c in asciish { + match (latch, *c) { + (false, 32...127) => r.push(*c as char), + _ => { + if !latch { + r.push('#'); + latch = true; + } + r.push_str(&format!("{:02x}", *c)); + } + } + } + r +} + diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index 68306b01e80c0..322590a0bf713 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -61,6 +61,8 @@ macro_rules! map { ) } +use rstd::prelude::*; +use rstd::ops::Deref; #[cfg(feature = "std")] pub mod bytes; @@ -75,15 +77,28 @@ pub mod hash; pub mod sandbox; pub mod storage; pub mod uint; +mod authority_id; #[cfg(test)] mod tests; pub use self::hash::{H160, H256, H512}; pub use self::uint::{U256, U512}; - -/// An identifier for an authority in the consensus algorithm. The same as ed25519::Public. -pub type AuthorityId = [u8; 32]; +pub use authority_id::AuthorityId; /// A 512-bit value interpreted as a signature. pub type Signature = hash::H512; + +/// Hex-serialised shim for `Vec`. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Hash, PartialOrd, Ord))] +pub struct Bytes(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); + +impl From> for Bytes { + fn from(s: Vec) -> Self { Bytes(s) } +} + +impl Deref for Bytes { + type Target = [u8]; + fn deref(&self) -> &[u8] { &self.0[..] } +} diff --git a/substrate/primitives/src/sandbox.rs b/substrate/primitives/src/sandbox.rs index 3fc8abc302c4c..b7e9d0cd62ba2 100644 --- a/substrate/primitives/src/sandbox.rs +++ b/substrate/primitives/src/sandbox.rs @@ -16,18 +16,14 @@ //! Definition of a sandbox environment. -use codec::{Slicable, Input}; +use codec::{Encode, Decode, Input, Output}; use rstd::vec::Vec; /// Error error that can be returned from host function. #[cfg_attr(feature = "std", derive(Debug))] pub struct HostError; -impl Slicable for HostError { - fn decode(_: &mut I) -> Option { - Some(HostError) - } - +impl Encode for HostError { fn using_encoded R>(&self, f: F) -> R { f(&[]) } @@ -37,6 +33,12 @@ impl Slicable for HostError { } } +impl Decode for HostError { + fn decode(_: &mut I) -> Option { + Some(HostError) + } +} + #[derive(Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug))] #[repr(i8)] @@ -91,40 +93,40 @@ impl From<::wasmi::RuntimeValue> for TypedValue { impl From for ::wasmi::RuntimeValue { fn from(val: TypedValue) -> ::wasmi::RuntimeValue { use ::wasmi::RuntimeValue; + use ::wasmi::nan_preserving_float::{F32, F64}; match val { TypedValue::I32(v) => RuntimeValue::I32(v), TypedValue::I64(v) => RuntimeValue::I64(v), - TypedValue::F32(v_bits) => RuntimeValue::F32(f32::from_bits(v_bits as u32)), - TypedValue::F64(v_bits) => RuntimeValue::F64(f64::from_bits(v_bits as u64)), + TypedValue::F32(v_bits) => RuntimeValue::F32(F32::from_bits(v_bits as u32)), + TypedValue::F64(v_bits) => RuntimeValue::F64(F64::from_bits(v_bits as u64)), } } } -impl Slicable for TypedValue { - fn encode(&self) -> Vec { - let mut v = Vec::new(); +impl Encode for TypedValue { + fn encode_to(&self, dest: &mut T) { match *self { TypedValue::I32(i) => { - v.push(ValueType::I32 as u8); - i.using_encoded(|s| v.extend(s)); + dest.push_byte(ValueType::I32 as u8); + dest.push(&i); } TypedValue::I64(i) => { - v.push(ValueType::I64 as u8); - i.using_encoded(|s| v.extend(s)); + dest.push_byte(ValueType::I64 as u8); + dest.push(&i); } TypedValue::F32(f_bits) => { - v.push(ValueType::F32 as u8); - f_bits.using_encoded(|s| v.extend(s)); + dest.push_byte(ValueType::F32 as u8); + dest.push(&f_bits); } TypedValue::F64(f_bits) => { - v.push(ValueType::F64 as u8); - f_bits.using_encoded(|s| v.extend(s)); + dest.push_byte(ValueType::F64 as u8); + dest.push(&f_bits); } } - - v } +} +impl Decode for TypedValue { fn decode(value: &mut I) -> Option { let typed_value = match i8::decode(value) { Some(x) if x == ValueType::I32 as i8 => TypedValue::I32(i32::decode(value)?), @@ -156,21 +158,21 @@ impl From for ReturnValue { } } -impl Slicable for ReturnValue { - fn encode(&self) -> Vec { - let mut v = Vec::new(); +impl Encode for ReturnValue { + fn encode_to(&self, dest: &mut T) { match *self { ReturnValue::Unit => { - v.push(0); + dest.push_byte(0); } ReturnValue::Value(ref val) => { - v.push(1); - val.using_encoded(|s| v.extend(s)); + dest.push_byte(1); + dest.push(val); } } - v } +} +impl Decode for ReturnValue { fn decode(value: &mut I) -> Option { match i8::decode(value) { Some(0) => Some(ReturnValue::Unit), @@ -182,7 +184,7 @@ impl Slicable for ReturnValue { impl ReturnValue { /// Maximum number of bytes `ReturnValue` might occupy when serialized with - /// `Slicable`. + /// `Codec`. /// /// Breakdown: /// 1 byte for encoding unit/value variant @@ -218,23 +220,22 @@ pub enum ExternEntity { Memory(u32), } -impl Slicable for ExternEntity { - fn encode(&self) -> Vec { - let mut v = Vec::new(); +impl Encode for ExternEntity { + fn encode_to(&self, dest: &mut T) { match *self { ExternEntity::Function(ref index) => { - v.push(ExternEntityKind::Function as u8); - index.using_encoded(|s| v.extend(s)); + dest.push_byte(ExternEntityKind::Function as u8); + dest.push(index); } ExternEntity::Memory(ref mem_id) => { - v.push(ExternEntityKind::Memory as u8); - mem_id.using_encoded(|s| v.extend(s)); + dest.push_byte(ExternEntityKind::Memory as u8); + dest.push(mem_id); } } - - v } +} +impl Decode for ExternEntity { fn decode(value: &mut I) -> Option { match i8::decode(value) { Some(x) if x == ExternEntityKind::Function as i8 => { @@ -265,16 +266,15 @@ pub struct Entry { pub entity: ExternEntity, } -impl Slicable for Entry { - fn encode(&self) -> Vec { - let mut v = Vec::new(); - self.module_name.using_encoded(|s| v.extend(s)); - self.field_name.using_encoded(|s| v.extend(s)); - self.entity.using_encoded(|s| v.extend(s)); - - v +impl Encode for Entry { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.module_name); + dest.push(&self.field_name); + dest.push(&self.entity); } +} +impl Decode for Entry { fn decode(value: &mut I) -> Option { let module_name = Vec::decode(value)?; let field_name = Vec::decode(value)?; @@ -296,11 +296,13 @@ pub struct EnvironmentDefinition { pub entries: Vec, } -impl Slicable for EnvironmentDefinition { - fn encode(&self) -> Vec { - self.entries.encode() +impl Encode for EnvironmentDefinition { + fn encode_to(&self, dest: &mut T) { + self.entries.encode_to(dest) } +} +impl Decode for EnvironmentDefinition { fn decode(value: &mut I) -> Option { let entries = Vec::decode(value)?; @@ -339,8 +341,9 @@ pub const ERR_EXECUTION: u32 = -3i32 as u32; mod tests { use super::*; use std::fmt; + use codec::Codec; - fn roundtrip(s: S) { + fn roundtrip(s: S) { let encoded = s.encode(); assert_eq!(S::decode(&mut &encoded[..]).unwrap(), s); } diff --git a/substrate/rpc-servers/src/lib.rs b/substrate/rpc-servers/src/lib.rs index ec3d2d6fdd98a..006345e68e335 100644 --- a/substrate/rpc-servers/src/lib.rs +++ b/substrate/rpc-servers/src/lib.rs @@ -34,6 +34,8 @@ use substrate_runtime_primitives::traits::Block as BlockT; type Metadata = apis::metadata::Metadata; type RpcHandler = pubsub::PubSubHandler; +pub type HttpServer = http::Server; +pub type WsServer = ws::Server; /// Construct rpc `IoHandler` pub fn rpc_handler( @@ -45,7 +47,7 @@ pub fn rpc_handler( Block: 'static, S: apis::state::StateApi, C: apis::chain::ChainApi, - A: apis::author::AuthorApi, + A: apis::author::AuthorApi, Y: apis::system::SystemApi, { let mut io = pubsub::PubSubHandler::default(); diff --git a/substrate/rpc/Cargo.toml b/substrate/rpc/Cargo.toml index 45bddecdfdf5d..fb73d9ef653f7 100644 --- a/substrate/rpc/Cargo.toml +++ b/substrate/rpc/Cargo.toml @@ -4,19 +4,20 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] -error-chain = "0.11" +error-chain = "0.12" jsonrpc-core = { git="https://github.com/paritytech/jsonrpc.git" } jsonrpc-macros = { git="https://github.com/paritytech/jsonrpc.git" } jsonrpc-pubsub = { git="https://github.com/paritytech/jsonrpc.git" } log = "0.3" parking_lot = "0.4" +substrate-codec = { path = "../codec" } substrate-client = { path = "../client" } substrate-executor = { path = "../executor" } substrate-extrinsic-pool = { path = "../extrinsic-pool" } substrate-primitives = { path = "../primitives" } substrate-runtime-primitives = { path = "../runtime/primitives" } substrate-state-machine = { path = "../state-machine" } -tokio-core = "0.1.12" +tokio = "0.1.7" [dev-dependencies] assert_matches = "1.1" diff --git a/substrate/rpc/src/author/error.rs b/substrate/rpc/src/author/error.rs index 5f7b9a82b282a..ce82ec2925055 100644 --- a/substrate/rpc/src/author/error.rs +++ b/substrate/rpc/src/author/error.rs @@ -16,12 +16,17 @@ //! Authoring RPC module errors. +use client; use extrinsic_pool::txpool; use rpc; +use errors; + + error_chain! { links { Pool(txpool::Error, txpool::ErrorKind) #[doc = "Pool error"]; + Client(client::error::Error, client::error::ErrorKind) #[doc = "Client error"]; } errors { /// Not implemented yet @@ -29,6 +34,11 @@ error_chain! { description("not yet implemented"), display("Method Not Implemented"), } + /// Incorrect extrinsic format. + BadFormat { + description("bad format"), + display("Invalid extrinsic format"), + } /// Verification error Verification(e: Box<::std::error::Error + Send>) { description("extrinsic verification error"), @@ -37,16 +47,23 @@ error_chain! { } } +const ERROR: i64 = 1000; + impl From for rpc::Error { fn from(e: Error) -> Self { match e { - Error(ErrorKind::Unimplemented, _) => rpc::Error { - code: rpc::ErrorCode::ServerError(-1), - message: "Not implemented yet".into(), + Error(ErrorKind::Unimplemented, _) => errors::unimplemented(), + Error(ErrorKind::BadFormat, _) => rpc::Error { + code: rpc::ErrorCode::ServerError(ERROR + 1), + message: "Extrinsic has invalid format.".into(), data: None, }, - // TODO [ToDr] Unwrap Pool errors. - _ => rpc::Error::internal_error(), + Error(ErrorKind::Verification(e), _) => rpc::Error { + code: rpc::ErrorCode::ServerError(ERROR + 2), + message: e.description().into(), + data: Some(format!("{:?}", e).into()), + }, + e => errors::internal(e), } } } diff --git a/substrate/rpc/src/author/mod.rs b/substrate/rpc/src/author/mod.rs index 4ed850db55837..9077abdc3ffd8 100644 --- a/substrate/rpc/src/author/mod.rs +++ b/substrate/rpc/src/author/mod.rs @@ -17,7 +17,20 @@ //! Substrate block-author/full-node API. use std::sync::Arc; -use extrinsic_pool::api::{Error, ExtrinsicPool}; + +use client::{self, Client}; +use codec::Codec; +use extrinsic_pool::{ + api::{Error, ExtrinsicPool}, + watcher::Status, +}; +use jsonrpc_macros::pubsub; +use jsonrpc_pubsub::SubscriptionId; +use primitives::Bytes; +use rpc::futures::{Sink, Stream, Future}; +use runtime_primitives::{generic, traits}; +use subscriptions::Subscriptions; +use tokio::runtime::TaskExecutor; pub mod error; @@ -29,23 +42,107 @@ use self::error::Result; build_rpc_trait! { /// Substrate authoring RPC API pub trait AuthorApi { + type Metadata; + /// Submit extrinsic for inclusion in block. + #[rpc(name = "author_submitRichExtrinsic")] + fn submit_rich_extrinsic(&self, Extrinsic) -> Result; + /// Submit hex-encoded extrinsic for inclusion in block. #[rpc(name = "author_submitExtrinsic")] - fn submit_extrinsic(&self, Extrinsic) -> Result; + fn submit_extrinsic(&self, Bytes) -> Result; + + #[pubsub(name = "author_extrinsicUpdate")] { + /// Submit an extrinsic to watch. + #[rpc(name = "author_submitAndWatchExtrinsic")] + fn watch_extrinsic(&self, Self::Metadata, pubsub::Subscriber>, Bytes); + + /// Unsubscribe from extrinsic watching. + #[rpc(name = "author_unwatchExtrinsic")] + fn unwatch_extrinsic(&self, SubscriptionId) -> Result; + } + + } +} + +/// Authoring API +pub struct Author { + /// Substrate client + client: Arc>, + /// Extrinsic pool + pool: Arc

, + /// Subscriptions manager + subscriptions: Subscriptions, +} + +impl Author { + /// Create new instance of Authoring API. + pub fn new(client: Arc>, pool: Arc

::Hash; @@ -147,24 +154,25 @@ impl(pub (u64, u64, Call)); +pub struct TestXt(pub (u64, u64, Call)); -impl Slicable for TestXt { +impl Decode for TestXt { fn decode(input: &mut I) -> Option { - Some(TestXt(Slicable::decode(input)?)) + Some(TestXt(Decode::decode(input)?)) } - fn encode(&self) -> Vec { - self.0.encode() +} + +impl Encode for TestXt { + fn encode_to(&self, dest: &mut T) { + self.0.encode_to(dest) } } -impl Checkable for TestXt { + +impl Checkable for TestXt { type Checked = Self; - type Address = u64; - type AccountId = u64; - fn sender(&self) -> &u64 { &(self.0).0 } - fn check Result + Send + Sync>(self, _lookup: ThisLookup) -> Result { Ok(self) } + fn check_with(self, _: Context) -> Result { Ok(self) } } -impl + Slicable + Sized + Send + Sync + Serialize + DeserializeOwned + Clone + Eq + Debug> Applyable for TestXt { +impl + Codec + Sized + Send + Sync + Serialize + DeserializeOwned + Clone + Eq + Debug> Applyable for TestXt { type AccountId = u64; type Index = u64; fn sender(&self) -> &u64 { &(self.0).0 } diff --git a/substrate/runtime/primitives/src/traits.rs b/substrate/runtime/primitives/src/traits.rs index c204b5ebda049..3c89087d70dc3 100644 --- a/substrate/runtime/primitives/src/traits.rs +++ b/substrate/runtime/primitives/src/traits.rs @@ -22,9 +22,10 @@ use runtime_io; #[cfg(feature = "std")] use std::fmt::{Debug, Display}; #[cfg(feature = "std")] use serde::{Serialize, de::DeserializeOwned}; use substrate_primitives; -use codec::Slicable; +use codec::{Codec, Encode}; pub use integer_sqrt::IntegerSquareRoot; pub use num_traits::{Zero, One, Bounded}; +pub use num_traits::ops::checked::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv}; use rstd::ops::{Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; /// A lazy value. @@ -32,11 +33,15 @@ pub trait Lazy { fn get(&mut self) -> &T; } +impl<'a> Lazy<[u8]> for &'a [u8] { + fn get(&mut self) -> &[u8] { &**self } +} + /// Means of signature verification. pub trait Verify { /// Type of the signer. type Signer; - /// Verify a signature. + /// Verify a signature. Return `true` if signature is valid for the value. fn verify>(&self, msg: L, signer: &Self::Signer) -> bool; } @@ -121,21 +126,29 @@ impl RefInto for T { } pub trait SimpleArithmetic: - Zero + One + IntegerSquareRoot + As + + Zero + One + IntegerSquareRoot + As + Add + AddAssign + Sub + SubAssign + Mul + MulAssign + Div + DivAssign + Rem + RemAssign + + CheckedAdd + + CheckedSub + + CheckedMul + + CheckedDiv + PartialOrd + Ord {} impl + + Zero + One + IntegerSquareRoot + As + Add + AddAssign + Sub + SubAssign + Mul + MulAssign + Div + DivAssign + Rem + RemAssign + + CheckedAdd + + CheckedSub + + CheckedMul + + CheckedDiv + PartialOrd + Ord > SimpleArithmetic for T {} @@ -181,7 +194,7 @@ impl Executable for (A, B) { } /// Abstraction around hashing -pub trait Hashing: 'static + MaybeSerializeDebug + Clone + Eq + PartialEq { // Stupid bug in the Rust compiler believes derived +pub trait Hash: 'static + MaybeSerializeDebug + Clone + Eq + PartialEq { // Stupid bug in the Rust compiler believes derived // traits must be fulfilled by all type parameters. /// The hash type produced. type Output: Member + AsRef<[u8]>; @@ -190,8 +203,8 @@ pub trait Hashing: 'static + MaybeSerializeDebug + Clone + Eq + PartialEq { // S fn hash(s: &[u8]) -> Self::Output; /// Produce the hash of some codec-encodable value. - fn hash_of(s: &S) -> Self::Output { - Slicable::using_encoded(s, Self::hash) + fn hash_of(s: &S) -> Self::Output { + Encode::using_encoded(s, Self::hash) } /// Produce the patricia-trie root of a mapping from indices to byte slices. @@ -214,12 +227,12 @@ pub trait Hashing: 'static + MaybeSerializeDebug + Clone + Eq + PartialEq { // S fn storage_root() -> Self::Output; } -/// Blake2-256 Hashing implementation. +/// Blake2-256 Hash implementation. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] pub struct BlakeTwo256; -impl Hashing for BlakeTwo256 { +impl Hash for BlakeTwo256 { type Output = substrate_primitives::H256; fn hash(s: &[u8]) -> Self::Output { runtime_io::blake2_256(s).into() @@ -303,7 +316,7 @@ pub trait Member: Send + Sync + Sized + MaybeSerializeDebug + Eq + PartialEq + C impl Member for T {} /// Something that acts like a `Digest` - it can have `Log`s `push`ed onto it and these `Log`s are -/// each `Slicable`. +/// each `Codec`. pub trait Digest { type Item: Member; fn push(&mut self, item: Self::Item); @@ -314,10 +327,10 @@ pub trait Digest { /// `parent_hash`, as well as a `digest` and a block `number`. /// /// You can also create a `new` one from those fields. -pub trait Header: Clone + Send + Sync + Slicable + Eq + MaybeSerializeDebug { - type Number: Member + ::rstd::hash::Hash + Copy + MaybeDisplay + SimpleArithmetic + Slicable; - type Hash: Member + ::rstd::hash::Hash + Copy + MaybeDisplay + Default + SimpleBitOps + Slicable + AsRef<[u8]>; - type Hashing: Hashing; +pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebug + 'static { + type Number: Member + ::rstd::hash::Hash + Copy + MaybeDisplay + SimpleArithmetic + Codec; + type Hash: Member + ::rstd::hash::Hash + Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]>; + type Hashing: Hash; type Digest: Member + Default; fn new( @@ -344,7 +357,7 @@ pub trait Header: Clone + Send + Sync + Slicable + Eq + MaybeSerializeDebug { fn set_digest(&mut self, Self::Digest); fn hash(&self) -> Self::Hash { - ::hash_of(self) + ::hash_of(self) } } @@ -352,50 +365,53 @@ pub trait Header: Clone + Send + Sync + Slicable + Eq + MaybeSerializeDebug { /// `Extrinsic` piece of information as well as a `Header`. /// /// You can get an iterator over each of the `extrinsics` and retrieve the `header`. -pub trait Block: Clone + Send + Sync + Slicable + Eq + MaybeSerializeDebug { - type Extrinsic: Member + Slicable; +pub trait Block: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebug + 'static { + type Extrinsic: Member + Codec; type Header: Header; - type Hash: Member + ::rstd::hash::Hash + Copy + MaybeDisplay + Default + SimpleBitOps + Slicable + AsRef<[u8]>; + type Hash: Member + ::rstd::hash::Hash + Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]>; fn header(&self) -> &Self::Header; fn extrinsics(&self) -> &[Self::Extrinsic]; fn deconstruct(self) -> (Self::Header, Vec); fn new(header: Self::Header, extrinsics: Vec) -> Self; fn hash(&self) -> Self::Hash { - <::Hashing as Hashing>::hash_of(self.header()) + <::Hashing as Hash>::hash_of(self.header()) } } /// Extract the hashing type for a block. -pub type HashingFor = <::Header as Header>::Hashing; +pub type HashFor = <::Header as Header>::Hashing; +/// Extract the number type for a block. +pub type NumberFor = <::Header as Header>::Number; /// A "checkable" piece of information, used by the standard Substrate Executive in order to /// check the validity of a piece of extrinsic information, usually by verifying the signature. -pub trait Checkable: Sized + Send + Sync { - type Address: Member + MaybeDisplay; - type AccountId: Member + MaybeDisplay; - type Checked: Member; - fn sender(&self) -> &Self::Address; - fn check Result + Send + Sync>(self, lookup: ThisLookup) -> Result; +/// Implement for pieces of information that require some additional context `Context` in order to be +/// checked. +pub trait Checkable: Sized { + /// Returned if `check_with` succeeds. + type Checked; + + fn check_with(self, context: Context) -> Result; } /// A "checkable" piece of information, used by the standard Substrate Executive in order to /// check the validity of a piece of extrinsic information, usually by verifying the signature. -/// -/// This does that checking without requiring a lookup argument. -pub trait BlindCheckable: Sized + Send + Sync { - type Address: Member + MaybeDisplay; - type Checked: Member; - fn sender(&self) -> &Self::Address; +/// Implement for pieces of information that don't require additional context in order to be +/// checked. +pub trait BlindCheckable: Sized { + /// Returned if `check` succeeds. + type Checked; + fn check(self) -> Result; } -impl Checkable for T { - type Address = ::Address; - type AccountId = ::Address; +// Every `BlindCheckable` is also a `Checkable` for arbitrary `Context`. +impl Checkable for T { type Checked = ::Checked; - fn sender(&self) -> &Self::Address { BlindCheckable::sender(self) } - fn check Result + Send + Sync>(self, _: ThisLookup) -> Result { BlindCheckable::check(self) } + fn check_with(self, _: Context) -> Result { + BlindCheckable::check(self) + } } /// An "executable" piece of information, used by the standard Substrate Executive in order to diff --git a/substrate/runtime/session/Cargo.toml b/substrate/runtime/session/Cargo.toml index 93938fc3561b7..74edc88b10219 100644 --- a/substrate/runtime/session/Cargo.toml +++ b/substrate/runtime/session/Cargo.toml @@ -17,6 +17,7 @@ substrate-runtime-support = { path = "../../runtime-support", default_features = substrate-runtime-primitives = { path = "../primitives", default_features = false } substrate-runtime-consensus = { path = "../consensus", default_features = false } substrate-runtime-system = { path = "../system", default_features = false } +substrate-runtime-timestamp = { path = "../timestamp", default_features = false } [features] default = ["std"] diff --git a/substrate/runtime/session/src/lib.rs b/substrate/runtime/session/src/lib.rs index b8de8abb1ad5a..6e320a73575f9 100644 --- a/substrate/runtime/session/src/lib.rs +++ b/substrate/runtime/session/src/lib.rs @@ -43,14 +43,26 @@ extern crate substrate_codec as codec; extern crate substrate_runtime_primitives as primitives; extern crate substrate_runtime_consensus as consensus; extern crate substrate_runtime_system as system; +extern crate substrate_runtime_timestamp as timestamp; use rstd::prelude::*; -use primitives::traits::{Zero, One, RefInto, Executable, Convert}; +use primitives::traits::{Zero, One, RefInto, Executable, Convert, As}; use runtime_support::{StorageValue, StorageMap}; use runtime_support::dispatch::Result; -pub trait Trait: consensus::Trait { +/// A session has changed. +pub trait OnSessionChange { + /// Session has changed. + fn on_session_change(normal_rotation: bool, time_elapsed: T); +} + +impl OnSessionChange for () { + fn on_session_change(_: bool, _: T) {} +} + +pub trait Trait: timestamp::Trait { type ConvertAccountIdToSessionKey: Convert; + type OnSessionChange: OnSessionChange; } decl_module! { @@ -64,7 +76,7 @@ decl_module! { #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum PrivCall { fn set_length(new: T::BlockNumber) -> Result = 0; - fn force_new_session() -> Result = 1; + fn force_new_session(normal_rotation: bool) -> Result = 1; } } decl_storage! { @@ -76,6 +88,10 @@ decl_storage! { pub SessionLength get(length): b"ses:len" => required T::BlockNumber; // Current index of the session. pub CurrentIndex get(current_index): b"ses:ind" => required T::BlockNumber; + // Timestamp when current session started. + pub CurrentStart get(current_start): b"ses:current_start" => required T::Moment; + // Percent by which the session must necessarily finish late before we early-exit the session. + pub BrokenPercentLate get(broken_percent_late): b"ses:broken_percent_late" => required T::Moment; // Block at which the session length last changed. LastLengthChange: b"ses:llc" => T::BlockNumber; @@ -111,8 +127,8 @@ impl Module { } /// Forces a new session. - fn force_new_session() -> Result { - Self::rotate_session(); + fn force_new_session(normal_rotation: bool) -> Result { + Self::rotate_session(normal_rotation); Ok(()) } @@ -135,15 +151,21 @@ impl Module { // new set. // check block number and call next_session if necessary. let block_number = >::block_number(); - if ((block_number - Self::last_length_change()) % Self::length()).is_zero() { - Self::rotate_session(); + let is_final_block = ((block_number - Self::last_length_change()) % Self::length()).is_zero(); + let broken_validation = Self::broken_validation(); + if is_final_block || broken_validation { + Self::rotate_session(!broken_validation); } } /// Move onto next session: register the new authority set. - pub fn rotate_session() { + pub fn rotate_session(normal_rotation: bool) { + let now = >::get(); + let time_elapsed = now.clone() - Self::current_start(); + // Increment current session index. >::put(>::get() + One::one()); + >::put(now); // Enact era length change. if let Some(next_len) = >::take() { @@ -152,6 +174,8 @@ impl Module { >::put(block_number); } + T::OnSessionChange::on_session_change(normal_rotation, time_elapsed); + // Update any changes in session keys. Self::validators().iter().enumerate().for_each(|(i, v)| { if let Some(n) = >::take(v) { @@ -159,6 +183,34 @@ impl Module { } }); } + + /// Get the time that should have elapsed over a session if everything was working perfectly. + pub fn ideal_session_duration() -> T::Moment { + let block_period = >::block_period(); + let session_length = >::sa(Self::length()); + session_length * block_period + } + + /// Number of blocks remaining in this session, not counting this one. If the session is + /// due to rotate at the end of this block, then it will return 0. If the just began, then + /// it will return `Self::length() - 1`. + pub fn blocks_remaining() -> T::BlockNumber { + let length = Self::length(); + let length_minus_1 = length - One::one(); + let block_number = >::block_number(); + length_minus_1 - (block_number - Self::last_length_change() + length_minus_1) % length + } + + /// Returns `true` if the current validator set is taking took long to validate blocks. + pub fn broken_validation() -> bool { + let now = >::get(); + let block_period = >::block_period(); + let blocks_remaining = Self::blocks_remaining(); + let blocks_remaining = >::sa(blocks_remaining); + now + blocks_remaining * block_period > + Self::current_start() + Self::ideal_session_duration() * + (T::Moment::sa(100) + Self::broken_percent_late()) / T::Moment::sa(100) + } } impl Executable for Module { @@ -168,9 +220,13 @@ impl Executable for Module { } #[cfg(any(feature = "std", test))] +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] pub struct GenesisConfig { pub session_length: T::BlockNumber, pub validators: Vec, + pub broken_percent_late: T::Moment, } #[cfg(any(feature = "std", test))] @@ -180,6 +236,7 @@ impl Default for GenesisConfig { GenesisConfig { session_length: T::BlockNumber::sa(1000), validators: vec![], + broken_percent_late: T::Moment::sa(30), } } } @@ -187,15 +244,16 @@ impl Default for GenesisConfig { #[cfg(any(feature = "std", test))] impl primitives::BuildStorage for GenesisConfig { - fn build_storage(self) -> runtime_io::TestExternalities { - use runtime_io::twox_128; - use codec::Slicable; + fn build_storage(self) -> ::std::result::Result { + use codec::Encode; use primitives::traits::As; - map![ - twox_128(>::key()).to_vec() => self.session_length.encode(), - twox_128(>::key()).to_vec() => T::BlockNumber::sa(0).encode(), - twox_128(>::key()).to_vec() => self.validators.encode() - ] + Ok(map![ + Self::hash(>::key()).to_vec() => self.session_length.encode(), + Self::hash(>::key()).to_vec() => T::BlockNumber::sa(0).encode(), + Self::hash(>::key()).to_vec() => T::Moment::zero().encode(), + Self::hash(>::key()).to_vec() => self.validators.encode(), + Self::hash(>::key()).to_vec() => self.broken_percent_late.encode() + ]) } } @@ -226,24 +284,34 @@ mod tests { type AccountId = u64; type Header = Header; } + impl timestamp::Trait for Test { + const TIMESTAMP_SET_POSITION: u32 = 0; + type Moment = u64; + } impl Trait for Test { type ConvertAccountIdToSessionKey = Identity; + type OnSessionChange = (); } type System = system::Module; type Consensus = consensus::Module; + type Timestamp = timestamp::Module; type Session = Module; fn new_test_ext() -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::::default().build_storage(); + let mut t = system::GenesisConfig::::default().build_storage().unwrap(); t.extend(consensus::GenesisConfig::{ code: vec![], authorities: vec![1, 2, 3], - }.build_storage()); + }.build_storage().unwrap()); + t.extend(timestamp::GenesisConfig::{ + period: 5, + }.build_storage().unwrap()); t.extend(GenesisConfig::{ session_length: 2, validators: vec![1, 2, 3], - }.build_storage()); + broken_percent_late: 30, + }.build_storage().unwrap()); t } @@ -256,6 +324,36 @@ mod tests { }); } + #[test] + fn should_identify_broken_validation() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(2); + assert_eq!(Session::blocks_remaining(), 0); + Timestamp::set_timestamp(0); + assert_ok!(Session::set_length(3)); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 1); + assert_eq!(Session::length(), 3); + assert_eq!(Session::current_start(), 0); + assert_eq!(Session::ideal_session_duration(), 15); + // ideal end = 0 + 15 * 3 = 15 + // broken_limit = 15 * 130 / 100 = 19 + + System::set_block_number(3); + assert_eq!(Session::blocks_remaining(), 2); + Timestamp::set_timestamp(9); // earliest end = 9 + 2 * 5 = 19; OK. + assert!(!Session::broken_validation()); + Session::check_rotate_session(); + + System::set_block_number(4); + assert_eq!(Session::blocks_remaining(), 1); + Timestamp::set_timestamp(15); // another 1 second late. earliest end = 15 + 1 * 5 = 20; broken. + assert!(Session::broken_validation()); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 2); + }); + } + #[test] fn session_length_change_should_work() { with_externalities(&mut new_test_ext(), || { diff --git a/substrate/runtime/staking/Cargo.toml b/substrate/runtime/staking/Cargo.toml index b231ed7cf192e..410667aaec6c7 100644 --- a/substrate/runtime/staking/Cargo.toml +++ b/substrate/runtime/staking/Cargo.toml @@ -11,7 +11,6 @@ safe-mix = { path = "../../../safe-mix", default_features = false} substrate-keyring = { path = "../../keyring", optional = true } substrate-codec = { path = "../../codec", default_features = false } substrate-primitives = { path = "../../primitives", default_features = false } -substrate-runtime-contract = { path = "../contract", default_features = false } substrate-runtime-std = { path = "../../runtime-std", default_features = false } substrate-runtime-io = { path = "../../runtime-io", default_features = false } substrate-runtime-sandbox = { path = "../../runtime-sandbox", default_features = false } @@ -20,9 +19,10 @@ substrate-runtime-primitives = { path = "../primitives", default_features = fals substrate-runtime-consensus = { path = "../consensus", default_features = false } substrate-runtime-system = { path = "../system", default_features = false } substrate-runtime-session = { path = "../session", default_features = false } +substrate-runtime-timestamp = { path = "../timestamp", default_features = false } [dev-dependencies] -wabt = "0.1.7" +wabt = "0.4" [features] default = ["std"] @@ -33,7 +33,6 @@ std = [ "substrate-keyring", "substrate-codec/std", "substrate-primitives/std", - "substrate-runtime-contract/std", "substrate-runtime-std/std", "substrate-runtime-io/std", "substrate-runtime-sandbox/std", diff --git a/substrate/runtime/staking/src/address.rs b/substrate/runtime/staking/src/address.rs index dc0769e4ad124..249e0b20db225 100644 --- a/substrate/runtime/staking/src/address.rs +++ b/substrate/runtime/staking/src/address.rs @@ -16,10 +16,9 @@ //! Address type that is union of index and id for an account. -use rstd::prelude::*; #[cfg(feature = "std")] use std::fmt; -use super::{Member, Slicable, As, Input}; +use super::{Member, Decode, Encode, As, Input, Output}; /// A vetted and verified extrinsic from the external world. #[derive(PartialEq, Eq, Clone)] @@ -59,45 +58,46 @@ fn need_more_than(a: T, b: T) -> Option { if a < b { Some(a) } else { None } } -impl Slicable for Address where - AccountId: Member + Slicable, - AccountIndex: Member + Slicable + PartialOrd + Ord + As + As + As + Copy, +impl Decode for Address where + AccountId: Member + Decode, + AccountIndex: Member + Decode + PartialOrd + Ord + As + As + As + Copy, { fn decode(input: &mut I) -> Option { Some(match input.read_byte()? { x @ 0x00...0xef => Address::Index(As::sa(x)), 0xfc => Address::Index(As::sa(need_more_than(0xef, u16::decode(input)?)?)), 0xfd => Address::Index(As::sa(need_more_than(0xffff, u32::decode(input)?)?)), - 0xfe => Address::Index(need_more_than(As::sa(0xffffffffu32), Slicable::decode(input)?)?), - 0xff => Address::Id(Slicable::decode(input)?), + 0xfe => Address::Index(need_more_than(As::sa(0xffffffffu32), Decode::decode(input)?)?), + 0xff => Address::Id(Decode::decode(input)?), _ => return None, }) } +} - fn encode(&self) -> Vec { - let mut v = Vec::new(); - +impl Encode for Address where + AccountId: Member + Encode, + AccountIndex: Member + Encode + PartialOrd + Ord + As + As + As + Copy, +{ + fn encode_to(&self, dest: &mut T) { match *self { Address::Id(ref i) => { - v.push(255); - i.using_encoded(|s| v.extend(s)); + dest.push_byte(255); + dest.push(i); } Address::Index(i) if i > As::sa(0xffffffffu32) => { - v.push(254); - i.using_encoded(|s| v.extend(s)); + dest.push_byte(254); + dest.push(&i); } Address::Index(i) if i > As::sa(0xffffu32) => { - v.push(253); - As::::as_(i).using_encoded(|s| v.extend(s)); + dest.push_byte(253); + dest.push(&As::::as_(i)); } Address::Index(i) if i >= As::sa(0xf0u32) => { - v.push(252); - As::::as_(i).using_encoded(|s| v.extend(s)); + dest.push_byte(252); + dest.push(&As::::as_(i)); } - Address::Index(i) => v.push(As::::as_(i)), + Address::Index(i) => dest.push_byte(As::::as_(i)), } - - v } } diff --git a/substrate/runtime/staking/src/genesis_config.rs b/substrate/runtime/staking/src/genesis_config.rs new file mode 100644 index 0000000000000..2987725b7a235 --- /dev/null +++ b/substrate/runtime/staking/src/genesis_config.rs @@ -0,0 +1,152 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo 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. + +// Substrate Demo 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 Substrate Demo. If not, see . + +//! Build a staking genesis block. + +#![cfg(feature = "std")] + +use rstd::prelude::*; +use codec::Encode; +use runtime_support::{StorageValue, StorageMap}; +use primitives::traits::{Zero, As}; +use {runtime_io, primitives}; +use super::{Trait, ENUM_SET_SIZE, EnumSet, NextEnumSet, Intentions, CurrentEra, + BondingDuration, CreationFee, TransferFee, ReclaimRebate, + ExistentialDeposit, TransactionByteFee, TransactionBaseFee, TotalStake, + SessionsPerEra, ValidatorCount, FreeBalance, SessionReward, EarlyEraSlash}; + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +pub struct GenesisConfig { + pub sessions_per_era: T::BlockNumber, + pub current_era: T::BlockNumber, + pub balances: Vec<(T::AccountId, T::Balance)>, + pub intentions: Vec, + pub validator_count: u64, + pub bonding_duration: T::BlockNumber, + pub transaction_base_fee: T::Balance, + pub transaction_byte_fee: T::Balance, + pub transfer_fee: T::Balance, + pub creation_fee: T::Balance, + pub reclaim_rebate: T::Balance, + pub existential_deposit: T::Balance, + pub session_reward: T::Balance, + pub early_era_slash: T::Balance, +} + +impl GenesisConfig where T::AccountId: From { + pub fn simple() -> Self { + GenesisConfig { + sessions_per_era: T::BlockNumber::sa(2), + current_era: T::BlockNumber::sa(0), + balances: vec![(T::AccountId::from(1), T::Balance::sa(111))], + intentions: vec![T::AccountId::from(1), T::AccountId::from(2), T::AccountId::from(3)], + validator_count: 3, + bonding_duration: T::BlockNumber::sa(0), + transaction_base_fee: T::Balance::sa(0), + transaction_byte_fee: T::Balance::sa(0), + transfer_fee: T::Balance::sa(0), + creation_fee: T::Balance::sa(0), + existential_deposit: T::Balance::sa(0), + reclaim_rebate: T::Balance::sa(0), + session_reward: T::Balance::sa(0), + early_era_slash: T::Balance::sa(0), + } + } + + pub fn extended() -> Self { + GenesisConfig { + sessions_per_era: T::BlockNumber::sa(3), + current_era: T::BlockNumber::sa(1), + balances: vec![ + (T::AccountId::from(1), T::Balance::sa(10)), + (T::AccountId::from(2), T::Balance::sa(20)), + (T::AccountId::from(3), T::Balance::sa(30)), + (T::AccountId::from(4), T::Balance::sa(40)), + (T::AccountId::from(5), T::Balance::sa(50)), + (T::AccountId::from(6), T::Balance::sa(60)), + (T::AccountId::from(7), T::Balance::sa(1)) + ], + intentions: vec![T::AccountId::from(1), T::AccountId::from(2), T::AccountId::from(3)], + validator_count: 3, + bonding_duration: T::BlockNumber::sa(0), + transaction_base_fee: T::Balance::sa(1), + transaction_byte_fee: T::Balance::sa(0), + transfer_fee: T::Balance::sa(0), + creation_fee: T::Balance::sa(0), + existential_deposit: T::Balance::sa(0), + reclaim_rebate: T::Balance::sa(0), + session_reward: T::Balance::sa(0), + early_era_slash: T::Balance::sa(0), + } + } +} + +impl Default for GenesisConfig { + fn default() -> Self { + GenesisConfig { + sessions_per_era: T::BlockNumber::sa(1000), + current_era: T::BlockNumber::sa(0), + balances: vec![], + intentions: vec![], + validator_count: 0, + bonding_duration: T::BlockNumber::sa(1000), + transaction_base_fee: T::Balance::sa(0), + transaction_byte_fee: T::Balance::sa(0), + transfer_fee: T::Balance::sa(0), + creation_fee: T::Balance::sa(0), + existential_deposit: T::Balance::sa(0), + reclaim_rebate: T::Balance::sa(0), + session_reward: T::Balance::sa(0), + early_era_slash: T::Balance::sa(0), + } + } +} + +impl primitives::BuildStorage for GenesisConfig { + fn build_storage(self) -> Result { + let total_stake: T::Balance = self.balances.iter().fold(Zero::zero(), |acc, &(_, n)| acc + n); + + let mut r: runtime_io::TestExternalities = map![ + Self::hash(>::key()).to_vec() => T::AccountIndex::sa(self.balances.len() / ENUM_SET_SIZE).encode(), + Self::hash(>::key()).to_vec() => self.intentions.encode(), + Self::hash(>::key()).to_vec() => self.sessions_per_era.encode(), + Self::hash(>::key()).to_vec() => self.validator_count.encode(), + Self::hash(>::key()).to_vec() => self.bonding_duration.encode(), + Self::hash(>::key()).to_vec() => self.transaction_base_fee.encode(), + Self::hash(>::key()).to_vec() => self.transaction_byte_fee.encode(), + Self::hash(>::key()).to_vec() => self.transfer_fee.encode(), + Self::hash(>::key()).to_vec() => self.creation_fee.encode(), + Self::hash(>::key()).to_vec() => self.existential_deposit.encode(), + Self::hash(>::key()).to_vec() => self.reclaim_rebate.encode(), + Self::hash(>::key()).to_vec() => self.current_era.encode(), + Self::hash(>::key()).to_vec() => self.session_reward.encode(), + Self::hash(>::key()).to_vec() => self.early_era_slash.encode(), + Self::hash(>::key()).to_vec() => total_stake.encode() + ]; + + let ids: Vec<_> = self.balances.iter().map(|x| x.0.clone()).collect(); + for i in 0..(ids.len() + ENUM_SET_SIZE - 1) / ENUM_SET_SIZE { + r.insert(Self::hash(&>::key_for(T::AccountIndex::sa(i))).to_vec(), + ids[i * ENUM_SET_SIZE..ids.len().min((i + 1) * ENUM_SET_SIZE)].to_owned().encode()); + } + for (who, value) in self.balances.into_iter() { + r.insert(Self::hash(&>::key_for(who)).to_vec(), value.encode()); + } + Ok(r) + } +} diff --git a/substrate/runtime/staking/src/lib.rs b/substrate/runtime/staking/src/lib.rs index 12d591e3a6172..ba71c6ec3f1e9 100644 --- a/substrate/runtime/staking/src/lib.rs +++ b/substrate/runtime/staking/src/lib.rs @@ -36,31 +36,33 @@ extern crate substrate_runtime_std as rstd; extern crate substrate_codec as codec; extern crate substrate_primitives; -extern crate substrate_runtime_contract as contract; extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_primitives as primitives; extern crate substrate_runtime_consensus as consensus; extern crate substrate_runtime_sandbox as sandbox; extern crate substrate_runtime_session as session; extern crate substrate_runtime_system as system; +extern crate substrate_runtime_timestamp as timestamp; #[cfg(test)] use std::fmt::Debug; use rstd::prelude::*; use rstd::{cmp, result}; -use rstd::cell::RefCell; -use rstd::collections::btree_map::{BTreeMap, Entry}; -use codec::{Input, Slicable}; +use codec::{Encode, Decode, Codec, Input, Output}; use runtime_support::{StorageValue, StorageMap, Parameter}; use runtime_support::dispatch::Result; +use session::OnSessionChange; use primitives::traits::{Zero, One, Bounded, RefInto, SimpleArithmetic, Executable, MakePayment, - As, AuxLookup, Hashing as HashingT, Member}; + As, AuxLookup, Member, CheckedAdd, CheckedSub}; use address::Address as RawAddress; -pub mod address; -#[cfg(test)] mod mock; -#[cfg(test)] + +pub mod address; mod tests; +mod genesis_config; + +#[cfg(feature = "std")] +pub use genesis_config::GenesisConfig; /// Number of account IDs stored per enum set. const ENUM_SET_SIZE: usize = 64; @@ -86,30 +88,26 @@ pub enum LockStatus { Staked, } -pub trait ContractAddressFor { - fn contract_address_for(code: &[u8], origin: &AccountId) -> AccountId; +/// The account was the given id was killed. +pub trait OnAccountKill { + /// The account was the given id was killed. + fn on_account_kill(who: &AccountId); } -impl ContractAddressFor for Hashing where - Hashing: HashingT, - AccountId: Sized + Slicable + From, - Hashing::Output: Slicable -{ - fn contract_address_for(code: &[u8], origin: &AccountId) -> AccountId { - let mut dest_pre = Hashing::hash(code).encode(); - origin.using_encoded(|s| dest_pre.extend(s)); - AccountId::from(Hashing::hash(&dest_pre)) - } +impl OnAccountKill for () { + fn on_account_kill(_who: &AccountId) {} } pub trait Trait: system::Trait + session::Trait { /// The balance of an account. - type Balance: Parameter + SimpleArithmetic + Slicable + Default + Copy + As + As; - /// Function type to get the contract address given the creator. - type DetermineContractAddress: ContractAddressFor; + type Balance: Parameter + SimpleArithmetic + Codec + Default + Copy + As + As + As; /// Type used for storing an account's index; implies the maximum number of accounts the system /// can hold. - type AccountIndex: Parameter + Member + Slicable + SimpleArithmetic + As + As + As + As + Copy; + type AccountIndex: Parameter + Member + Codec + SimpleArithmetic + As + As + As + As + As + Copy; + /// A function which is invoked when the given account is dead. + /// + /// Gives a chance to clean up resources associated with the given account. + type OnAccountKill: OnAccountKill; } decl_module! { @@ -119,7 +117,9 @@ decl_module! { pub enum Call where aux: T::PublicAux { fn transfer(aux, dest: RawAddress, value: T::Balance) -> Result = 0; fn stake(aux) -> Result = 1; - fn unstake(aux) -> Result = 2; + fn unstake(aux, index: u32) -> Result = 2; + fn nominate(aux, target: RawAddress) -> Result = 3; + fn unnominate(aux, target_index: u32) -> Result = 4; } #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -141,6 +141,7 @@ decl_storage! { // The length of a staking era in sessions. pub SessionsPerEra get(sessions_per_era): b"sta:spe" => required T::BlockNumber; // The total amount of stake on the system. + // TODO: this doesn't actually track total stake yet - it should do. pub TotalStake get(total_stake): b"sta:tot" => required T::Balance; // The fee to be paid for making a transaction; the base. pub TransactionBaseFee get(transaction_base_fee): b"sta:basefee" => required T::Balance; @@ -154,17 +155,27 @@ decl_storage! { pub TransferFee get(transfer_fee): b"sta:transfer_fee" => required T::Balance; // The fee required to create an account. At least as big as ReclaimRebate. pub CreationFee get(creation_fee): b"sta:creation_fee" => required T::Balance; - // The fee required to create a contract. At least as big as ReclaimRebate. - pub ContractFee get(contract_fee): b"sta:contract_fee" => required T::Balance; + // Maximum reward, per validator, that is provided per acceptable session. + pub SessionReward get(session_reward): b"sta:session_reward" => required T::Balance; + // Slash, per validator that is taken per abnormal era end. + pub EarlyEraSlash get(early_era_slash): b"sta:early_era_slash" => required T::Balance; // The current era index. pub CurrentEra get(current_era): b"sta:era" => required T::BlockNumber; // All the accounts with a desire to stake. - pub Intentions: b"sta:wil:" => default Vec; + pub Intentions get(intentions): b"sta:wil:" => default Vec; + // All nominator -> nominee relationships. + pub Nominating get(nominating): b"sta:nominating" => map [ T::AccountId => T::AccountId ]; + // Nominators for a particular account. + pub NominatorsFor get(nominators_for): b"sta:nominators_for" => default map [ T::AccountId => Vec ]; + // Nominators for a particular account that is in action right now. + pub CurrentNominatorsFor get(current_nominators_for): b"sta:current_nominators_for" => default map [ T::AccountId => Vec ]; // The next value of sessions per era. pub NextSessionsPerEra get(next_sessions_per_era): b"sta:nse" => T::BlockNumber; - // The block number at which the era length last changed. + // The session index at which the era length last changed. pub LastEraLengthChange get(last_era_length_change): b"sta:lec" => default T::BlockNumber; + // The current era stake threshold + pub StakeThreshold get(stake_threshold): b"sta:stake_threshold" => required T::Balance; // The next free enumeration set. pub NextEnumSet get(next_enum_set): b"sta:next_enum" => required T::AccountIndex; @@ -176,7 +187,9 @@ decl_storage! { // This is the only balance that matters in terms of most operations on tokens. It is // alone used to determine the balance when in the contract execution environment. When this // balance falls below the value of `ExistentialDeposit`, then the "current account" is - // deleted: specifically, `Bondage`, `StorageOf`, `CodeOf` and `FreeBalance`. + // deleted: specifically, `Bondage` and `FreeBalance`. Furthermore, `OnAccountKill` callback + // is invoked, giving a chance to external modules to cleanup data associated with + // the deleted account. // // `system::AccountNonce` is also deleted if `ReservedBalance` is also zero (it also gets // collapsed to zero if it ever becomes less than `ExistentialDeposit`. @@ -198,19 +211,6 @@ decl_storage! { // The block at which the `who`'s funds become entirely liquid. pub Bondage get(bondage): b"sta:bon:" => default map [ T::AccountId => T::BlockNumber ]; - - // The code associated with an account. - pub CodeOf: b"sta:cod:" => default map [ T::AccountId => Vec ]; // TODO Vec values should be optimised to not do a length prefix. - - // The storage items associated with an account/key. - // TODO: keys should also be able to take AsRef to ensure Vecs can be passed as &[u8] - // TODO: This will need to be stored as a double-map, with `T::AccountId` using the usual XX hash - // function, and then the output of this concatenated onto a separate blake2 hash of the `Vec` - // key. We will then need a `remove_prefix` in addition to `set_storage` which removes all - // storage items with a particular prefix otherwise we'll suffer leakage with the removal - // of smart contracts. -// pub StorageOf: b"sta:sto:" => map [ T::AccountId => map(blake2) Vec => Vec ]; - pub StorageOf: b"sta:sto:" => map [ (T::AccountId, Vec) => Vec ]; } enum NewAccountOutcome { @@ -219,6 +219,14 @@ enum NewAccountOutcome { BadHint, } +/// Outcome of a balance update. +pub enum UpdateBalanceOutcome { + /// Account balance was simply updated. + Updated, + /// The update has led to killing of the account. + AccountKilled, +} + impl Module { // PUBLIC IMMUTABLES @@ -258,25 +266,40 @@ impl Module { } } - /// Create a smart-contract account. - pub fn create(aux: &T::PublicAux, code: &[u8], value: T::Balance) -> Result { - // commit anything that made it this far to storage - if let Some(commit) = Self::effect_create(aux.ref_into(), code, value, &DirectAccountDb)? { - >::merge(&mut DirectAccountDb, commit); - } - Ok(()) - } - // PUBLIC DISPATCH /// Transfer some unlocked staking balance to another staker. - /// TODO: probably want to state gas-limit and gas-price. - fn transfer(aux: &T::PublicAux, dest: Address, value: T::Balance) -> Result { + pub fn transfer(aux: &T::PublicAux, dest: Address, value: T::Balance) -> Result { let dest = Self::lookup(dest)?; - // commit anything that made it this far to storage - if let Some(commit) = Self::effect_transfer(aux.ref_into(), &dest, value, &DirectAccountDb)? { - >::merge(&mut DirectAccountDb, commit); + + let transactor = aux.ref_into(); + let from_balance = Self::free_balance(transactor); + let would_create = from_balance.is_zero(); + let fee = if would_create { Self::creation_fee() } else { Self::transfer_fee() }; + let liability = value + fee; + + let new_from_balance = match from_balance.checked_sub(&liability) { + Some(b) => b, + None => return Err("balance too low to send value"), + }; + if would_create && value < Self::existential_deposit() { + return Err("value too low to create account"); + } + if >::get(transactor) > >::block_number() { + return Err("bondage too high to send value"); + } + + let to_balance = Self::free_balance(&dest); + let new_to_balance = match to_balance.checked_add(&value) { + Some(b) => b, + None => return Err("destination balance too high to receive value"), + }; + + if transactor != &dest { + Self::set_free_balance(transactor, new_from_balance); + Self::set_free_balance_creating(&dest, new_to_balance); } + Ok(()) } @@ -284,27 +307,82 @@ impl Module { /// /// Effects will be felt at the beginning of the next era. fn stake(aux: &T::PublicAux) -> Result { + let aux = aux.ref_into(); + ensure!(Self::nominating(aux).is_none(), "Cannot stake if already nominating."); let mut intentions = >::get(); // can't be in the list twice. - ensure!(intentions.iter().find(|&t| t == aux.ref_into()).is_none(), "Cannot stake if already staked."); - intentions.push(aux.ref_into().clone()); + ensure!(intentions.iter().find(|&t| t == aux).is_none(), "Cannot stake if already staked."); + intentions.push(aux.clone()); >::put(intentions); - >::insert(aux.ref_into(), T::BlockNumber::max_value()); + >::insert(aux, T::BlockNumber::max_value()); Ok(()) } /// Retract the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. - fn unstake(aux: &T::PublicAux) -> Result { + fn unstake(aux: &T::PublicAux, position: u32) -> Result { + let aux = aux.ref_into(); + let position = position as usize; let mut intentions = >::get(); - let position = intentions.iter().position(|t| t == aux.ref_into()).ok_or("Cannot unstake if not already staked.")?; +// let position = intentions.iter().position(|t| t == aux.ref_into()).ok_or("Cannot unstake if not already staked.")?; + if intentions.get(position) != Some(aux) { + return Err("Invalid index") + } intentions.swap_remove(position); >::put(intentions); >::insert(aux.ref_into(), Self::current_era() + Self::bonding_duration()); Ok(()) } + fn nominate(aux: &T::PublicAux, target: RawAddress) -> Result { + let target = Self::lookup(target)?; + let aux = aux.ref_into(); + + ensure!(Self::nominating(aux).is_none(), "Cannot nominate if already nominating."); + ensure!(Self::intentions().iter().find(|&t| t == aux.ref_into()).is_none(), "Cannot nominate if already staked."); + + // update nominators_for + let mut t = Self::nominators_for(&target); + t.push(aux.clone()); + >::insert(&target, t); + + // update nominating + >::insert(aux, &target); + + // Update bondage + >::insert(aux.ref_into(), T::BlockNumber::max_value()); + + Ok(()) + } + + /// Will panic if called when source isn't currently nominating target. + /// Updates Nominating, NominatorsFor and NominationBalance. + fn unnominate(aux: &T::PublicAux, target_index: u32) -> Result { + let source = aux.ref_into(); + let target_index = target_index as usize; + + let target = >::get(source).ok_or("Account must be nominating")?; + + let mut t = Self::nominators_for(&target); + if t.get(target_index) != Some(source) { + return Err("Invalid target index") + } + + // Ok - all valid. + + // update nominators_for + t.swap_remove(target_index); + >::insert(&target, t); + + // update nominating + >::remove(source); + + // update bondage + >::insert(aux.ref_into(), Self::current_era() + Self::bonding_duration()); + Ok(()) + } + // PRIV DISPATCH /// Set the number of sessions in an era. @@ -327,22 +405,23 @@ impl Module { /// Force there to be a new era. This also forces a new session immediately after. fn force_new_era() -> Result { - Self::new_era(); - >::rotate_session(); + >::rotate_session(false); Ok(()) } // PUBLIC MUTABLES (DANGEROUS) - /// Set the free balance of an account to some new value. Will enforce ExistentialDeposit law, - /// anulling the account as needed. - pub fn set_reserved_balance(who: &T::AccountId, balance: T::Balance) -> bool { + /// Set the free balance of an account to some new value. + /// + /// Will enforce ExistentialDeposit law, anulling the account as needed. + /// In that case it will return `AccountKilled`. + pub fn set_reserved_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { if balance < Self::existential_deposit() { Self::on_reserved_too_low(who); - false + UpdateBalanceOutcome::AccountKilled } else { >::insert(who, balance); - true + UpdateBalanceOutcome::Updated } } @@ -351,15 +430,55 @@ impl Module { /// /// Doesn't do any preparatory work for creating a new account, so should only be used when it /// is known that the account already exists. - pub fn set_free_balance(who: &T::AccountId, balance: T::Balance) -> bool { + /// + /// Returns if the account was successfully updated or update has led to killing of the account. + pub fn set_free_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { // Commented out for no - but consider it instructive. // assert!(!Self::voting_balance(who).is_zero()); if balance < Self::existential_deposit() { Self::on_free_too_low(who); - false + UpdateBalanceOutcome::AccountKilled } else { >::insert(who, balance); - true + UpdateBalanceOutcome::Updated + } + } + + /// Set the free balance on an account to some new value. + /// + /// Same as [`set_free_balance`], but will create a new account. + /// + /// Returns if the account was successfully updated or update has led to killing of the account. + /// + /// [`set_free_balance`]: #method.set_free_balance + pub fn set_free_balance_creating(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { + let ed = >::existential_deposit(); + // If the balance is too low, then the account is reaped. + // NOTE: There are two balances for every account: `reserved_balance` and + // `free_balance`. This contract subsystem only cares about the latter: whenever + // the term "balance" is used *here* it should be assumed to mean "free balance" + // in the rest of the module. + // Free balance can never be less than ED. If that happens, it gets reduced to zero + // and the account information relevant to this subsystem is deleted (i.e. the + // account is reaped). + // NOTE: This is orthogonal to the `Bondage` value that an account has, a high + // value of which makes even the `free_balance` unspendable. + // TODO: enforce this for the other balance-altering functions. + if balance < ed { + Self::on_free_too_low(who); + UpdateBalanceOutcome::AccountKilled + } else { + if !>::exists(who) { + let outcome = Self::new_account(&who, balance); + let credit = match outcome { + NewAccountOutcome::GoodHint => balance + >::reclaim_rebate(), + _ => balance, + }; + >::insert(who, credit); + } else { + >::insert(who, balance); + } + UpdateBalanceOutcome::Updated } } @@ -379,6 +498,17 @@ impl Module { } } + /// Adds up to `value` to the free balance of `who`. + /// + /// If `who` doesn't exist, nothing is done and an Err returned. + pub fn reward(who: &T::AccountId, value: T::Balance) -> Result { + if Self::voting_balance(who).is_zero() { + return Err("beneficiary account must pre-exist"); + } + Self::set_free_balance(who, Self::free_balance(who) + value); + Ok(()) + } + /// Moves `value` from balance to reserved balance. /// /// If the free balance is lower than `value`, then no funds will be moved and an `Err` will @@ -453,14 +583,54 @@ impl Module { } } - /// Hook to be called after to transaction processing. - pub fn check_new_era() { - // check block number and call new_era if necessary. - if (>::block_number() - Self::last_era_length_change()) % Self::era_length() == Zero::zero() { + /// Session has just changed. We need to determine whether we pay a reward, slash and/or + /// move to a new era. + fn new_session(normal_rotation: bool, actual_elapsed: T::Moment) { + let session_index = >::current_index(); + + if normal_rotation { + // reward + let ideal_elapsed = >::ideal_session_duration(); + let per65536: u64 = (T::Moment::sa(65536u64) * ideal_elapsed.clone() / actual_elapsed.max(ideal_elapsed)).as_(); + let reward = Self::session_reward() * T::Balance::sa(per65536) / T::Balance::sa(65536u64); + // apply good session reward + for v in >::validators().iter() { + let noms = Self::current_nominators_for(v); + let total = noms.iter().map(Self::voting_balance).fold(Self::voting_balance(v), |acc, x| acc + x); + if !total.is_zero() { + let safe_mul_rational = |b| b * reward / total;// TODO: avoid overflow + for n in noms.iter() { + let _ = Self::reward(n, safe_mul_rational(Self::voting_balance(n))); + } + let _ = Self::reward(v, safe_mul_rational(Self::voting_balance(v))); + } + } + } else { + // slash + let early_era_slash = Self::early_era_slash(); + for v in >::validators().iter() { + if let Some(rem) = Self::slash(v, early_era_slash) { + let noms = Self::current_nominators_for(v); + let total = noms.iter().map(Self::voting_balance).fold(T::Balance::zero(), |acc, x| acc + x); + if !total.is_zero() { + let safe_mul_rational = |b| b * rem / total;// TODO: avoid overflow + for n in noms.iter() { + let _ = Self::slash(n, safe_mul_rational(Self::voting_balance(n))); // best effort - not much that can be done on fail. + } + } + } + } + } + if ((session_index - Self::last_era_length_change()) % Self::sessions_per_era()).is_zero() || !normal_rotation { Self::new_era(); } } + /// Balance of a (potential) validator that includes all nominators. + fn nomination_balance(who: &T::AccountId) -> T::Balance { + Self::nominators_for(who).iter().map(Self::voting_balance).fold(Zero::zero(), |acc, x| acc + x) + } + /// The era has changed - enact new staking set. /// /// NOTE: This always happens immediately before a session change to ensure that new validators @@ -473,7 +643,7 @@ impl Module { if let Some(next_spe) = Self::next_sessions_per_era() { if next_spe != Self::sessions_per_era() { >::put(&next_spe); - >::put(&>::block_number()); + >::put(&>::current_index()); } } @@ -481,17 +651,30 @@ impl Module { // combination of validators, then use session::internal::set_validators(). // for now, this just orders would-be stakers by their balances and chooses the top-most // >::get() of them. + // TODO: this is not sound. this should be moved to an off-chain solution mechanism. let mut intentions = >::get() .into_iter() - .map(|v| (Self::voting_balance(&v), v)) + .map(|v| (Self::voting_balance(&v) + Self::nomination_balance(&v), v)) .collect::>(); intentions.sort_unstable_by(|&(ref b1, _), &(ref b2, _)| b2.cmp(&b1)); - >::set_validators( - &intentions.into_iter() + + >::put( + if intentions.len() > 0 { + let i = (>::get() as usize).min(intentions.len() - 1); + intentions[i].0.clone() + } else { Zero::zero() } + ); + let vals = &intentions.into_iter() .map(|(_, v)| v) .take(>::get() as usize) - .collect::>() - ); + .collect::>(); + for v in >::validators().iter() { + >::remove(v); + } + for v in vals.iter() { + >::insert(v, Self::nominators_for(v)); + } + >::set_validators(vals); } fn enum_set_size() -> T::AccountIndex { @@ -586,8 +769,7 @@ impl Module { fn on_free_too_low(who: &T::AccountId) { >::remove(who); >::remove(who); - >::remove(who); - // TODO: >::remove_prefix(address.clone()); + T::OnAccountKill::on_account_kill(who); if Self::reserved_balance(who).is_zero() { >::remove(who); @@ -605,7 +787,12 @@ impl Module { impl Executable for Module { fn execute() { - Self::check_new_era(); + } +} + +impl OnSessionChange for Module { + fn on_session_change(normal_rotation: bool, elapsed: T::Moment) { + Self::new_session(normal_rotation, elapsed); } } @@ -620,449 +807,14 @@ impl AuxLookup for Module { } } -// Each identity's stake may be in one of three bondage states, given by an integer: -// - n | n <= >::get(): inactive: free to be transferred. -// - ~0: active: currently representing a validator. -// - n | n > >::get(): deactivating: recently representing a validator and not yet -// ready for transfer. - -struct ChangeEntry { - balance: Option, - code: Option>, - storage: BTreeMap, Option>>, -} - -// Cannot derive(Default) since it erroneously bounds T by Default. -impl Default for ChangeEntry { - fn default() -> Self { - ChangeEntry { - balance: Default::default(), - code: Default::default(), - storage: Default::default(), - } - } -} - -impl ChangeEntry { - pub fn contract_created(b: T::Balance, c: Vec) -> Self { - ChangeEntry { balance: Some(b), code: Some(c), storage: Default::default() } - } - pub fn balance_changed(b: T::Balance) -> Self { - ChangeEntry { balance: Some(b), code: None, storage: Default::default() } - } -} - -type State = BTreeMap<::AccountId, ChangeEntry>; - -trait AccountDb { - fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option>; - fn get_code(&self, account: &T::AccountId) -> Vec; - fn get_balance(&self, account: &T::AccountId) -> T::Balance; - - fn merge(&mut self, state: State); -} - -struct DirectAccountDb; -impl AccountDb for DirectAccountDb { - fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option> { - >::get(&(account.clone(), location.to_vec())) - } - fn get_code(&self, account: &T::AccountId) -> Vec { - >::get(account) - } - fn get_balance(&self, account: &T::AccountId) -> T::Balance { - >::get(account) - } - fn merge(&mut self, s: State) { - let ed = >::existential_deposit(); - for (address, changed) in s.into_iter() { - if let Some(balance) = changed.balance { - // If the balance is too low, then the account is reaped. - // NOTE: There are two balances for every account: `reserved_balance` and - // `free_balance`. This contract subsystem only cares about the latter: whenever - // the term "balance" is used *here* it should be assumed to mean "free balance" - // in the rest of the module. - // Free balance can never be less than ED. If that happens, it gets reduced to zero - // and the account information relevant to this subsystem is deleted (i.e. the - // account is reaped). - // NOTE: This is orthogonal to the `Bondage` value that an account has, a high - // value of which makes even the `free_balance` unspendable. - // TODO: enforce this for the other balance-altering functions. - if balance < ed { - >::on_free_too_low(&address); - continue; - } else { - if !>::exists(&address) { - let outcome = >::new_account(&address, balance); - let credit = match outcome { - NewAccountOutcome::GoodHint => balance + >::reclaim_rebate(), - _ => balance, - }; - >::insert(&address, credit); - } else { - >::insert(&address, balance); - } - } - } - if let Some(code) = changed.code { - >::insert(&address, &code); - } - for (k, v) in changed.storage.into_iter() { - if let Some(value) = v { - >::insert((address.clone(), k), &value); - } else { - >::remove((address.clone(), k)); - } - } - } - } -} - -struct OverlayAccountDb<'a, T: Trait + 'a> { - local: RefCell>, - underlying: &'a AccountDb, -} -impl<'a, T: Trait> OverlayAccountDb<'a, T> { - fn new(underlying: &'a AccountDb) -> OverlayAccountDb<'a, T> { - OverlayAccountDb { - local: RefCell::new(State::new()), - underlying, - } - } - - fn into_state(self) -> State { - self.local.into_inner() - } - - fn set_storage(&mut self, account: &T::AccountId, location: Vec, value: Option>) { - self.local - .borrow_mut() - .entry(account.clone()) - .or_insert(Default::default()) - .storage - .insert(location, value); - } - fn set_balance(&mut self, account: &T::AccountId, balance: T::Balance) { - self.local - .borrow_mut() - .entry(account.clone()) - .or_insert(Default::default()) - .balance = Some(balance); - } -} - -impl<'a, T: Trait> AccountDb for OverlayAccountDb<'a, T> { - fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option> { - self.local - .borrow() - .get(account) - .and_then(|a| a.storage.get(location)) - .cloned() - .unwrap_or_else(|| self.underlying.get_storage(account, location)) - } - fn get_code(&self, account: &T::AccountId) -> Vec { - self.local - .borrow() - .get(account) - .and_then(|a| a.code.clone()) - .unwrap_or_else(|| self.underlying.get_code(account)) - } - fn get_balance(&self, account: &T::AccountId) -> T::Balance { - self.local - .borrow() - .get(account) - .and_then(|a| a.balance) - .unwrap_or_else(|| self.underlying.get_balance(account)) - } - fn merge(&mut self, s: State) { - let mut local = self.local.borrow_mut(); - - for (address, changed) in s.into_iter() { - match local.entry(address) { - Entry::Occupied(e) => { - let mut value = e.into_mut(); - if changed.balance.is_some() { - value.balance = changed.balance; - } - if changed.code.is_some() { - value.code = changed.code; - } - value.storage.extend(changed.storage.into_iter()); - } - Entry::Vacant(e) => { - e.insert(changed); - } - } - } - } -} - -impl Module { - fn effect_create>( - transactor: &T::AccountId, - code: &[u8], - value: T::Balance, - account_db: &DB, - ) -> result::Result>, &'static str> { - let from_balance = account_db.get_balance(transactor); - - let liability = value + Self::contract_fee(); - - if from_balance < liability { - return Err("balance too low to send value"); - } - if value < Self::existential_deposit() { - return Err("value too low to create account"); - } - if >::get(transactor) > >::block_number() { - return Err("bondage too high to send value"); - } - - let dest = T::DetermineContractAddress::contract_address_for(code, transactor); - - // early-out if degenerate. - if &dest == transactor { - return Ok(None); - } - - let mut local = BTreeMap::new(); - // two inserts are safe - // note that we now know that `&dest != transactor` due to early-out before. - local.insert(dest, ChangeEntry::contract_created(value, code.to_vec())); - local.insert(transactor.clone(), ChangeEntry::balance_changed(from_balance - liability)); - Ok(Some(local)) - } - - fn effect_transfer>( - transactor: &T::AccountId, - dest: &T::AccountId, - value: T::Balance, - account_db: &DB, - ) -> result::Result>, &'static str> { - let would_create = account_db.get_balance(transactor).is_zero(); - let fee = if would_create { Self::creation_fee() } else { Self::transfer_fee() }; - let liability = value + fee; - - let from_balance = account_db.get_balance(transactor); - if from_balance < liability { - return Err("balance too low to send value"); - } - if would_create && value < Self::existential_deposit() { - return Err("value too low to create account"); - } - if >::get(transactor) > >::block_number() { - return Err("bondage too high to send value"); - } - - let to_balance = account_db.get_balance(dest); - if to_balance + value <= to_balance { - return Err("destination balance too high to receive value"); - } - - // TODO: an additional fee, based upon gaslimit/gasprice. - let gas_limit = 100_000; - - // TODO: consider storing upper-bound for contract's gas limit in fixed-length runtime - // code in contract itself and use that. - - // Our local overlay: Should be used for any transfers and creates that happen internally. - let mut overlay = OverlayAccountDb::new(account_db); - - if transactor != dest { - overlay.set_balance(transactor, from_balance - liability); - overlay.set_balance(dest, to_balance + value); - } - - let dest_code = overlay.get_code(dest); - let should_commit = if dest_code.is_empty() { - true - } else { - // TODO: logging (logs are just appended into a notable storage-based vector and - // cleared every block). - let mut staking_ext = StakingExt { - account_db: &mut overlay, - account: dest.clone(), - }; - contract::execute(&dest_code, &mut staking_ext, gas_limit).is_ok() - }; - - Ok(if should_commit { - Some(overlay.into_state()) - } else { - None - }) - } -} - -struct StakingExt<'a, 'b: 'a, T: Trait + 'b> { - account_db: &'a mut OverlayAccountDb<'b, T>, - account: T::AccountId, -} -impl<'a, 'b: 'a, T: Trait> contract::Ext for StakingExt<'a, 'b, T> { - type AccountId = T::AccountId; - type Balance = T::Balance; - - fn get_storage(&self, key: &[u8]) -> Option> { - self.account_db.get_storage(&self.account, key) - } - fn set_storage(&mut self, key: &[u8], value: Option>) { - self.account_db.set_storage(&self.account, key.to_vec(), value); - } - fn create(&mut self, code: &[u8], value: Self::Balance) { - if let Ok(Some(commit_state)) = - Module::::effect_create(&self.account, code, value, self.account_db) - { - self.account_db.merge(commit_state); - } - } - fn transfer(&mut self, to: &Self::AccountId, value: Self::Balance) { - if let Ok(Some(commit_state)) = - Module::::effect_transfer(&self.account, to, value, self.account_db) - { - self.account_db.merge(commit_state); - } - } -} - impl MakePayment for Module { fn make_payment(transactor: &T::AccountId, encoded_len: usize) -> Result { let b = Self::free_balance(transactor); - let transaction_fee = Self::transaction_base_fee() + Self::transaction_byte_fee() * >::sa(encoded_len); - if b < transaction_fee { + let transaction_fee = Self::transaction_base_fee() + Self::transaction_byte_fee() * >::sa(encoded_len as u64); + if b < transaction_fee + Self::existential_deposit() { return Err("not enough funds for transaction fee"); } >::insert(transactor, b - transaction_fee); Ok(()) } } - -#[cfg(any(feature = "std", test))] -pub struct DummyContractAddressFor; -#[cfg(any(feature = "std", test))] -impl ContractAddressFor for DummyContractAddressFor { - fn contract_address_for(_code: &[u8], origin: &u64) -> u64 { - origin + 1 - } -} - -#[cfg(any(feature = "std", test))] -pub struct GenesisConfig { - pub sessions_per_era: T::BlockNumber, - pub current_era: T::BlockNumber, - pub balances: Vec<(T::AccountId, T::Balance)>, - pub intentions: Vec, - pub validator_count: u64, - pub bonding_duration: T::BlockNumber, - pub transaction_base_fee: T::Balance, - pub transaction_byte_fee: T::Balance, - pub transfer_fee: T::Balance, - pub creation_fee: T::Balance, - pub contract_fee: T::Balance, - pub reclaim_rebate: T::Balance, - pub existential_deposit: T::Balance, -} - -#[cfg(any(feature = "std", test))] -impl GenesisConfig where T::AccountId: From { - pub fn simple() -> Self { - GenesisConfig { - sessions_per_era: T::BlockNumber::sa(2), - current_era: T::BlockNumber::sa(0), - balances: vec![(T::AccountId::from(1), T::Balance::sa(111))], - intentions: vec![T::AccountId::from(1), T::AccountId::from(2), T::AccountId::from(3)], - validator_count: 3, - bonding_duration: T::BlockNumber::sa(0), - transaction_base_fee: T::Balance::sa(0), - transaction_byte_fee: T::Balance::sa(0), - transfer_fee: T::Balance::sa(0), - creation_fee: T::Balance::sa(0), - contract_fee: T::Balance::sa(0), - existential_deposit: T::Balance::sa(0), - reclaim_rebate: T::Balance::sa(0), - } - } - - pub fn extended() -> Self { - GenesisConfig { - sessions_per_era: T::BlockNumber::sa(3), - current_era: T::BlockNumber::sa(1), - balances: vec![ - (T::AccountId::from(1), T::Balance::sa(10)), - (T::AccountId::from(2), T::Balance::sa(20)), - (T::AccountId::from(3), T::Balance::sa(30)), - (T::AccountId::from(4), T::Balance::sa(40)), - (T::AccountId::from(5), T::Balance::sa(50)), - (T::AccountId::from(6), T::Balance::sa(60)), - (T::AccountId::from(7), T::Balance::sa(1)) - ], - intentions: vec![T::AccountId::from(1), T::AccountId::from(2), T::AccountId::from(3)], - validator_count: 3, - bonding_duration: T::BlockNumber::sa(0), - transaction_base_fee: T::Balance::sa(1), - transaction_byte_fee: T::Balance::sa(0), - transfer_fee: T::Balance::sa(0), - creation_fee: T::Balance::sa(0), - contract_fee: T::Balance::sa(0), - existential_deposit: T::Balance::sa(0), - reclaim_rebate: T::Balance::sa(0), - } - } -} - -#[cfg(any(feature = "std", test))] -impl Default for GenesisConfig { - fn default() -> Self { - GenesisConfig { - sessions_per_era: T::BlockNumber::sa(1000), - current_era: T::BlockNumber::sa(0), - balances: vec![], - intentions: vec![], - validator_count: 0, - bonding_duration: T::BlockNumber::sa(1000), - transaction_base_fee: T::Balance::sa(0), - transaction_byte_fee: T::Balance::sa(0), - transfer_fee: T::Balance::sa(0), - creation_fee: T::Balance::sa(0), - contract_fee: T::Balance::sa(0), - existential_deposit: T::Balance::sa(0), - reclaim_rebate: T::Balance::sa(0), - } - } -} - -#[cfg(any(feature = "std", test))] -impl primitives::BuildStorage for GenesisConfig { - fn build_storage(self) -> runtime_io::TestExternalities { - use runtime_io::twox_128; - use codec::Slicable; - - let total_stake: T::Balance = self.balances.iter().fold(Zero::zero(), |acc, &(_, n)| acc + n); - - let mut r: runtime_io::TestExternalities = map![ - twox_128(>::key()).to_vec() => T::AccountIndex::sa(self.balances.len() / ENUM_SET_SIZE).encode(), - twox_128(>::key()).to_vec() => self.intentions.encode(), - twox_128(>::key()).to_vec() => self.sessions_per_era.encode(), - twox_128(>::key()).to_vec() => self.validator_count.encode(), - twox_128(>::key()).to_vec() => self.bonding_duration.encode(), - twox_128(>::key()).to_vec() => self.transaction_base_fee.encode(), - twox_128(>::key()).to_vec() => self.transaction_byte_fee.encode(), - twox_128(>::key()).to_vec() => self.transfer_fee.encode(), - twox_128(>::key()).to_vec() => self.creation_fee.encode(), - twox_128(>::key()).to_vec() => self.contract_fee.encode(), - twox_128(>::key()).to_vec() => self.existential_deposit.encode(), - twox_128(>::key()).to_vec() => self.reclaim_rebate.encode(), - twox_128(>::key()).to_vec() => self.current_era.encode(), - twox_128(>::key()).to_vec() => total_stake.encode() - ]; - - let ids: Vec<_> = self.balances.iter().map(|x| x.0.clone()).collect(); - for i in 0..(ids.len() + ENUM_SET_SIZE - 1) / ENUM_SET_SIZE { - r.insert(twox_128(&>::key_for(T::AccountIndex::sa(i))).to_vec(), - ids[i * ENUM_SET_SIZE..ids.len().min((i + 1) * ENUM_SET_SIZE)].to_owned().encode()); - } - for (who, value) in self.balances.into_iter() { - r.insert(twox_128(&>::key_for(who)).to_vec(), value.encode()); - } - r - } -} diff --git a/substrate/runtime/staking/src/mock.rs b/substrate/runtime/staking/src/mock.rs index c5a3e3e5af8d7..66119cef6bd92 100644 --- a/substrate/runtime/staking/src/mock.rs +++ b/substrate/runtime/staking/src/mock.rs @@ -23,7 +23,7 @@ use primitives::traits::{HasPublicAux, Identity}; use primitives::testing::{Digest, Header}; use substrate_primitives::H256; use runtime_io; -use {DummyContractAddressFor, GenesisConfig, Module, Trait, consensus, session, system}; +use {GenesisConfig, Module, Trait, consensus, session, system, timestamp}; // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] @@ -46,15 +46,20 @@ impl system::Trait for Test { } impl session::Trait for Test { type ConvertAccountIdToSessionKey = Identity; + type OnSessionChange = Staking; +} +impl timestamp::Trait for Test { + const TIMESTAMP_SET_POSITION: u32 = 0; + type Moment = u64; } impl Trait for Test { type Balance = u64; - type DetermineContractAddress = DummyContractAddressFor; type AccountIndex = u64; + type OnAccountKill = (); } -pub fn new_test_ext(ext_deposit: u64, session_length: u64, sessions_per_era: u64, current_era: u64, monied: bool) -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::::default().build_storage(); +pub fn new_test_ext(ext_deposit: u64, session_length: u64, sessions_per_era: u64, current_era: u64, monied: bool, reward: u64) -> runtime_io::TestExternalities { + let mut t = system::GenesisConfig::::default().build_storage().unwrap(); let balance_factor = if ext_deposit > 0 { 256 } else { @@ -63,15 +68,24 @@ pub fn new_test_ext(ext_deposit: u64, session_length: u64, sessions_per_era: u64 t.extend(consensus::GenesisConfig::{ code: vec![], authorities: vec![], - }.build_storage()); + }.build_storage().unwrap()); t.extend(session::GenesisConfig::{ session_length, validators: vec![10, 20], - }.build_storage()); + broken_percent_late: 30, + }.build_storage().unwrap()); t.extend(GenesisConfig::{ sessions_per_era, current_era, - balances: if monied { vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor)] } else { vec![] }, + balances: if monied { + if reward > 0 { + vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor), (10, balance_factor), (20, balance_factor)] + } else { + vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor)] + } + } else { + vec![(10, balance_factor), (20, balance_factor)] + }, intentions: vec![], validator_count: 2, bonding_duration: 3, @@ -80,12 +94,17 @@ pub fn new_test_ext(ext_deposit: u64, session_length: u64, sessions_per_era: u64 existential_deposit: ext_deposit, transfer_fee: 0, creation_fee: 0, - contract_fee: 0, reclaim_rebate: 0, - }.build_storage()); + session_reward: reward, + early_era_slash: if monied { 20 } else { 0 }, + }.build_storage().unwrap()); + t.extend(timestamp::GenesisConfig::{ + period: 5 + }.build_storage().unwrap()); t } pub type System = system::Module; pub type Session = session::Module; +pub type Timestamp = timestamp::Module; pub type Staking = Module; diff --git a/substrate/runtime/staking/src/tests.rs b/substrate/runtime/staking/src/tests.rs index 08479c0696ec7..ef9fa4faa5173 100644 --- a/substrate/runtime/staking/src/tests.rs +++ b/substrate/runtime/staking/src/tests.rs @@ -16,13 +16,88 @@ //! Tests for the module. +#![cfg(test)] + use super::*; use runtime_io::with_externalities; -use mock::*; +use mock::{Session, Staking, System, Timestamp, Test, new_test_ext}; + +#[test] +fn reward_should_work() { + with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { + assert_eq!(Staking::voting_balance(&10), 1); + assert_ok!(Staking::reward(&10, 10)); + assert_eq!(Staking::voting_balance(&10), 11); + }); +} + +#[test] +fn rewards_should_work() { + with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { + assert_eq!(Staking::era_length(), 9); + assert_eq!(Staking::sessions_per_era(), 3); + assert_eq!(Staking::last_era_length_change(), 0); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 0); + assert_eq!(Staking::voting_balance(&10), 1); + + System::set_block_number(3); + Timestamp::set_timestamp(15); // on time. + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 1); + assert_eq!(Staking::voting_balance(&10), 11); + System::set_block_number(6); + Timestamp::set_timestamp(31); // a little late + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 2); + assert_eq!(Staking::voting_balance(&10), 20); // less reward + System::set_block_number(9); + Timestamp::set_timestamp(50); // very late + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 1); + assert_eq!(Session::current_index(), 3); + assert_eq!(Staking::voting_balance(&10), 27); // much less reward + }); +} + +#[test] +fn slashing_should_work() { + with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { + assert_eq!(Staking::era_length(), 9); + assert_eq!(Staking::sessions_per_era(), 3); + assert_eq!(Staking::last_era_length_change(), 0); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 0); + assert_eq!(Staking::voting_balance(&10), 1); + + System::set_block_number(3); + Timestamp::set_timestamp(15); // on time. + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 1); + assert_eq!(Staking::voting_balance(&10), 11); + + System::set_block_number(6); + Timestamp::set_timestamp(30); // on time. + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 2); + assert_eq!(Staking::voting_balance(&10), 21); + + System::set_block_number(7); + Timestamp::set_timestamp(100); // way too late - early exit. + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 1); + assert_eq!(Session::current_index(), 3); + assert_eq!(Staking::voting_balance(&10), 1); + }); +} #[test] fn indexing_lookup_should_work() { - with_externalities(&mut new_test_ext(10, 1, 2, 0, true), || { + with_externalities(&mut new_test_ext(10, 1, 2, 0, true, 0), || { assert_eq!(Staking::lookup_index(0), Some(1)); assert_eq!(Staking::lookup_index(1), Some(2)); assert_eq!(Staking::lookup_index(2), Some(3)); @@ -33,7 +108,7 @@ fn indexing_lookup_should_work() { #[test] fn default_indexing_on_new_accounts_should_work() { - with_externalities(&mut new_test_ext(10, 1, 2, 0, true), || { + with_externalities(&mut new_test_ext(10, 1, 2, 0, true, 0), || { assert_eq!(Staking::lookup_index(4), None); assert_ok!(Staking::transfer(&1, 5.into(), 10)); assert_eq!(Staking::lookup_index(4), Some(5)); @@ -42,7 +117,7 @@ fn default_indexing_on_new_accounts_should_work() { #[test] fn dust_account_removal_should_work() { - with_externalities(&mut new_test_ext(256 * 10, 1, 2, 0, true), || { + with_externalities(&mut new_test_ext(256 * 10, 1, 2, 0, true, 0), || { System::inc_account_nonce(&2); assert_eq!(System::account_nonce(&2), 1); assert_eq!(Staking::voting_balance(&2), 256 * 20); @@ -56,7 +131,7 @@ fn dust_account_removal_should_work() { #[test] fn reclaim_indexing_on_new_accounts_should_work() { - with_externalities(&mut new_test_ext(256 * 1, 1, 2, 0, true), || { + with_externalities(&mut new_test_ext(256 * 1, 1, 2, 0, true, 0), || { assert_eq!(Staking::lookup_index(1), Some(2)); assert_eq!(Staking::lookup_index(4), None); assert_eq!(Staking::voting_balance(&2), 256 * 20); @@ -72,7 +147,7 @@ fn reclaim_indexing_on_new_accounts_should_work() { #[test] fn reserved_balance_should_prevent_reclaim_count() { - with_externalities(&mut new_test_ext(256 * 1, 1, 2, 0, true), || { + with_externalities(&mut new_test_ext(256 * 1, 1, 2, 0, true, 0), || { System::inc_account_nonce(&2); assert_eq!(Staking::lookup_index(1), Some(2)); assert_eq!(Staking::lookup_index(4), None); @@ -100,7 +175,7 @@ fn reserved_balance_should_prevent_reclaim_count() { #[test] fn staking_should_work() { - with_externalities(&mut new_test_ext(0, 1, 2, 0, true), || { + with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || { assert_eq!(Staking::era_length(), 2); assert_eq!(Staking::validator_count(), 2); assert_eq!(Staking::bonding_duration(), 3); @@ -111,66 +186,177 @@ fn staking_should_work() { assert_ok!(Staking::stake(&1)); assert_ok!(Staking::stake(&2)); assert_ok!(Staking::stake(&4)); - Staking::check_new_era(); + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 0); assert_eq!(Session::validators(), vec![10, 20]); // Block 2: New validator set now. System::set_block_number(2); - Staking::check_new_era(); + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 1); assert_eq!(Session::validators(), vec![4, 2]); // Block 3: Unstake highest, introduce another staker. No change yet. System::set_block_number(3); assert_ok!(Staking::stake(&3)); - assert_ok!(Staking::unstake(&4)); - Staking::check_new_era(); + assert_ok!(Staking::unstake(&4, Staking::intentions().iter().position(|&x| x == 4).unwrap() as u32)); + assert_eq!(Staking::current_era(), 1); + Session::check_rotate_session(); // Block 4: New era - validators change. System::set_block_number(4); - Staking::check_new_era(); + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 2); assert_eq!(Session::validators(), vec![3, 2]); // Block 5: Transfer stake from highest to lowest. No change yet. System::set_block_number(5); assert_ok!(Staking::transfer(&4, 1.into(), 40)); - Staking::check_new_era(); + Session::check_rotate_session(); // Block 6: Lowest now validator. System::set_block_number(6); - Staking::check_new_era(); + Session::check_rotate_session(); assert_eq!(Session::validators(), vec![1, 3]); // Block 7: Unstake three. No change yet. System::set_block_number(7); - assert_ok!(Staking::unstake(&3)); - Staking::check_new_era(); + assert_ok!(Staking::unstake(&3, Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32)); + Session::check_rotate_session(); assert_eq!(Session::validators(), vec![1, 3]); // Block 8: Back to one and two. System::set_block_number(8); - Staking::check_new_era(); + Session::check_rotate_session(); assert_eq!(Session::validators(), vec![1, 2]); }); } +#[test] +fn nominating_and_rewards_should_work() { + with_externalities(&mut new_test_ext(0, 1, 1, 0, true, 10), || { + assert_eq!(Staking::era_length(), 1); + assert_eq!(Staking::validator_count(), 2); + assert_eq!(Staking::bonding_duration(), 3); + assert_eq!(Session::validators(), vec![10, 20]); + + System::set_block_number(1); + assert_ok!(Staking::stake(&1)); + assert_ok!(Staking::stake(&2)); + assert_ok!(Staking::stake(&3)); + assert_ok!(Staking::nominate(&4, 1.into())); + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 1); + assert_eq!(Session::validators(), vec![1, 3]); // 4 + 1, 3 + assert_eq!(Staking::voting_balance(&1), 10); + assert_eq!(Staking::voting_balance(&2), 20); + assert_eq!(Staking::voting_balance(&3), 30); + assert_eq!(Staking::voting_balance(&4), 40); + + System::set_block_number(2); + assert_ok!(Staking::unnominate(&4, 0)); + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 2); + assert_eq!(Session::validators(), vec![3, 2]); + assert_eq!(Staking::voting_balance(&1), 12); + assert_eq!(Staking::voting_balance(&2), 20); + assert_eq!(Staking::voting_balance(&3), 40); + assert_eq!(Staking::voting_balance(&4), 48); + + System::set_block_number(3); + assert_ok!(Staking::stake(&4)); + assert_ok!(Staking::unstake(&3, Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32)); + assert_ok!(Staking::nominate(&3, 1.into())); + Session::check_rotate_session(); + assert_eq!(Session::validators(), vec![1, 4]); + assert_eq!(Staking::voting_balance(&1), 12); + assert_eq!(Staking::voting_balance(&2), 30); + assert_eq!(Staking::voting_balance(&3), 50); + assert_eq!(Staking::voting_balance(&4), 48); + + System::set_block_number(4); + Session::check_rotate_session(); + assert_eq!(Staking::voting_balance(&1), 13); + assert_eq!(Staking::voting_balance(&2), 30); + assert_eq!(Staking::voting_balance(&3), 58); + assert_eq!(Staking::voting_balance(&4), 58); + }); +} + +#[test] +fn nominating_slashes_should_work() { + with_externalities(&mut new_test_ext(0, 2, 2, 0, true, 10), || { + assert_eq!(Staking::era_length(), 4); + assert_eq!(Staking::validator_count(), 2); + assert_eq!(Staking::bonding_duration(), 3); + assert_eq!(Session::validators(), vec![10, 20]); + + System::set_block_number(2); + Session::check_rotate_session(); + + Timestamp::set_timestamp(15); + System::set_block_number(4); + assert_ok!(Staking::stake(&1)); + assert_ok!(Staking::stake(&3)); + assert_ok!(Staking::nominate(&2, 3.into())); + assert_ok!(Staking::nominate(&4, 1.into())); + Session::check_rotate_session(); + + assert_eq!(Staking::current_era(), 1); + assert_eq!(Session::validators(), vec![1, 3]); // 1 + 4, 3 + 2 + assert_eq!(Staking::voting_balance(&1), 10); + assert_eq!(Staking::voting_balance(&2), 20); + assert_eq!(Staking::voting_balance(&3), 30); + assert_eq!(Staking::voting_balance(&4), 40); + + System::set_block_number(5); + Timestamp::set_timestamp(100); // late + assert_eq!(Session::blocks_remaining(), 1); + assert!(Session::broken_validation()); + Session::check_rotate_session(); + + assert_eq!(Staking::current_era(), 2); + assert_eq!(Staking::voting_balance(&1), 0); + assert_eq!(Staking::voting_balance(&2), 20); + assert_eq!(Staking::voting_balance(&3), 10); + assert_eq!(Staking::voting_balance(&4), 30); + }); +} + +#[test] +fn double_staking_should_fail() { + with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || { + System::set_block_number(1); + assert_ok!(Staking::stake(&1)); + assert_noop!(Staking::stake(&1), "Cannot stake if already staked."); + assert_noop!(Staking::nominate(&1, 1.into()), "Cannot nominate if already staked."); + assert_ok!(Staking::nominate(&2, 1.into())); + assert_noop!(Staking::stake(&2), "Cannot stake if already nominating."); + assert_noop!(Staking::nominate(&2, 1.into()), "Cannot nominate if already nominating."); + }); +} + #[test] fn staking_eras_work() { - with_externalities(&mut new_test_ext(0, 1, 2, 0, true), || { + with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || { assert_eq!(Staking::era_length(), 2); assert_eq!(Staking::sessions_per_era(), 2); assert_eq!(Staking::last_era_length_change(), 0); assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 0); // Block 1: No change. System::set_block_number(1); - Staking::check_new_era(); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 1); assert_eq!(Staking::sessions_per_era(), 2); assert_eq!(Staking::last_era_length_change(), 0); assert_eq!(Staking::current_era(), 0); // Block 2: Simple era change. System::set_block_number(2); - Staking::check_new_era(); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 2); assert_eq!(Staking::sessions_per_era(), 2); assert_eq!(Staking::last_era_length_change(), 0); assert_eq!(Staking::current_era(), 1); @@ -178,35 +364,41 @@ fn staking_eras_work() { // Block 3: Schedule an era length change; no visible changes. System::set_block_number(3); assert_ok!(Staking::set_sessions_per_era(3)); - Staking::check_new_era(); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 3); assert_eq!(Staking::sessions_per_era(), 2); assert_eq!(Staking::last_era_length_change(), 0); assert_eq!(Staking::current_era(), 1); // Block 4: Era change kicks in. System::set_block_number(4); - Staking::check_new_era(); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 4); assert_eq!(Staking::sessions_per_era(), 3); assert_eq!(Staking::last_era_length_change(), 4); assert_eq!(Staking::current_era(), 2); // Block 5: No change. System::set_block_number(5); - Staking::check_new_era(); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 5); assert_eq!(Staking::sessions_per_era(), 3); assert_eq!(Staking::last_era_length_change(), 4); assert_eq!(Staking::current_era(), 2); // Block 6: No change. System::set_block_number(6); - Staking::check_new_era(); + assert!(!Session::broken_validation()); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 6); assert_eq!(Staking::sessions_per_era(), 3); assert_eq!(Staking::last_era_length_change(), 4); assert_eq!(Staking::current_era(), 2); // Block 7: Era increment. System::set_block_number(7); - Staking::check_new_era(); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 7); assert_eq!(Staking::sessions_per_era(), 3); assert_eq!(Staking::last_era_length_change(), 4); assert_eq!(Staking::current_era(), 3); @@ -215,7 +407,7 @@ fn staking_eras_work() { #[test] fn staking_balance_works() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 42); assert_eq!(Staking::free_balance(&1), 42); assert_eq!(Staking::reserved_balance(&1), 0); @@ -228,7 +420,7 @@ fn staking_balance_works() { #[test] fn staking_balance_transfer_works() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 111); assert_ok!(Staking::transfer(&1, 2.into(), 69)); assert_eq!(Staking::voting_balance(&1), 42); @@ -238,7 +430,7 @@ fn staking_balance_transfer_works() { #[test] fn staking_balance_transfer_when_bonded_should_not_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 111); assert_ok!(Staking::stake(&1)); assert_noop!(Staking::transfer(&1, 2.into(), 69), "bondage too high to send value"); @@ -247,7 +439,7 @@ fn staking_balance_transfer_when_bonded_should_not_work() { #[test] fn reserving_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 111); assert_eq!(Staking::voting_balance(&1), 111); @@ -264,7 +456,7 @@ fn reserving_balance_should_work() { #[test] fn staking_balance_transfer_when_reserved_should_not_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 111); assert_ok!(Staking::reserve(&1, 69)); assert_noop!(Staking::transfer(&1, 2.into(), 69), "balance too low to send value"); @@ -273,7 +465,7 @@ fn staking_balance_transfer_when_reserved_should_not_work() { #[test] fn deducting_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 111); assert_ok!(Staking::reserve(&1, 69)); assert_eq!(Staking::free_balance(&1), 42); @@ -282,7 +474,7 @@ fn deducting_balance_should_work() { #[test] fn deducting_balance_when_bonded_should_not_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 111); >::insert(1, 2); System::set_block_number(1); @@ -293,7 +485,7 @@ fn deducting_balance_when_bonded_should_not_work() { #[test] fn refunding_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 42); >::insert(1, 69); Staking::unreserve(&1, 69); @@ -304,7 +496,7 @@ fn refunding_balance_should_work() { #[test] fn slashing_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 111); assert_ok!(Staking::reserve(&1, 69)); assert!(Staking::slash(&1, 69).is_none()); @@ -315,7 +507,7 @@ fn slashing_balance_should_work() { #[test] fn slashing_incomplete_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 42); assert_ok!(Staking::reserve(&1, 21)); assert!(Staking::slash(&1, 69).is_some()); @@ -326,7 +518,7 @@ fn slashing_incomplete_balance_should_work() { #[test] fn unreserving_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 111); assert_ok!(Staking::reserve(&1, 111)); Staking::unreserve(&1, 42); @@ -337,7 +529,7 @@ fn unreserving_balance_should_work() { #[test] fn slashing_reserved_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 111); assert_ok!(Staking::reserve(&1, 111)); assert!(Staking::slash_reserved(&1, 42).is_none()); @@ -348,7 +540,7 @@ fn slashing_reserved_balance_should_work() { #[test] fn slashing_incomplete_reserved_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 111); assert_ok!(Staking::reserve(&1, 42)); assert!(Staking::slash_reserved(&1, 69).is_some()); @@ -359,7 +551,7 @@ fn slashing_incomplete_reserved_balance_should_work() { #[test] fn transferring_reserved_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 110); >::insert(2, 1); assert_ok!(Staking::reserve(&1, 110)); @@ -373,7 +565,7 @@ fn transferring_reserved_balance_should_work() { #[test] fn transferring_reserved_balance_to_nonexistent_should_fail() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 111); assert_ok!(Staking::reserve(&1, 111)); assert_noop!(Staking::transfer_reserved(&1, &2, 42), "beneficiary account must pre-exist"); @@ -382,7 +574,7 @@ fn transferring_reserved_balance_to_nonexistent_should_fail() { #[test] fn transferring_incomplete_reserved_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false), || { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { >::insert(1, 110); >::insert(2, 1); assert_ok!(Staking::reserve(&1, 41)); @@ -393,3 +585,19 @@ fn transferring_incomplete_reserved_balance_should_work() { assert_eq!(Staking::free_balance(&2), 42); }); } + +#[test] +fn transferring_too_high_value_should_not_panic() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + >::insert(1, u64::max_value()); + >::insert(2, 1); + + assert_err!( + Staking::transfer(&1, 2.into(), u64::max_value()), + "destination balance too high to receive value" + ); + + assert_eq!(Staking::free_balance(&1), u64::max_value()); + assert_eq!(Staking::free_balance(&2), 1); + }); +} diff --git a/substrate/runtime/system/src/lib.rs b/substrate/runtime/system/src/lib.rs index d8a7f9c1a0792..002c540590557 100644 --- a/substrate/runtime/system/src/lib.rs +++ b/substrate/runtime/system/src/lib.rs @@ -39,25 +39,25 @@ extern crate safe_mix; use rstd::prelude::*; use primitives::traits::{self, CheckEqual, SimpleArithmetic, SimpleBitOps, Zero, One, Bounded, - Hashing, Member, MaybeDisplay}; + Hash, Member, MaybeDisplay}; use runtime_support::{StorageValue, StorageMap, Parameter}; use safe_mix::TripletMix; #[cfg(any(feature = "std", test))] use rstd::marker::PhantomData; #[cfg(any(feature = "std", test))] -use codec::Slicable; +use codec::Encode; #[cfg(any(feature = "std", test))] use runtime_io::{twox_128, TestExternalities}; /// Compute the extrinsics root of a list of extrinsics. -pub fn extrinsics_root(extrinsics: &[E]) -> H::Output { - extrinsics_data_root::(extrinsics.iter().map(codec::Slicable::encode).collect()) +pub fn extrinsics_root(extrinsics: &[E]) -> H::Output { + extrinsics_data_root::(extrinsics.iter().map(codec::Encode::encode).collect()) } /// Compute the extrinsics root of a list of extrinsics. -pub fn extrinsics_data_root(xts: Vec>) -> H::Output { +pub fn extrinsics_data_root(xts: Vec>) -> H::Output { let xts = xts.iter().map(Vec::as_slice).collect::>(); H::enumerated_trie_root(&xts) } @@ -66,12 +66,11 @@ pub trait Trait: Eq + Clone { type Index: Parameter + Member + Default + MaybeDisplay + SimpleArithmetic + Copy; type BlockNumber: Parameter + Member + MaybeDisplay + SimpleArithmetic + Default + Bounded + Copy + rstd::hash::Hash; type Hash: Parameter + Member + MaybeDisplay + SimpleBitOps + Default + Copy + CheckEqual + rstd::hash::Hash + AsRef<[u8]>; - type Hashing: Hashing; + type Hashing: Hash; type Digest: Parameter + Member + Default + traits::Digest; type AccountId: Parameter + Member + MaybeDisplay + Ord + Default; type Header: Parameter + traits::Header< Number = Self::BlockNumber, - Hashing = Self::Hashing, Hash = Self::Hash, Digest = Self::Digest >; @@ -193,6 +192,9 @@ impl Module { } #[cfg(any(feature = "std", test))] +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] pub struct GenesisConfig(PhantomData); #[cfg(any(feature = "std", test))] @@ -205,16 +207,15 @@ impl Default for GenesisConfig { #[cfg(any(feature = "std", test))] impl primitives::BuildStorage for GenesisConfig { - fn build_storage(self) -> runtime_io::TestExternalities { - use runtime_io::twox_128; - use codec::Slicable; - - map![ - twox_128(&>::key_for(T::BlockNumber::zero())).to_vec() => [69u8; 32].encode(), - twox_128(>::key()).to_vec() => 1u64.encode(), - twox_128(>::key()).to_vec() => [69u8; 32].encode(), - twox_128(>::key()).to_vec() => [0u8; 32].encode(), - twox_128(>::key()).to_vec() => [0u8; 4].encode() - ] + fn build_storage(self) -> Result { + use codec::Encode; + + Ok(map![ + Self::hash(&>::key_for(T::BlockNumber::zero())).to_vec() => [69u8; 32].encode(), + Self::hash(>::key()).to_vec() => 1u64.encode(), + Self::hash(>::key()).to_vec() => [69u8; 32].encode(), + Self::hash(>::key()).to_vec() => [0u8; 32].encode(), + Self::hash(>::key()).to_vec() => [0u8; 4].encode() + ]) } } diff --git a/substrate/runtime/timestamp/Cargo.toml b/substrate/runtime/timestamp/Cargo.toml index d90f961b6c69b..1b5637a2c33a6 100644 --- a/substrate/runtime/timestamp/Cargo.toml +++ b/substrate/runtime/timestamp/Cargo.toml @@ -14,6 +14,7 @@ substrate-runtime-primitives = { path = "../primitives", default_features = fals substrate-codec = { path = "../../codec", default_features = false } substrate-primitives = { path = "../../primitives", default_features = false } substrate-runtime-system = { path = "../system", default_features = false } +substrate-runtime-consensus = { path = "../consensus", default_features = false } [dev-dependencies] substrate-runtime-io = { path = "../../runtime-io", default_features = true } diff --git a/substrate/runtime/timestamp/src/lib.rs b/substrate/runtime/timestamp/src/lib.rs index 73f30c27aeb13..0d20bd6b58e97 100644 --- a/substrate/runtime/timestamp/src/lib.rs +++ b/substrate/runtime/timestamp/src/lib.rs @@ -35,17 +35,20 @@ extern crate serde_derive; extern crate substrate_primitives; extern crate substrate_runtime_primitives as runtime_primitives; extern crate substrate_runtime_system as system; +extern crate substrate_runtime_consensus as consensus; extern crate substrate_codec as codec; use runtime_support::{StorageValue, Parameter}; use runtime_support::dispatch::Result; -use runtime_primitives::traits::{HasPublicAux, Executable, MaybeEmpty}; +use runtime_primitives::traits::{Executable, MaybeEmpty, SimpleArithmetic, As, Zero}; -pub trait Trait: HasPublicAux + system::Trait { +pub trait Trait: consensus::Trait where + ::PublicAux: MaybeEmpty +{ // the position of the required timestamp-set extrinsic. - const SET_POSITION: u32; + const TIMESTAMP_SET_POSITION: u32; - type Value: Parameter + Default; + type Moment: Parameter + Default + SimpleArithmetic + As; } decl_module! { @@ -53,36 +56,48 @@ decl_module! { #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum Call where aux: T::PublicAux { - fn set(aux, now: T::Value) -> Result = 0; + fn set(aux, now: T::Moment) -> Result = 0; } } decl_storage! { trait Store for Module; - pub Now get(now): b"tim:val" => required T::Value; + pub Now get(now): b"tim:val" => required T::Moment; + // The minimum (and advised) period between blocks. + pub BlockPeriod get(block_period): b"tim:block_period" => required T::Moment; // Did the timestamp get updated in this block? DidUpdate: b"tim:did" => default bool; } impl Module { - pub fn get() -> T::Value { - ::Now::get() + pub fn get() -> T::Moment { + Self::now() } /// Set the current time. - fn set(aux: &T::PublicAux, now: T::Value) -> Result { + fn set(aux: &T::PublicAux, now: T::Moment) -> Result { assert!(aux.is_empty()); assert!(!::DidUpdate::exists(), "Timestamp must be updated only once in the block"); assert!( - >::extrinsic_index() == T::SET_POSITION, + >::extrinsic_index() == T::TIMESTAMP_SET_POSITION, "Timestamp extrinsic must be at position {} in the block", - T::SET_POSITION + T::TIMESTAMP_SET_POSITION + ); + assert!( + Self::now().is_zero() || now >= Self::now() + Self::block_period(), + "Timestamp but increment by at least between sequential blocks" ); ::Now::put(now); ::DidUpdate::put(true); Ok(()) } + + /// Set the timestamp to something in particular. Only used for tests. + #[cfg(any(feature = "std", test))] + pub fn set_timestamp(now: T::Moment) { + ::Now::put(now); + } } impl Executable for Module { @@ -92,20 +107,31 @@ impl Executable for Module { } #[cfg(any(feature = "std", test))] -#[derive(Default)] +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] pub struct GenesisConfig { - pub now: T::Value, + pub period: T::Moment, +} + +#[cfg(any(feature = "std", test))] +impl Default for GenesisConfig { + fn default() -> Self { + GenesisConfig { + period: T::Moment::sa(5), + } + } } #[cfg(any(feature = "std", test))] impl runtime_primitives::BuildStorage for GenesisConfig { - fn build_storage(self) -> runtime_primitives::StorageMap { - use runtime_io::twox_128; - use codec::Slicable; - map![ - twox_128(>::key()).to_vec() => self.now.encode() - ] + fn build_storage(self) -> ::std::result::Result { + use codec::Encode; + Ok(map![ + Self::hash(>::key()).to_vec() => self.period.encode(), + Self::hash(>::key()).to_vec() => T::Moment::sa(0).encode() + ]) } } @@ -114,7 +140,6 @@ mod tests { use super::*; use runtime_io::with_externalities; - use runtime_support::storage::StorageValue; use substrate_primitives::H256; use runtime_primitives::BuildStorage; use runtime_primitives::traits::{HasPublicAux, BlakeTwo256}; @@ -134,21 +159,50 @@ mod tests { type AccountId = u64; type Header = Header; } + impl consensus::Trait for Test { + type PublicAux = u64; + type SessionKey = u64; + } impl Trait for Test { - const SET_POSITION: u32 = 0; - type Value = u64; + const TIMESTAMP_SET_POSITION: u32 = 0; + type Moment = u64; } type Timestamp = Module; #[test] fn timestamp_works() { - let mut t = system::GenesisConfig::::default().build_storage(); - t.extend(GenesisConfig:: { now: 42 }.build_storage()); + let mut t = system::GenesisConfig::::default().build_storage().unwrap(); + t.extend(GenesisConfig:: { period: 0 }.build_storage().unwrap()); with_externalities(&mut t, || { - assert_eq!(::Now::get(), 42); + Timestamp::set_timestamp(42); assert_ok!(Timestamp::aux_dispatch(Call::set(69), &0)); assert_eq!(Timestamp::now(), 69); }); } + + #[test] + #[should_panic(expected = "Timestamp must be updated only once in the block")] + fn double_timestamp_should_fail() { + let mut t = system::GenesisConfig::::default().build_storage().unwrap(); + t.extend(GenesisConfig:: { period: 5 }.build_storage().unwrap()); + + with_externalities(&mut t, || { + Timestamp::set_timestamp(42); + assert_ok!(Timestamp::aux_dispatch(Call::set(69), &0)); + let _ = Timestamp::aux_dispatch(Call::set(70), &0); + }); + } + + #[test] + #[should_panic(expected = "Timestamp but increment by at least between sequential blocks")] + fn block_period_is_enforced() { + let mut t = system::GenesisConfig::::default().build_storage().unwrap(); + t.extend(GenesisConfig:: { period: 5 }.build_storage().unwrap()); + + with_externalities(&mut t, || { + Timestamp::set_timestamp(42); + let _ = Timestamp::aux_dispatch(Call::set(46), &0); + }); + } } diff --git a/substrate/runtime/version/Cargo.toml b/substrate/runtime/version/Cargo.toml new file mode 100644 index 0000000000000..febbe10d31070 --- /dev/null +++ b/substrate/runtime/version/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "substrate-runtime-version" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +serde = { version = "1.0", default_features = false } +serde_derive = { version = "1.0", optional = true } +substrate-codec = { path = "../../codec", default_features = false } +substrate-runtime-std = { path = "../../runtime-std", default_features = false } +substrate-runtime-support = { path = "../../runtime-support", default_features = false } + +[features] +default = ["std"] +std = [ + "serde/std", + "serde_derive", + "substrate-codec/std", + "substrate-runtime-std/std", + "substrate-runtime-support/std", +] diff --git a/substrate/runtime/version/src/lib.rs b/substrate/runtime/version/src/lib.rs new file mode 100644 index 0000000000000..4f4031220f9bf --- /dev/null +++ b/substrate/runtime/version/src/lib.rs @@ -0,0 +1,175 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo 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. + +// Substrate Demo 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 Substrate Demo. If not, see . + +//! Version module for runtime; Provide a function that returns runtime version. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +extern crate serde; + +#[cfg(feature = "std")] +#[macro_use] +extern crate serde_derive; + +#[allow(unused_imports)] +#[macro_use] +extern crate substrate_runtime_std as rstd; + +#[macro_use] +extern crate substrate_runtime_support as runtime_support; + +extern crate substrate_codec as codec; + +use rstd::prelude::*; +use codec::{Encode, Output}; +#[cfg(feature = "std")] +use codec::{Decode, Input}; +#[cfg(feature = "std")] +use std::borrow::Cow; + +#[cfg(feature = "std")] +use std::fmt; + +#[cfg(feature = "std")] +pub type VersionString = ::std::borrow::Cow<'static, str>; +#[cfg(not(feature = "std"))] +pub type VersionString = &'static str; + +#[cfg(feature = "std")] +#[macro_export] +macro_rules! ver_str { + ( $y:expr ) => {{ ::std::borrow::Cow::Borrowed($y) }} +} + +#[cfg(not(feature = "std"))] +#[macro_export] +macro_rules! ver_str { + ( $y:expr ) => {{ $y }} +} + +/// Runtime version. +/// This should not be thought of as classic Semver (major/minor/tiny). +/// This triplet have different semantics and mis-interpretation could cause problems. +/// In particular: bug fixes should result in an increment of `spec_version` and possibly `authoring_version`, +/// absolutely not `impl_version` since they change the semantics of the runtime. +#[derive(Clone)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +pub struct RuntimeVersion { + /// Identifies the different Substrate runtimes. There'll be at least polkadot and demo. + /// A different on-chain spec_name to that of the native runtime would normally result + /// in node not attempting to sync or author blocks. + pub spec_name: VersionString, + + /// Name of the implementation of the spec. This is of little consequence for the node + /// and serves only to differentiate code of different implementation teams. For this + /// codebase, it will be parity-polkadot. If there were a non-Rust implementation of the + /// Polkadot runtime (e.g. C++), then it would identify itself with an accordingly different + /// `impl_name`. + pub impl_name: VersionString, + + /// `authoring_version` is the version of the authorship interface. An authoring node + /// will not attempt to author blocks unless this is equal to its native runtime. + pub authoring_version: u32, + + /// Version of the runtime specification. A full-node will not attempt to use its native + /// runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`, + /// `spec_version` and `authoring_version` are the same between Wasm and native. + pub spec_version: u32, + + /// Version of the implementation of the specification. Nodes are free to ignore this; it + /// serves only as an indication that the code is different; as long as the other two versions + /// are the same then while the actual code may be different, it is nonetheless required to + /// do the same thing. + /// Non-consensus-breaking optimisations are about the only changes that could be made which + /// would result in only the `impl_version` changing. + pub impl_version: u32, +} + +// TODO: remove this after PoC-2 +#[cfg(feature = "std")] +impl Default for RuntimeVersion { + fn default() -> RuntimeVersion { + RuntimeVersion { + spec_name: ver_str!("polkadot"), + impl_name: ver_str!("parity-polkadot"), + authoring_version: 0, + spec_version: 0, + impl_version: 0, + } + } +} + +#[cfg(feature = "std")] +impl fmt::Display for RuntimeVersion { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}-{}:{}({}-{})", self.spec_name, self.spec_version, self.authoring_version, self.impl_name, self.impl_version) + } +} + +#[cfg(feature = "std")] +impl RuntimeVersion { + /// Check if this version matches other version for calling into runtime. + pub fn can_call_with(&self, other: &RuntimeVersion) -> bool { + self.spec_version == other.spec_version && + self.spec_name == other.spec_name && + self.authoring_version == other.authoring_version + } + + /// Check if this version matches other version for authoring blocks. + pub fn can_author_with(&self, other: &RuntimeVersion) -> bool { + self.authoring_version == other.authoring_version && + self.spec_name == other.spec_name + } +} + +impl Encode for RuntimeVersion { + fn encode_to(&self, dest: &mut T) { + dest.push(self.spec_name.as_bytes()); + dest.push(self.impl_name.as_bytes()); + dest.push(&self.authoring_version); + dest.push(&self.spec_version); + dest.push(&self.impl_version); + } +} + +#[cfg(feature = "std")] +impl Decode for RuntimeVersion { + fn decode(value: &mut I) -> Option { + Some(RuntimeVersion { + spec_name: Cow::Owned(String::from_utf8_lossy(&Vec::decode(value)?).into()), + impl_name: Cow::Owned(String::from_utf8_lossy(&Vec::decode(value)?).into()), + authoring_version: Decode::decode(value)?, + spec_version: Decode::decode(value)?, + impl_version: Decode::decode(value)?, + }) + } +} + +pub trait Trait { + const VERSION: RuntimeVersion; +} + +decl_module! { + pub struct Module; +} + +impl Module { + /// Get runtime version. + pub fn version() -> RuntimeVersion { + T::VERSION.clone() + } +} diff --git a/substrate/service/Cargo.toml b/substrate/service/Cargo.toml new file mode 100644 index 0000000000000..a7e1d65c88425 --- /dev/null +++ b/substrate/service/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "substrate-service" +version = "0.3.0" +authors = ["Parity Technologies "] + +[dependencies] +futures = "0.1.17" +parking_lot = "0.4" +error-chain = "0.12" +lazy_static = "1.0" +log = "0.3" +slog = "^2" +tokio = "0.1.7" +exit-future = "0.1" +serde = "1.0" +serde_json = "1.0" +serde_derive = "1.0" +target_info = "0.1" +substrate-keystore = { path = "../../substrate/keystore" } +substrate-runtime-io = { path = "../../substrate/runtime-io" } +substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" } +substrate-primitives = { path = "../../substrate/primitives" } +substrate-network = { path = "../../substrate/network" } +substrate-client = { path = "../../substrate/client" } +substrate-client-db = { path = "../../substrate/client/db" } +substrate-codec = { path = "../../substrate/codec" } +substrate-executor = { path = "../../substrate/executor" } +substrate-extrinsic-pool = { path = "../../substrate/extrinsic-pool" } +substrate-rpc = { path = "../../substrate/rpc" } +substrate-rpc-servers = { path = "../../substrate/rpc-servers" } +substrate-telemetry = { path = "../../substrate/telemetry" } diff --git a/substrate/service/src/chain_ops.rs b/substrate/service/src/chain_ops.rs new file mode 100644 index 0000000000000..aeefda6a676a0 --- /dev/null +++ b/substrate/service/src/chain_ops.rs @@ -0,0 +1,139 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +//! Chain utilities. + +use std::{self, io::{Read, Write}}; +use futures::Future; +use serde_json; + +use client::BlockOrigin; +use runtime_primitives::generic::{SignedBlock, BlockId}; +use runtime_primitives::traits::{As}; +use components::{ServiceFactory, FactoryFullConfiguration, FactoryBlockNumber, RuntimeGenesis}; +use new_client; +use codec::{Decode, Encode}; +use error; +use chain_spec::ChainSpec; + +/// Export a range of blocks to a binary stream. +pub fn export_blocks(config: FactoryFullConfiguration, exit: E, mut output: W, from: FactoryBlockNumber, to: Option>, json: bool) -> error::Result<()> + where F: ServiceFactory, E: Future + Send + 'static, W: Write, +{ + let client = new_client::(config)?; + let mut block = from; + + let last = match to { + Some(v) if v == As::sa(0) => As::sa(1), + Some(v) => v, + None => client.info()?.chain.best_number, + }; + + if last < block { + return Err("Invalid block range specified".into()); + } + + let (exit_send, exit_recv) = std::sync::mpsc::channel(); + ::std::thread::spawn(move || { + let _ = exit.wait(); + let _ = exit_send.send(()); + }); + info!("Exporting blocks from #{} to #{}", block, last); + if !json { + output.write(&(last - block + As::sa(1)).encode())?; + } + + loop { + if exit_recv.try_recv().is_ok() { + break; + } + match client.block(&BlockId::number(block))? { + Some(block) => { + if json { + serde_json::to_writer(&mut output, &block).map_err(|e| format!("Eror writing JSON: {}", e))?; + } else { + output.write(&block.encode())?; + } + }, + None => break, + } + if block.as_() % 10000 == 0 { + info!("#{}", block); + } + if block == last { + break; + } + block += As::sa(1); + } + Ok(()) +} + +/// Import blocks from a binary stream. +pub fn import_blocks(config: FactoryFullConfiguration, exit: E, mut input: R) -> error::Result<()> + where F: ServiceFactory, E: Future + Send + 'static, R: Read, +{ + let client = new_client::(config)?; + + let (exit_send, exit_recv) = std::sync::mpsc::channel(); + ::std::thread::spawn(move || { + let _ = exit.wait(); + let _ = exit_send.send(()); + }); + + let count: u32 = Decode::decode(&mut input).ok_or("Error reading file")?; + info!("Importing {} blocks", count); + let mut block = 0; + for _ in 0 .. count { + if exit_recv.try_recv().is_ok() { + break; + } + match SignedBlock::decode(&mut input) { + Some(block) => { + let header = client.check_justification(block.block.header, block.justification.into())?; + client.import_block(BlockOrigin::File, header, Some(block.block.extrinsics))?; + }, + None => { + warn!("Error reading block data."); + break; + } + } + block += 1; + if block % 1000 == 0 { + info!("#{}", block); + } + } + info!("Imported {} blocks. Best: #{}", block, client.info()?.chain.best_number); + + Ok(()) +} + +/// Revert the chain. +pub fn revert_chain(config: FactoryFullConfiguration, blocks: FactoryBlockNumber) -> error::Result<()> + where F: ServiceFactory, +{ + let client = new_client::(config)?; + let reverted = client.revert(blocks)?; + let info = client.info()?.chain; + info!("Reverted {} blocks. Best: #{} ({})", reverted, info.best_number, info.best_hash); + Ok(()) +} + +/// Build a chain spec json +pub fn build_spec(spec: ChainSpec, raw: bool) -> error::Result + where G: RuntimeGenesis, +{ + Ok(spec.to_json(raw)?) +} diff --git a/substrate/service/src/chain_spec.rs b/substrate/service/src/chain_spec.rs new file mode 100644 index 0000000000000..6ccd0545b4435 --- /dev/null +++ b/substrate/service/src/chain_spec.rs @@ -0,0 +1,170 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +//! Substrate chain configurations. + +use std::collections::HashMap; +use std::fs::File; +use std::path::PathBuf; +use primitives::storage::{StorageKey, StorageData}; +use runtime_primitives::{BuildStorage, StorageMap}; +use serde_json as json; +use components::RuntimeGenesis; + +enum GenesisSource { + File(PathBuf), + Embedded(&'static [u8]), + Factory(fn() -> G), +} + +impl GenesisSource { + fn resolve(&self) -> Result, String> { + #[derive(Serialize, Deserialize)] + struct GenesisContainer { + genesis: Genesis, + } + + match *self { + GenesisSource::File(ref path) => { + let file = File::open(path).map_err(|e| format!("Error opening spec file: {}", e))?; + let genesis: GenesisContainer = json::from_reader(file).map_err(|e| format!("Error parsing spec file: {}", e))?; + Ok(genesis.genesis) + }, + GenesisSource::Embedded(buf) => { + let genesis: GenesisContainer = json::from_reader(buf).map_err(|e| format!("Error parsing embedded file: {}", e))?; + Ok(genesis.genesis) + }, + GenesisSource::Factory(f) => Ok(Genesis::Runtime(f())), + } + } +} + +impl<'a, G: RuntimeGenesis> BuildStorage for &'a ChainSpec { + fn build_storage(self) -> Result { + match self.genesis.resolve()? { + Genesis::Runtime(gc) => gc.build_storage(), + Genesis::Raw(map) => Ok(map.into_iter().map(|(k, v)| (k.0, v.0)).collect()), + } + } +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +enum Genesis { + Runtime(G), + Raw(HashMap), +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct ChainSpecFile { + pub name: String, + pub id: String, + pub boot_nodes: Vec, + pub telemetry_url: Option, +} + +/// A configuration of a chain. Can be used to build a genesis block. +pub struct ChainSpec { + spec: ChainSpecFile, + genesis: GenesisSource, +} + +impl ChainSpec { + pub fn boot_nodes(&self) -> &[String] { + &self.spec.boot_nodes + } + + pub fn name(&self) -> &str { + &self.spec.name + } + + pub fn id(&self) -> &str { + &self.spec.id + } + + pub fn telemetry_url(&self) -> Option<&str> { + self.spec.telemetry_url.as_ref().map(String::as_str) + } + + /// Parse json content into a `ChainSpec` + pub fn from_embedded(json: &'static [u8]) -> Result { + let spec = json::from_slice(json).map_err(|e| format!("Error parsing spec file: {}", e))?; + Ok(ChainSpec { + spec, + genesis: GenesisSource::Embedded(json), + }) + } + + /// Parse json file into a `ChainSpec` + pub fn from_json_file(path: PathBuf) -> Result { + let file = File::open(&path).map_err(|e| format!("Error opening spec file: {}", e))?; + let spec = json::from_reader(file).map_err(|e| format!("Error parsing spec file: {}", e))?; + Ok(ChainSpec { + spec, + genesis: GenesisSource::File(path), + }) + } + + /// Create hardcoded spec. + pub fn from_genesis( + name: &str, + id: &str, + constructor: fn() -> G, + boot_nodes: Vec, + telemetry_url: Option<&str> + ) -> Self + { + let spec = ChainSpecFile { + name: name.to_owned(), + id: id.to_owned(), + boot_nodes: boot_nodes, + telemetry_url: telemetry_url.map(str::to_owned), + }; + ChainSpec { + spec, + genesis: GenesisSource::Factory(constructor), + } + } + + /// Dump to json string. + pub fn to_json(self, raw: bool) -> Result { + #[derive(Serialize, Deserialize)] + struct Container { + #[serde(flatten)] + spec: ChainSpecFile, + #[serde(flatten)] + genesis: Genesis, + + }; + let genesis = match (raw, self.genesis.resolve()?) { + (true, Genesis::Runtime(g)) => { + let storage = g.build_storage()?.into_iter() + .map(|(k, v)| (StorageKey(k), StorageData(v))) + .collect(); + + Genesis::Raw(storage) + }, + (_, genesis) => genesis, + }; + let spec = Container { + spec: self.spec, + genesis, + }; + json::to_string_pretty(&spec).map_err(|e| format!("Error generating spec json: {}", e)) + } +} diff --git a/substrate/service/src/components.rs b/substrate/service/src/components.rs new file mode 100644 index 0000000000000..058ea13dc7b84 --- /dev/null +++ b/substrate/service/src/components.rs @@ -0,0 +1,254 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +//! Polkadot service components. + +use std::sync::Arc; +use std::marker::PhantomData; +use serde::{Serialize, de::DeserializeOwned}; +use chain_spec::ChainSpec; +use client_db; +use client::{self, Client}; +use error; +use network::{self, OnDemand}; +use substrate_executor::{NativeExecutor, NativeExecutionDispatch}; +use extrinsic_pool::{txpool::Options as ExtrinsicPoolOptions, api::ExtrinsicPool as ExtrinsicPoolApi}; +use runtime_primitives::{traits::Block as BlockT, traits::Header as HeaderT, generic::BlockId, BuildStorage}; +use config::Configuration; + +// Type aliases. +// These exist mainly to avoid typing `::Foo` all over the code. +/// Network service type for a factory. +pub type NetworkService = network::Service< + ::Block, + ::NetworkProtocol +>; + +/// Code executor type for a factory. +pub type CodeExecutor = NativeExecutor<::RuntimeDispatch>; + +/// Full client backend type for a factory. +pub type FullBackend = client_db::Backend<::Block>; + +/// Full client executor type for a factory. +pub type FullExecutor = client::LocalCallExecutor< + client_db::Backend<::Block>, + CodeExecutor +>; + +/// Light client backend type for a factory. +pub type LightBackend = client::light::backend::Backend< + client_db::light::LightStorage<::Block>, + network::OnDemand<::Block, + NetworkService> +>; + +/// Light client executor type for a factory. +pub type LightExecutor = client::light::call_executor::RemoteCallExecutor< + client::light::blockchain::Blockchain< + client_db::light::LightStorage<::Block>, + network::OnDemand<::Block, NetworkService> + >, + network::OnDemand<::Block, NetworkService> +>; + +/// Full client type for a factory. +pub type FullClient = Client, FullExecutor, ::Block>; + +/// Light client type for a factory. +pub type LightClient = Client, LightExecutor, ::Block>; + +/// `ChainSpec` specialization for a factory. +pub type FactoryChainSpec = ChainSpec<::Genesis>; + +/// `Genesis` specialization for a factory. +pub type FactoryGenesis = ::Genesis; + +/// `Block` type for a factory. +pub type FactoryBlock = ::Block; + +/// `Number` type for a factory. +pub type FactoryBlockNumber = < as BlockT>::Header as HeaderT>::Number; + +/// Full `Configuration` type for a factory. +pub type FactoryFullConfiguration = Configuration<::Configuration, FactoryGenesis>; + +/// Client type for `Components`. +pub type ComponentClient = Client< + ::Backend, + ::Executor, + FactoryBlock<::Factory> +>; + +/// Block type for `Components` +pub type ComponentBlock = <::Factory as ServiceFactory>::Block; + +/// Extrinsic pool API type for `Components`. +pub type PoolApi = <::ExtrinsicPool as ExtrinsicPool>>::Api; + +/// A set of traits for the runtime genesis config. +pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {} +impl RuntimeGenesis for T {} + +/// A collection of types and methods to build a service on top of the substrate service. +pub trait ServiceFactory { + /// Block type. + type Block: BlockT; + /// Network protocol extensions. + type NetworkProtocol: network::specialization::Specialization; + /// Chain runtime. + type RuntimeDispatch: NativeExecutionDispatch + Send + Sync + 'static; + /// Extrinsic pool type for the full client. + type FullExtrinsicPool: ExtrinsicPool; + /// Extrinsic pool type for the light client. + type LightExtrinsicPool: ExtrinsicPool; + /// Genesis configuration for the runtime. + type Genesis: RuntimeGenesis; + /// Other configuration for service members. + type Configuration: Default; + + /// Network protocol id. + const NETWORK_PROTOCOL_ID: network::ProtocolId; + + //TODO: replace these with a constructor trait. that ExtrinsicPool implements. + /// Extrinsic pool constructor for the full client. + fn build_full_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc>) + -> Result; + /// Extrinsic pool constructor for the light client. + fn build_light_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc>) + -> Result; + + /// Build network protocol. + fn build_network_protocol(config: &FactoryFullConfiguration) + -> Result; +} + +// TODO: move this to substrate-extrinsic-pool +/// Extrinsic pool bridge. +pub trait ExtrinsicPool: network::TransactionPool + Send + Sync + 'static { + type Api: ExtrinsicPoolApi, Block::Hash>; + + /// Update the pool after a new block has been imported. + fn prune_imported(&self, hash: &Block::Hash); + /// Returns underlying API. + fn api(&self) -> Arc; +} + +/// A collection of types and function to generalise over full / light client type. +pub trait Components { + /// Associated service factory. + type Factory: ServiceFactory; + /// Client backend. + type Backend: 'static + client::backend::Backend>; + /// Client executor. + type Executor: 'static + client::CallExecutor> + Send + Sync; + /// Extrinsic pool type. + type ExtrinsicPool: ExtrinsicPool>; + + /// Create client. + fn build_client( + config: &FactoryFullConfiguration, + executor: CodeExecutor, + ) + -> Result<( + Arc>, + Option, NetworkService>>> + ), error::Error>; + + /// Create extrinsic pool. + fn build_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc>) + -> Result; +} + +/// A struct that implement `Components` for the full client. +pub struct FullComponents { + _factory: PhantomData, +} + +impl Components for FullComponents { + type Factory = Factory; + type Executor = FullExecutor; + type Backend = FullBackend; + type ExtrinsicPool = ::FullExtrinsicPool; + + fn build_client( + config: &FactoryFullConfiguration, + executor: CodeExecutor, + ) + -> Result<( + Arc>, + Option, NetworkService>>> + ), error::Error> + { + let db_settings = client_db::DatabaseSettings { + cache_size: None, + path: config.database_path.as_str().into(), + pruning: config.pruning.clone(), + }; + Ok((Arc::new(client_db::new_client(db_settings, executor, &config.chain_spec, config.execution_strategy)?), None)) + } + + fn build_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc>) + -> Result + { + Factory::build_full_extrinsic_pool(config, client) + } +} + +/// A struct that implement `Components` for the light client. +pub struct LightComponents { + _factory: PhantomData, +} + +impl Components for LightComponents + where + <::Block as BlockT>::Hash: Into<[u8; 32]>, +{ + type Factory = Factory; + type Executor = LightExecutor; + type Backend = LightBackend; + type ExtrinsicPool = ::LightExtrinsicPool; + + fn build_client( + config: &FactoryFullConfiguration, + executor: CodeExecutor, + ) + -> Result<( + Arc>, + Option, + NetworkService>>> + ), error::Error> + { + let db_settings = client_db::DatabaseSettings { + cache_size: None, + path: config.database_path.as_str().into(), + pruning: config.pruning.clone(), + }; + let db_storage = client_db::light::LightStorage::new(db_settings)?; + let light_blockchain = client::light::new_light_blockchain(db_storage); + let fetch_checker = Arc::new(client::light::new_fetch_checker(light_blockchain.clone(), executor)); + let fetcher = Arc::new(network::OnDemand::new(fetch_checker)); + let client_backend = client::light::new_light_backend(light_blockchain, fetcher.clone()); + let client = client::light::new_light(client_backend, fetcher.clone(), &config.chain_spec)?; + Ok((Arc::new(client), Some(fetcher))) + } + + fn build_extrinsic_pool(config: ExtrinsicPoolOptions, client: Arc>) + -> Result + { + Factory::build_light_extrinsic_pool(config, client) + } +} diff --git a/substrate/service/src/config.rs b/substrate/service/src/config.rs new file mode 100644 index 0000000000000..b3e42c9b6c0f5 --- /dev/null +++ b/substrate/service/src/config.rs @@ -0,0 +1,121 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see .? + +//! Service configuration. + +use std::net::SocketAddr; +use extrinsic_pool; +use chain_spec::ChainSpec; +pub use client::ExecutionStrategy; +pub use network::Roles; +pub use network::NetworkConfiguration; +pub use client_db::PruningMode; +use runtime_primitives::BuildStorage; +use serde::{Serialize, de::DeserializeOwned}; +use target_info::Target; + +/// Service configuration. +pub struct Configuration { + /// Implementation name + pub impl_name: &'static str, + /// Implementation version + pub impl_version: &'static str, + /// Git commit if any. + pub impl_commit: &'static str, + /// Node roles. + pub roles: Roles, + /// Extrinsic pool configuration. + pub extrinsic_pool: extrinsic_pool::txpool::Options, + /// Network configuration. + pub network: NetworkConfiguration, + /// Path to key files. + pub keystore_path: String, + /// Path to the database. + pub database_path: String, + /// Pruning settings. + pub pruning: PruningMode, + /// Additional key seeds. + pub keys: Vec, + /// Chain configuration. + pub chain_spec: ChainSpec, + /// Custom configuration. + pub custom: C, + /// Telemetry server URL, optional - only `Some` if telemetry reporting is enabled + pub telemetry: Option, + /// Node name. + pub name: String, + /// Execution strategy. + pub execution_strategy: ExecutionStrategy, + /// Minimum number of heap pages to allocate for Wasm execution. + pub min_heap_pages: usize, + /// Maximum number of heap pages to allocate for Wasm execution. + pub max_heap_pages: usize, + /// RPC over HTTP binding address. `None` if disabled. + pub rpc_http: Option, + /// RPC over Websockets binding address. `None` if disabled. + pub rpc_ws: Option, + /// Telemetry service URL. `None` if disabled. + pub telemetry_url: Option, +} + +impl Configuration { + /// Create default config for given chain spec. + pub fn default_with_spec(chain_spec: ChainSpec) -> Self { + let mut configuration = Configuration { + impl_name: "parity-substrate", + impl_version: "0.0.0", + impl_commit: "", + chain_spec, + name: Default::default(), + roles: Roles::FULL, + extrinsic_pool: Default::default(), + network: Default::default(), + keystore_path: Default::default(), + database_path: Default::default(), + keys: Default::default(), + custom: Default::default(), + telemetry: Default::default(), + pruning: PruningMode::default(), + execution_strategy: ExecutionStrategy::Both, + min_heap_pages: 8, + max_heap_pages: 1024, + rpc_http: None, + rpc_ws: None, + telemetry_url: None, + }; + configuration.network.boot_nodes = configuration.chain_spec.boot_nodes().to_vec(); + configuration.telemetry_url = configuration.chain_spec.telemetry_url().map(str::to_owned); + configuration + } + + /// Returns platform info + pub fn platform() -> String { + let env = Target::env(); + let env_dash = if env.is_empty() { "" } else { "-" }; + format!("{}-{}{}{}", Target::arch(), Target::os(), env_dash, env) + } + + /// Returns full version string. + pub fn full_version(&self) -> String { + let commit_dash = if self.impl_commit.is_empty() { "" } else { "-" }; + format!("{}{}{}-{}", self.impl_version, commit_dash, self.impl_commit, Self::platform()) + } + + /// Implementation id and version. + pub fn client_id(&self) -> String { + format!("{}/v{}", self.impl_name, self.full_version()) + } +} diff --git a/polkadot/service/src/error.rs b/substrate/service/src/error.rs similarity index 74% rename from polkadot/service/src/error.rs rename to substrate/service/src/error.rs index fbb6981407df8..abc09cb0c3c45 100644 --- a/polkadot/service/src/error.rs +++ b/substrate/service/src/error.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. +// This file is part of Substrate. -// Polkadot is free software: you can redistribute it and/or modify +// Substrate 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. -// Polkadot is distributed in the hope that it will be useful, +// Substrate 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 Polkadot. If not, see . +// along with Substrate. If not, see . //! Errors that can occur during the service operation. @@ -21,6 +21,9 @@ use network; use keystore; error_chain! { + foreign_links { + Io(::std::io::Error) #[doc="IO error"]; + } links { Client(client::error::Error, client::error::ErrorKind) #[doc="Client error"]; Network(network::error::Error, network::error::ErrorKind) #[doc="Network error"]; diff --git a/substrate/service/src/lib.rs b/substrate/service/src/lib.rs new file mode 100644 index 0000000000000..fca2c4d05834e --- /dev/null +++ b/substrate/service/src/lib.rs @@ -0,0 +1,324 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +//! Substrate service. Starts a thread that spins the network, the client and the extrinsic pool. +//! Manages communication between them. + +#![warn(unused_extern_crates)] + +extern crate futures; +extern crate exit_future; +extern crate serde; +extern crate serde_json; +extern crate substrate_keystore as keystore; +extern crate substrate_primitives as primitives; +extern crate substrate_runtime_primitives as runtime_primitives; +extern crate substrate_network as network; +extern crate substrate_executor; +extern crate substrate_client as client; +extern crate substrate_client_db as client_db; +extern crate substrate_codec as codec; +extern crate substrate_extrinsic_pool as extrinsic_pool; +extern crate substrate_rpc; +extern crate substrate_rpc_servers as rpc; +extern crate target_info; +extern crate tokio; + +#[macro_use] +extern crate substrate_telemetry as tel; +#[macro_use] +extern crate error_chain; +#[macro_use] +extern crate slog; // needed until we can reexport `slog_info` from `substrate_telemetry` +#[macro_use] +extern crate log; +#[macro_use] +extern crate serde_derive; + +mod components; +mod error; +mod config; +mod chain_spec; +pub mod chain_ops; + +use std::io; +use std::net::SocketAddr; +use std::sync::Arc; +use futures::prelude::*; +use keystore::Store as Keystore; +use client::BlockchainEvents; +use network::ManageNetwork; +use runtime_primitives::traits::{Header, As}; +use exit_future::Signal; +use tokio::runtime::TaskExecutor; +use substrate_executor::NativeExecutor; + +pub use self::error::{ErrorKind, Error}; +pub use config::{Configuration, Roles, PruningMode}; +pub use chain_spec::ChainSpec; +pub use extrinsic_pool::txpool::{Options as ExtrinsicPoolOptions}; +pub use extrinsic_pool::api::{ExtrinsicPool as ExtrinsicPoolApi}; +pub use client::ExecutionStrategy; + +pub use components::{ServiceFactory, FullBackend, FullExecutor, LightBackend, + LightExecutor, ExtrinsicPool, Components, PoolApi, ComponentClient, + ComponentBlock, FullClient, LightClient, FullComponents, LightComponents, + CodeExecutor, NetworkService, FactoryChainSpec, FactoryBlock, + FactoryFullConfiguration, RuntimeGenesis, FactoryGenesis, +}; + +/// Substrate service. +pub struct Service { + client: Arc>, + network: Arc>, + extrinsic_pool: Arc, + keystore: Keystore, + signal: Option, + _rpc_http: Option, + _rpc_ws: Option, + _telemetry: Option, +} + +/// Creates bare client without any networking. +pub fn new_client(config: FactoryFullConfiguration) + -> Result>>, error::Error> +{ + let executor = NativeExecutor::with_heap_pages(config.min_heap_pages, config.max_heap_pages); + let (client, _) = components::FullComponents::::build_client( + &config, + executor, + )?; + Ok(client) +} + +impl Service + where + Components: components::Components, +{ + /// Creates a new service. + pub fn new( + config: FactoryFullConfiguration, + task_executor: TaskExecutor, + ) + -> Result + { + let (signal, exit) = ::exit_future::signal(); + + // Create client + let executor = NativeExecutor::with_heap_pages(config.min_heap_pages, config.max_heap_pages); + + let mut keystore = Keystore::open(config.keystore_path.as_str().into())?; + for seed in &config.keys { + keystore.generate_from_seed(seed)?; + } + + if keystore.contents()?.is_empty() { + let key = keystore.generate("")?; + info!("Generated a new keypair: {:?}", key.public()); + } + + let (client, on_demand) = Components::build_client(&config, executor)?; + let best_header = client.best_block_header()?; + + let version = config.full_version(); + info!("Best block: #{}", best_header.number()); + telemetry!("node.start"; "height" => best_header.number().as_(), "best" => ?best_header.hash()); + + let network_protocol = ::build_network_protocol(&config)?; + let extrinsic_pool = Arc::new( + Components::build_extrinsic_pool(config.extrinsic_pool, client.clone())? + ); + let extrinsic_pool_adapter = extrinsic_pool.clone(); + + let network_params = network::Params { + config: network::ProtocolConfig { + roles: config.roles, + }, + network_config: config.network, + chain: client.clone(), + on_demand: on_demand.clone() + .map(|d| d as Arc>>), + transaction_pool: extrinsic_pool_adapter, + specialization: network_protocol, + }; + + let network = network::Service::new(network_params, Components::Factory::NETWORK_PROTOCOL_ID)?; + on_demand.map(|on_demand| on_demand.set_service_link(Arc::downgrade(&network))); + + network.start_network(); + + { + // block notifications + let network = network.clone(); + let txpool = extrinsic_pool.clone(); + + let events = client.import_notification_stream() + .for_each(move |notification| { + network.on_block_imported(notification.hash, ¬ification.header); + txpool.prune_imported(¬ification.hash); + Ok(()) + }) + .select(exit.clone()) + .then(|_| Ok(())); + task_executor.spawn(events); + } + + { + // extrinsic notifications + let network = network.clone(); + let events = extrinsic_pool.api().import_notification_stream() + // TODO [ToDr] Consider throttling? + .for_each(move |_| { + network.trigger_repropagate(); + Ok(()) + }) + .select(exit.clone()) + .then(|_| Ok(())); + + task_executor.spawn(events); + } + + // RPC + let rpc_config = RpcConfig { + chain_name: config.chain_spec.name().to_string(), + impl_name: config.impl_name, + impl_version: config.impl_version, + }; + + let (rpc_http, rpc_ws) = { + let handler = || { + let client = client.clone(); + let chain = rpc::apis::chain::Chain::new(client.clone(), task_executor.clone()); + let author = rpc::apis::author::Author::new(client.clone(), extrinsic_pool.api(), task_executor.clone()); + rpc::rpc_handler::, _, _, _, _>( + client, + chain, + author, + rpc_config.clone(), + ) + }; + ( + maybe_start_server(config.rpc_http, |address| rpc::start_http(address, handler()))?, + maybe_start_server(config.rpc_ws, |address| rpc::start_ws(address, handler()))?, + ) + }; + + // Telemetry + let telemetry = match config.telemetry_url { + Some(url) => { + let name = config.name.clone(); + let impl_name = config.impl_name.to_owned(); + let version = version.clone(); + let chain_name = config.chain_spec.name().to_owned(); + Some(tel::init_telemetry(tel::TelemetryConfig { + url: url, + on_connect: Box::new(move || { + telemetry!("system.connected"; + "name" => name.clone(), + "implementation" => impl_name.clone(), + "version" => version.clone(), + "config" => "", + "chain" => chain_name.clone(), + ); + }), + })) + }, + None => None, + }; + + Ok(Service { + client: client, + network: network, + extrinsic_pool: extrinsic_pool, + signal: Some(signal), + keystore: keystore, + _rpc_http: rpc_http, + _rpc_ws: rpc_ws, + _telemetry: telemetry, + }) + } + + /// Get shared client instance. + pub fn client(&self) -> Arc> { + self.client.clone() + } + + /// Get shared network instance. + pub fn network(&self) -> Arc> { + self.network.clone() + } + + /// Get shared extrinsic pool instance. + pub fn extrinsic_pool(&self) -> Arc> { + self.extrinsic_pool.api() + } + + /// Get shared keystore. + pub fn keystore(&self) -> &Keystore { + &self.keystore + } +} + +impl Drop for Service where Components: components::Components { + fn drop(&mut self) { + debug!(target: "service", "Substrate service shutdown"); + + self.network.stop_network(); + + if let Some(signal) = self.signal.take() { + signal.fire(); + } + } +} + +fn maybe_start_server(address: Option, start: F) -> Result, io::Error> where + F: Fn(&SocketAddr) -> Result, +{ + Ok(match address { + Some(mut address) => Some(start(&address) + .or_else(|e| match e.kind() { + io::ErrorKind::AddrInUse | + io::ErrorKind::PermissionDenied => { + warn!("Unable to bind server to {}. Trying random port.", address); + address.set_port(0); + start(&address) + }, + _ => Err(e), + })?), + None => None, + }) +} + +#[derive(Clone)] +struct RpcConfig { + chain_name: String, + impl_name: &'static str, + impl_version: &'static str, +} + +impl substrate_rpc::system::SystemApi for RpcConfig { + fn system_name(&self) -> substrate_rpc::system::error::Result { + Ok(self.impl_name.into()) + } + + fn system_version(&self) -> substrate_rpc::system::error::Result { + Ok(self.impl_version.into()) + } + + fn system_chain(&self) -> substrate_rpc::system::error::Result { + Ok(self.chain_name.clone()) + } +} diff --git a/substrate/state-db/Cargo.toml b/substrate/state-db/Cargo.toml new file mode 100644 index 0000000000000..734fc27f483b9 --- /dev/null +++ b/substrate/state-db/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "substrate-state-db" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +parking_lot = "0.5" +log = "0.4" +substrate-primitives = { path = "../../substrate/primitives" } +substrate-codec = { path = "../../substrate/codec" } + +[dev-dependencies] +env_logger = "0.4" diff --git a/substrate/state-db/src/lib.rs b/substrate/state-db/src/lib.rs new file mode 100644 index 0000000000000..590c5c1a8986a --- /dev/null +++ b/substrate/state-db/src/lib.rs @@ -0,0 +1,393 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! State database maintenance. Handles finalization and pruning in the database. The input to +//! this module is a `ChangeSet` which is basicall a list of key-value pairs (trie nodes) that +//! were added or deleted during block execution. +//! +//! # Finalization. +//! Finalization window tracks a tree of blocks identified by header hash. The in-memory +//! overlay allows to get any node that was was inserted in any any of the blocks within the window. +//! The tree is journaled to the backing database and rebuilt on startup. +//! Finalization function select one root from the top of the tree and discards all other roots and +//! their subtrees. +//! +//! # Pruning. +//! See `RefWindow` for pruning algorithm details. `StateDb` prunes on each finalization until pruning +//! constraints are satisfied. +//! + +#[macro_use] extern crate log; +extern crate parking_lot; +extern crate substrate_codec as codec; +extern crate substrate_primitives as primitives; + +mod unfinalized; +mod pruning; +#[cfg(test)] mod test; + +use std::fmt; +use parking_lot::RwLock; +use codec::Codec; +use std::collections::HashSet; +use unfinalized::UnfinalizedOverlay; +use pruning::RefWindow; + +/// Database value type. +pub type DBValue = Vec; + +/// Basic set of requirements for the Block hash and node key types. +pub trait Hash: Send + Sync + Sized + Eq + PartialEq + Clone + Default + fmt::Debug + Codec + std::hash::Hash + 'static {} +impl Hash for T {} + +/// Backend database trait. Read-only. +pub trait MetaDb { + type Error: fmt::Debug; + + /// Get meta value, such as the journal. + fn get_meta(&self, key: &[u8]) -> Result, Self::Error>; +} + + +/// Backend database trait. Read-only. +pub trait HashDb { + type Hash: Hash; + type Error: fmt::Debug; + + /// Get state trie node. + fn get(&self, key: &Self::Hash) -> Result, Self::Error>; +} + +/// Error type. +/// Error type. +pub enum Error { + /// Database backend error. + Db(E), + /// `Codec` decoding error. + Decoding, +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match self { + Error::Db(e) => e.fmt(f), + Error::Decoding => write!(f, "Error decoding slicable value"), + } + } +} + +/// A set of state node changes. +#[derive(Default, Debug, Clone)] +pub struct ChangeSet { + /// Inserted nodes. + pub inserted: Vec<(H, DBValue)>, + /// Delted nodes. + pub deleted: Vec, +} + + +/// A set of changes to the backing database. +#[derive(Default, Debug, Clone)] +pub struct CommitSet { + /// State node changes. + pub data: ChangeSet, + /// Metadata changes. + pub meta: ChangeSet>, +} + +/// Pruning contraints. If none are specified pruning is +#[derive(Default, Debug, Clone)] +pub struct Constraints { + /// Maximum blocks. Defaults to 0 when unspecified, effectively keeping only unfinalized states. + pub max_blocks: Option, + /// Maximum memory in the pruning overlay. + pub max_mem: Option, +} + +/// Pruning mode. +#[derive(Debug, Clone)] +pub enum PruningMode { + /// Maintain a pruning window. + Constrained(Constraints), + /// No pruning. Finalization is a no-op. + ArchiveAll, + /// Finalization discards unfinalized nodes. All the finalized nodes are kept in the DB. + ArchiveCanonical, +} + +impl PruningMode { + /// Create a mode that keeps given number of blocks. + pub fn keep_blocks(n: u32) -> PruningMode { + PruningMode::Constrained(Constraints { + max_blocks: Some(n), + max_mem: None, + }) + } +} + +impl Default for PruningMode { + fn default() -> Self { + PruningMode::keep_blocks(256) + } +} + +fn to_meta_key(suffix: &[u8], data: &S) -> Vec { + let mut buffer = data.encode(); + buffer.extend(suffix); + buffer +} + +struct StateDbSync { + mode: PruningMode, + unfinalized: UnfinalizedOverlay, + pruning: Option>, + pinned: HashSet, +} + +impl StateDbSync { + pub fn new(mode: PruningMode, db: &D) -> Result, Error> { + trace!("StateDb settings: {:?}", mode); + let unfinalized: UnfinalizedOverlay = UnfinalizedOverlay::new(db)?; + let pruning: Option> = match mode { + PruningMode::Constrained(Constraints { + max_mem: Some(_), + .. + }) => unimplemented!(), + PruningMode::Constrained(_) => Some(RefWindow::new(db)?), + PruningMode::ArchiveAll | PruningMode::ArchiveCanonical => None, + }; + Ok(StateDbSync { + mode, + unfinalized, + pruning: pruning, + pinned: Default::default(), + }) + } + + pub fn insert_block(&mut self, hash: &BlockHash, number: u64, parent_hash: &BlockHash, mut changeset: ChangeSet) -> CommitSet { + if number == 0 { + return CommitSet { + data: changeset, + meta: Default::default(), + } + } + match self.mode { + PruningMode::ArchiveAll => { + changeset.deleted.clear(); + // write changes immediatelly + CommitSet { + data: changeset, + meta: Default::default(), + } + }, + PruningMode::Constrained(_) | PruningMode::ArchiveCanonical => { + self.unfinalized.insert(hash, number, parent_hash, changeset) + } + } + } + + pub fn finalize_block(&mut self, hash: &BlockHash) -> CommitSet { + // clear the temporary overlay from the previous finalization. + self.unfinalized.clear_overlay(); + let mut commit = match self.mode { + PruningMode::ArchiveAll => { + CommitSet::default() + }, + PruningMode::ArchiveCanonical => { + let mut commit = self.unfinalized.finalize(hash); + commit.data.deleted.clear(); + commit + }, + PruningMode::Constrained(_) => { + self.unfinalized.finalize(hash) + }, + }; + if let Some(ref mut pruning) = self.pruning { + pruning.note_finalized(hash, &mut commit); + } + self.prune(&mut commit); + commit + } + + pub fn best_finalized(&self) -> u64 { + return self.unfinalized.last_finalized_block_number() + } + + fn prune(&mut self, commit: &mut CommitSet) { + if let (&mut Some(ref mut pruning), &PruningMode::Constrained(ref constraints)) = (&mut self.pruning, &self.mode) { + loop { + if pruning.window_size() <= constraints.max_blocks.unwrap_or(0) as u64 { + break; + } + + if constraints.max_mem.map_or(false, |m| pruning.mem_used() > m) { + break; + } + + let pinned = &self.pinned; + if pruning.next_hash().map_or(false, |h| pinned.contains(&h)) { + break; + } + + pruning.prune_one(commit); + } + } + } + + /// Revert all unfinalized blocks with the best block number. + /// Returns a database commit or `None` if not possible. + /// For archive an empty commit set is returned. + pub fn revert_one(&mut self) -> Option> { + match self.mode { + PruningMode::ArchiveAll => { + Some(CommitSet::default()) + }, + PruningMode::ArchiveCanonical | PruningMode::Constrained(_) => { + self.unfinalized.revert_one() + }, + } + } + + pub fn pin(&mut self, hash: &BlockHash) { + self.pinned.insert(hash.clone()); + } + + pub fn unpin(&mut self, hash: &BlockHash) { + self.pinned.remove(hash); + } + + pub fn get>(&self, key: &Key, db: &D) -> Result, Error> { + if let Some(value) = self.unfinalized.get(key) { + return Ok(Some(value)); + } + db.get(key).map_err(|e| Error::Db(e)) + } +} + +/// State DB maintenance. See module description. +/// Can be shared across threads. +pub struct StateDb { + db: RwLock>, +} + +impl StateDb { + /// Creates a new instance. Does not expect any metadata in the database. + pub fn new(mode: PruningMode, db: &D) -> Result, Error> { + Ok(StateDb { + db: RwLock::new(StateDbSync::new(mode, db)?) + }) + } + + /// Add a new unfinalized block. + pub fn insert_block(&self, hash: &BlockHash, number: u64, parent_hash: &BlockHash, changeset: ChangeSet) -> CommitSet { + self.db.write().insert_block(hash, number, parent_hash, changeset) + } + + /// Finalize a previously inserted block. + pub fn finalize_block(&self, hash: &BlockHash) -> CommitSet { + self.db.write().finalize_block(hash) + } + + /// Prevents pruning of specified block and its descendants. + pub fn pin(&self, hash: &BlockHash) { + self.db.write().pin(hash) + } + + /// Allows pruning of specified block. + pub fn unpin(&self, hash: &BlockHash) { + self.db.write().unpin(hash) + } + + /// Get a value from unfinalized/pruning overlay or the backing DB. + pub fn get>(&self, key: &Key, db: &D) -> Result, Error> { + self.db.read().get(key, db) + } + + /// Revert all unfinalized blocks with the best block number. + /// Returns a database commit or `None` if not possible. + /// For archive an empty commit set is returned. + pub fn revert_one(&self) -> Option> { + self.db.write().revert_one() + } + + /// Returns last finalized block number. + pub fn best_finalized(&self) -> u64 { + return self.db.read().best_finalized() + } + +} + +#[cfg(test)] +mod tests { + use primitives::H256; + use {StateDb, PruningMode, Constraints}; + use test::{make_db, make_changeset, TestDb}; + + fn make_test_db(settings: PruningMode) -> (TestDb, StateDb) { + let mut db = make_db(&[91, 921, 922, 93, 94]); + let state_db = StateDb::new(settings, &db).unwrap(); + + db.commit(&state_db.insert_block(&H256::from(1), 1, &H256::from(0), make_changeset(&[1], &[91]))); + db.commit(&state_db.insert_block(&H256::from(21), 2, &H256::from(1), make_changeset(&[21], &[921, 1]))); + db.commit(&state_db.insert_block(&H256::from(22), 2, &H256::from(1), make_changeset(&[22], &[922]))); + db.commit(&state_db.insert_block(&H256::from(3), 3, &H256::from(21), make_changeset(&[3], &[93]))); + db.commit(&state_db.finalize_block(&H256::from(1))); + db.commit(&state_db.insert_block(&H256::from(4), 4, &H256::from(3), make_changeset(&[4], &[94]))); + db.commit(&state_db.finalize_block(&H256::from(21))); + db.commit(&state_db.finalize_block(&H256::from(3))); + + (db, state_db) + } + + #[test] + fn full_archive_keeps_everything() { + let (db, _) = make_test_db(PruningMode::ArchiveAll); + assert!(db.data_eq(&make_db(&[1, 21, 22, 3, 4, 91, 921, 922, 93, 94]))); + } + + #[test] + fn canonical_archive_keeps_canonical() { + let (db, _) = make_test_db(PruningMode::ArchiveCanonical); + assert!(db.data_eq(&make_db(&[1, 21, 3, 91, 921, 922, 93, 94]))); + } + + #[test] + fn prune_window_0() { + let (db, _) = make_test_db(PruningMode::Constrained(Constraints { + max_blocks: Some(0), + max_mem: None, + })); + assert!(db.data_eq(&make_db(&[21, 3, 922, 94]))); + } + + #[test] + fn prune_window_1() { + let (db, _) = make_test_db(PruningMode::Constrained(Constraints { + max_blocks: Some(1), + max_mem: None, + })); + assert!(db.data_eq(&make_db(&[21, 3, 922, 93, 94]))); + } + + #[test] + fn prune_window_2() { + let (db, _) = make_test_db(PruningMode::Constrained(Constraints { + max_blocks: Some(2), + max_mem: None, + })); + assert!(db.data_eq(&make_db(&[1, 21, 3, 921, 922, 93, 94]))); + } +} diff --git a/substrate/state-db/src/pruning.rs b/substrate/state-db/src/pruning.rs new file mode 100644 index 0000000000000..afe3f8bad1fd4 --- /dev/null +++ b/substrate/state-db/src/pruning.rs @@ -0,0 +1,280 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Pruning window. +//! +//! For each block we maintain a list of nodes pending deletion. +//! There is also a global index of node key to block number. +//! If a node is re-inserted into the window it gets removed from +//! the death list. +//! The changes are journaled in the DB. + +use std::collections::{HashMap, HashSet, VecDeque}; +use codec::{Decode, Encode, self}; +use {CommitSet, Error, MetaDb, to_meta_key, Hash}; + +const LAST_PRUNED: &[u8] = b"last_pruned"; +const PRUNING_JOURNAL: &[u8] = b"pruning_journal"; + +/// See module documentation. +pub struct RefWindow { + death_rows: VecDeque>, + death_index: HashMap, + pending_number: u64, +} + +#[derive(Debug, PartialEq, Eq)] +struct DeathRow { + hash: BlockHash, + journal_key: Vec, + deleted: HashSet, +} + +struct JournalRecord { + hash: BlockHash, + inserted: Vec, + deleted: Vec, +} + +impl Encode for JournalRecord { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.hash); + dest.push(&self.inserted); + dest.push(&self.deleted); + } +} + +impl Decode for JournalRecord { + fn decode(input: &mut I) -> Option { + Some(JournalRecord { + hash: Decode::decode(input)?, + inserted: Decode::decode(input)?, + deleted: Decode::decode(input)?, + }) + } +} + +fn to_journal_key(block: u64) -> Vec { + to_meta_key(PRUNING_JOURNAL, &block) +} + +impl RefWindow { + pub fn new(db: &D) -> Result, Error> { + let last_pruned = db.get_meta(&to_meta_key(LAST_PRUNED, &())) + .map_err(|e| Error::Db(e))?; + let pending_number: u64 = match last_pruned { + Some(buffer) => u64::decode(&mut buffer.as_slice()).ok_or(Error::Decoding)? + 1, + None => 1, + }; + let mut block = pending_number; + let mut pruning = RefWindow { + death_rows: Default::default(), + death_index: Default::default(), + pending_number: pending_number, + }; + // read the journal + trace!(target: "state-db", "Reading pruning journal. Last pruned #{}", pending_number - 1); + loop { + let journal_key = to_journal_key(block); + match db.get_meta(&journal_key).map_err(|e| Error::Db(e))? { + Some(record) => { + let record: JournalRecord = Decode::decode(&mut record.as_slice()).ok_or(Error::Decoding)?; + trace!(target: "state-db", "Pruning journal entry {} ({} inserted, {} deleted)", block, record.inserted.len(), record.deleted.len()); + pruning.import(&record.hash, journal_key, record.inserted.into_iter(), record.deleted); + }, + None => break, + } + block += 1; + } + Ok(pruning) + } + + fn import>(&mut self, hash: &BlockHash, journal_key: Vec, inserted: I, deleted: Vec) { + // remove all re-inserted keys from death rows + for k in inserted { + if let Some(block) = self.death_index.remove(&k) { + self.death_rows[(block - self.pending_number) as usize].deleted.remove(&k); + } + } + + // add new keys + let imported_block = self.pending_number + self.death_rows.len() as u64; + for k in deleted.iter() { + self.death_index.insert(k.clone(), imported_block); + } + self.death_rows.push_back( + DeathRow { + hash: hash.clone(), + deleted: deleted.into_iter().collect(), + journal_key: journal_key, + } + ); + } + + pub fn window_size(&self) -> u64 { + self.death_rows.len() as u64 + } + + pub fn next_hash(&self) -> Option { + self.death_rows.front().map(|r| r.hash.clone()) + } + + pub fn mem_used(&self) -> usize { + 0 + } + + /// Prune next block. Expects at least one block in the window. Adds changes to `commit`. + pub fn prune_one(&mut self, commit: &mut CommitSet) { + let pruned = self.death_rows.pop_front().expect("prune_one is only called with a non-empty window"); + trace!(target: "state-db", "Pruning {:?} ({} deleted)", pruned.hash, pruned.deleted.len()); + for k in pruned.deleted.iter() { + self.death_index.remove(&k); + } + commit.data.deleted.extend(pruned.deleted.into_iter()); + commit.meta.inserted.push((to_meta_key(LAST_PRUNED, &()), self.pending_number.encode())); + commit.meta.deleted.push(pruned.journal_key); + self.pending_number += 1; + } + + /// Add a change set to the window. Creates a journal record and pushes it to `commit` + pub fn note_finalized(&mut self, hash: &BlockHash, commit: &mut CommitSet) { + trace!(target: "state-db", "Adding to pruning window: {:?} ({} inserted, {} deleted)", hash, commit.data.inserted.len(), commit.data.deleted.len()); + let inserted = commit.data.inserted.iter().map(|(k, _)| k.clone()).collect(); + let deleted = ::std::mem::replace(&mut commit.data.deleted, Vec::new()); + let journal_record = JournalRecord { + hash: hash.clone(), + inserted, + deleted, + }; + let block = self.pending_number + self.window_size(); + let journal_key = to_journal_key(block); + commit.meta.inserted.push((journal_key.clone(), journal_record.encode())); + + self.import(hash, journal_key, journal_record.inserted.into_iter(), journal_record.deleted); + } +} + +#[cfg(test)] +mod tests { + use super::RefWindow; + use primitives::H256; + use {CommitSet}; + use test::{make_db, make_commit, TestDb}; + + fn check_journal(pruning: &RefWindow, db: &TestDb) { + let restored: RefWindow = RefWindow::new(db).unwrap(); + assert_eq!(pruning.pending_number, restored.pending_number); + assert_eq!(pruning.death_rows, restored.death_rows); + assert_eq!(pruning.death_index, restored.death_index); + } + + #[test] + fn created_from_empty_db() { + let db = make_db(&[]); + let pruning: RefWindow = RefWindow::new(&db).unwrap(); + assert_eq!(pruning.pending_number, 1); + assert!(pruning.death_rows.is_empty()); + assert!(pruning.death_index.is_empty()); + } + + #[test] + #[should_panic] + fn prune_empty_panics() { + let db = make_db(&[]); + let mut pruning: RefWindow = RefWindow::new(&db).unwrap(); + let mut commit = CommitSet::default(); + pruning.prune_one(&mut commit); + } + + #[test] + fn prune_one() { + let mut db = make_db(&[1, 2, 3]); + let mut pruning: RefWindow = RefWindow::new(&db).unwrap(); + let mut commit = make_commit(&[4, 5], &[1, 3]); + let h = H256::random(); + pruning.note_finalized(&h, &mut commit); + db.commit(&commit); + assert!(commit.data.deleted.is_empty()); + assert_eq!(pruning.death_rows.len(), 1); + assert_eq!(pruning.death_index.len(), 2); + assert!(db.data_eq(&make_db(&[1, 2, 3, 4, 5]))); + check_journal(&pruning, &db); + + let mut commit = CommitSet::default(); + pruning.prune_one(&mut commit); + db.commit(&commit); + assert!(db.data_eq(&make_db(&[2, 4, 5]))); + assert!(pruning.death_rows.is_empty()); + assert!(pruning.death_index.is_empty()); + assert_eq!(pruning.pending_number, 2); + } + + #[test] + fn prune_two() { + let mut db = make_db(&[1, 2, 3]); + let mut pruning: RefWindow = RefWindow::new(&db).unwrap(); + let mut commit = make_commit(&[4], &[1]); + pruning.note_finalized(&H256::random(), &mut commit); + db.commit(&commit); + let mut commit = make_commit(&[5], &[2]); + pruning.note_finalized(&H256::random(), &mut commit); + db.commit(&commit); + assert!(db.data_eq(&make_db(&[1, 2, 3, 4, 5]))); + + check_journal(&pruning, &db); + + let mut commit = CommitSet::default(); + pruning.prune_one(&mut commit); + db.commit(&commit); + assert!(db.data_eq(&make_db(&[2, 3, 4, 5]))); + let mut commit = CommitSet::default(); + pruning.prune_one(&mut commit); + db.commit(&commit); + assert!(db.data_eq(&make_db(&[3, 4, 5]))); + assert_eq!(pruning.pending_number, 3); + } + + #[test] + fn reinserted_survives() { + let mut db = make_db(&[1, 2, 3]); + let mut pruning: RefWindow = RefWindow::new(&db).unwrap(); + let mut commit = make_commit(&[], &[2]); + pruning.note_finalized(&H256::random(), &mut commit); + db.commit(&commit); + let mut commit = make_commit(&[2], &[]); + pruning.note_finalized(&H256::random(), &mut commit); + db.commit(&commit); + let mut commit = make_commit(&[], &[2]); + pruning.note_finalized(&H256::random(), &mut commit); + db.commit(&commit); + assert!(db.data_eq(&make_db(&[1, 2, 3]))); + + check_journal(&pruning, &db); + + let mut commit = CommitSet::default(); + pruning.prune_one(&mut commit); + db.commit(&commit); + assert!(db.data_eq(&make_db(&[1, 2, 3]))); + let mut commit = CommitSet::default(); + pruning.prune_one(&mut commit); + db.commit(&commit); + assert!(db.data_eq(&make_db(&[1, 2, 3]))); + pruning.prune_one(&mut commit); + db.commit(&commit); + assert!(db.data_eq(&make_db(&[1, 3]))); + assert_eq!(pruning.pending_number, 4); + } +} diff --git a/substrate/state-db/src/test.rs b/substrate/state-db/src/test.rs new file mode 100644 index 0000000000000..d9ff05a6a26a7 --- /dev/null +++ b/substrate/state-db/src/test.rs @@ -0,0 +1,83 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Test utils + +use std::collections::HashMap; +use primitives::H256; +use {DBValue, ChangeSet, CommitSet, MetaDb, HashDb}; + +#[derive(Default, Debug, Clone, PartialEq, Eq)] +pub struct TestDb { + pub data: HashMap, + pub meta: HashMap, DBValue>, +} + +impl MetaDb for TestDb { + type Error = (); + + fn get_meta(&self, key: &[u8]) -> Result, ()> { + Ok(self.meta.get(key).cloned()) + } +} + +impl HashDb for TestDb { + type Error = (); + type Hash = H256; + + fn get(&self, key: &H256) -> Result, ()> { + Ok(self.data.get(key).cloned()) + } +} + +impl TestDb { + pub fn commit(&mut self, commit: &CommitSet) { + self.data.extend(commit.data.inserted.iter().cloned()); + for k in commit.data.deleted.iter() { + self.data.remove(k); + } + self.meta.extend(commit.meta.inserted.iter().cloned()); + for k in commit.meta.deleted.iter() { + self.meta.remove(k); + } + } + + pub fn data_eq(&self, other: &TestDb) -> bool { + self.data == other.data + } +} + +pub fn make_changeset(inserted: &[u64], deleted: &[u64]) -> ChangeSet { + ChangeSet { + inserted: inserted.iter().map(|v| (H256::from(*v), H256::from(*v).to_vec())).collect(), + deleted: deleted.iter().map(|v| H256::from(*v)).collect(), + } +} + +pub fn make_commit(inserted: &[u64], deleted: &[u64]) -> CommitSet { + CommitSet { + data: make_changeset(inserted, deleted), + meta: ChangeSet::default(), + } +} + +pub fn make_db(inserted: &[u64]) -> TestDb { + TestDb { + data: inserted.iter().map(|v| (H256::from(*v), H256::from(*v).to_vec())).collect(), + meta: Default::default(), + } +} + diff --git a/substrate/state-db/src/unfinalized.rs b/substrate/state-db/src/unfinalized.rs new file mode 100644 index 0000000000000..ed122b4dbc636 --- /dev/null +++ b/substrate/state-db/src/unfinalized.rs @@ -0,0 +1,552 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Finalization window. +//! Maintains trees of block overlays and allows discarding trees/roots +//! The overlays are added in `insert` and removed in `finalize`. +//! Last finalized overlay is kept in memory until next call to `finalize` or +//! `clear_overlay` + +use std::collections::{HashMap, VecDeque}; +use super::{Error, DBValue, ChangeSet, CommitSet, MetaDb, Hash, to_meta_key}; +use codec::{self, Decode, Encode}; + +const UNFINALIZED_JOURNAL: &[u8] = b"unfinalized_journal"; +const LAST_FINALIZED: &[u8] = b"last_finalized"; + +/// See module documentation. +pub struct UnfinalizedOverlay { + last_finalized: Option<(BlockHash, u64)>, + levels: VecDeque>>, + parents: HashMap, + last_finalized_overlay: HashMap, +} + +struct JournalRecord { + hash: BlockHash, + parent_hash: BlockHash, + inserted: Vec<(Key, DBValue)>, + deleted: Vec, +} + +impl Encode for JournalRecord { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.hash); + dest.push(&self.parent_hash); + dest.push(&self.inserted); + dest.push(&self.deleted); + } +} + +impl Decode for JournalRecord { + fn decode(input: &mut I) -> Option { + Some(JournalRecord { + hash: Decode::decode(input)?, + parent_hash: Decode::decode(input)?, + inserted: Decode::decode(input)?, + deleted: Decode::decode(input)?, + }) + } +} + +fn to_journal_key(block: u64, index: u64) -> Vec { + to_meta_key(UNFINALIZED_JOURNAL, &(block, index)) +} + +#[cfg_attr(test, derive(PartialEq, Debug))] +struct BlockOverlay { + hash: BlockHash, + journal_key: Vec, + values: HashMap, + deleted: Vec, +} + +impl UnfinalizedOverlay { + /// Creates a new instance. Does not expect any metadata to be present in the DB. + pub fn new(db: &D) -> Result, Error> { + let last_finalized = db.get_meta(&to_meta_key(LAST_FINALIZED, &())) + .map_err(|e| Error::Db(e))?; + let last_finalized = match last_finalized { + Some(buffer) => Some(<(BlockHash, u64)>::decode(&mut buffer.as_slice()).ok_or(Error::Decoding)?), + None => None, + }; + let mut levels = VecDeque::new(); + let mut parents = HashMap::new(); + if let Some((ref hash, mut block)) = last_finalized { + // read the journal + trace!(target: "state-db", "Reading unfinalized journal. Last finalized #{} ({:?})", block, hash); + let mut total: u64 = 0; + block += 1; + loop { + let mut index: u64 = 0; + let mut level = Vec::new(); + loop { + let journal_key = to_journal_key(block, index); + match db.get_meta(&journal_key).map_err(|e| Error::Db(e))? { + Some(record) => { + let record: JournalRecord = Decode::decode(&mut record.as_slice()).ok_or(Error::Decoding)?; + let overlay = BlockOverlay { + hash: record.hash.clone(), + journal_key, + values: record.inserted.into_iter().collect(), + deleted: record.deleted, + }; + trace!(target: "state-db", "Unfinalized journal entry {}.{} ({} inserted, {} deleted)", block, index, overlay.values.len(), overlay.deleted.len()); + level.push(overlay); + parents.insert(record.hash, record.parent_hash); + index += 1; + total += 1; + }, + None => break, + } + } + if level.is_empty() { + break; + } + levels.push_back(level); + block += 1; + } + trace!(target: "state-db", "Finished reading unfinalized journal, {} entries", total); + } + Ok(UnfinalizedOverlay { + last_finalized: last_finalized, + levels, + parents, + last_finalized_overlay: Default::default(), + }) + } + + /// Insert a new block into the overlay. If inserted on the second level or lover expects parent to be present in the window. + pub fn insert(&mut self, hash: &BlockHash, number: u64, parent_hash: &BlockHash, changeset: ChangeSet) -> CommitSet { + let mut commit = CommitSet::default(); + if self.levels.is_empty() && self.last_finalized.is_none() { + // assume that parent was finalized + let last_finalized = (parent_hash.clone(), number - 1); + commit.meta.inserted.push((to_meta_key(LAST_FINALIZED, &()), last_finalized.encode())); + self.last_finalized = Some(last_finalized); + } else if self.last_finalized.is_some() { + assert!(number >= self.front_block_number() && number < (self.front_block_number() + self.levels.len() as u64 + 1)); + // check for valid parent if inserting on second level or higher + if number == self.front_block_number() { + assert!(self.last_finalized.as_ref().map_or(false, |&(ref h, n)| h == parent_hash && n == number - 1)); + } else { + assert!(self.parents.contains_key(&parent_hash)); + } + } + let level = if self.levels.is_empty() || number == self.front_block_number() + self.levels.len() as u64 { + self.levels.push_back(Vec::new()); + self.levels.back_mut().expect("can't be empty after insertion; qed") + } else { + let front_block_number = self.front_block_number(); + self.levels.get_mut((number - front_block_number) as usize) + .expect("number is [front_block_number .. front_block_number + levels.len()) is asserted in precondition; qed") + }; + + let index = level.len() as u64; + let journal_key = to_journal_key(number, index); + + let overlay = BlockOverlay { + hash: hash.clone(), + journal_key: journal_key.clone(), + values: changeset.inserted.iter().cloned().collect(), + deleted: changeset.deleted.clone(), + }; + level.push(overlay); + self.parents.insert(hash.clone(), parent_hash.clone()); + let journal_record = JournalRecord { + hash: hash.clone(), + parent_hash: parent_hash.clone(), + inserted: changeset.inserted, + deleted: changeset.deleted, + }; + trace!(target: "state-db", "Inserted unfinalized changeset {}.{} ({} inserted, {} deleted)", number, index, journal_record.inserted.len(), journal_record.deleted.len()); + let journal_record = journal_record.encode(); + commit.meta.inserted.push((journal_key, journal_record)); + commit + } + + fn discard( + levels: &mut [Vec>], + parents: &mut HashMap, + discarded_journals: &mut Vec>, + number: u64, + hash: &BlockHash, + ) { + if let Some((level, sublevels)) = levels.split_first_mut() { + level.retain(|ref overlay| { + let parent = parents.get(&overlay.hash).expect("there is a parent entry for each entry in levels; qed").clone(); + if parent == *hash { + parents.remove(&overlay.hash); + discarded_journals.push(overlay.journal_key.clone()); + Self::discard(sublevels, parents, discarded_journals, number + 1, &overlay.hash); + false + } else { + true + } + }); + } + } + + fn front_block_number(&self) -> u64 { + self.last_finalized.as_ref().map(|&(_, n)| n + 1).unwrap_or(0) + } + + pub fn last_finalized_block_number(&self) -> u64 { + self.last_finalized.as_ref().map(|&(_, n)| n).unwrap_or(0) + } + + /// This may be called when the last finalization commit was applied to the database. + pub fn clear_overlay(&mut self) { + self.last_finalized_overlay.clear(); + } + + /// Select a top-level root and finalized it. Discards all sibling subtrees and the root. + /// Returns a set of changes that need to be added to the DB. + pub fn finalize(&mut self, hash: &BlockHash) -> CommitSet { + trace!(target: "state-db", "Finalizing {:?}", hash); + let level = self.levels.pop_front().expect("no blocks to finalize"); + let index = level.iter().position(|overlay| overlay.hash == *hash) + .expect("attempting to finalize unknown block"); + + let mut commit = CommitSet::default(); + let mut discarded_journals = Vec::new(); + for (i, overlay) in level.into_iter().enumerate() { + self.parents.remove(&overlay.hash); + if i == index { + self.last_finalized_overlay = overlay.values; + // that's the one we need to finalize + commit.data.inserted = self.last_finalized_overlay.iter().map(|(k, v)| (k.clone(), v.clone())).collect(); + commit.data.deleted = overlay.deleted; + } else { + // TODO: borrow checker won't allow us to split out mutable refernces + // required for recursive processing. A more efficient implementaion + // that does not require converting to vector is possible + let mut vec: Vec<_> = self.levels.drain(..).collect(); + Self::discard(&mut vec, &mut self.parents, &mut discarded_journals, 0, &overlay.hash); + self.levels.extend(vec.into_iter()); + } + // cleanup journal entry + discarded_journals.push(overlay.journal_key); + } + commit.meta.deleted.append(&mut discarded_journals); + let last_finalized = (hash.clone(), self.front_block_number()); + commit.meta.inserted.push((to_meta_key(LAST_FINALIZED, &()), last_finalized.encode())); + self.last_finalized = Some(last_finalized); + trace!(target: "state-db", "Discarded {} records", commit.meta.deleted.len()); + commit + } + + /// Get a value from the node overlay. This searches in every existing changeset. + pub fn get(&self, key: &Key) -> Option { + if let Some(value) = self.last_finalized_overlay.get(&key) { + return Some(value.clone()); + } + for level in self.levels.iter() { + for overlay in level.iter() { + if let Some(value) = overlay.values.get(&key) { + return Some(value.clone()); + } + } + } + None + } + + /// Revert a single level. Returns commit set that deletes the journal or `None` if not possible. + pub fn revert_one(&mut self) -> Option> { + self.levels.pop_back().map(|level| { + let mut commit = CommitSet::default(); + for overlay in level.into_iter() { + commit.meta.deleted.push(overlay.journal_key); + self.parents.remove(&overlay.hash); + } + commit + }) + } +} + +#[cfg(test)] +mod tests { + use super::UnfinalizedOverlay; + use {ChangeSet}; + use primitives::H256; + use test::{make_db, make_changeset}; + + fn contains(overlay: &UnfinalizedOverlay, key: u64) -> bool { + overlay.get(&H256::from(key)) == Some(H256::from(key).to_vec()) + } + + #[test] + fn created_from_empty_db() { + let db = make_db(&[]); + let overlay: UnfinalizedOverlay = UnfinalizedOverlay::new(&db).unwrap(); + assert_eq!(overlay.last_finalized, None); + assert!(overlay.levels.is_empty()); + assert!(overlay.parents.is_empty()); + } + + #[test] + #[should_panic] + fn finalize_empty_panics() { + let db = make_db(&[]); + let mut overlay = UnfinalizedOverlay::::new(&db).unwrap(); + overlay.finalize(&H256::default()); + } + + #[test] + #[should_panic] + fn insert_ahead_panics() { + let db = make_db(&[]); + let h1 = H256::random(); + let h2 = H256::random(); + let mut overlay = UnfinalizedOverlay::::new(&db).unwrap(); + overlay.insert(&h1, 2, &H256::default(), ChangeSet::default()); + overlay.insert(&h2, 1, &h1, ChangeSet::default()); + } + + #[test] + #[should_panic] + fn insert_behind_panics() { + let h1 = H256::random(); + let h2 = H256::random(); + let db = make_db(&[]); + let mut overlay = UnfinalizedOverlay::::new(&db).unwrap(); + overlay.insert(&h1, 1, &H256::default(), ChangeSet::default()); + overlay.insert(&h2, 3, &h1, ChangeSet::default()); + } + + #[test] + #[should_panic] + fn insert_unknown_parent_panics() { + let db = make_db(&[]); + let h1 = H256::random(); + let h2 = H256::random(); + let mut overlay = UnfinalizedOverlay::::new(&db).unwrap(); + overlay.insert(&h1, 1, &H256::default(), ChangeSet::default()); + overlay.insert(&h2, 2, &H256::default(), ChangeSet::default()); + } + + #[test] + #[should_panic] + fn finalize_unknown_panics() { + let h1 = H256::random(); + let h2 = H256::random(); + let db = make_db(&[]); + let mut overlay = UnfinalizedOverlay::::new(&db).unwrap(); + overlay.insert(&h1, 1, &H256::default(), ChangeSet::default()); + overlay.finalize(&h2); + } + + #[test] + fn insert_finalize_one() { + let h1 = H256::random(); + let mut db = make_db(&[1, 2]); + let mut overlay = UnfinalizedOverlay::::new(&db).unwrap(); + let changeset = make_changeset(&[3, 4], &[2]); + let insertion = overlay.insert(&h1, 1, &H256::default(), changeset.clone()); + assert_eq!(insertion.data.inserted.len(), 0); + assert_eq!(insertion.data.deleted.len(), 0); + assert_eq!(insertion.meta.inserted.len(), 2); + assert_eq!(insertion.meta.deleted.len(), 0); + db.commit(&insertion); + let finalization = overlay.finalize(&h1); + assert_eq!(finalization.data.inserted.len(), changeset.inserted.len()); + assert_eq!(finalization.data.deleted.len(), changeset.deleted.len()); + assert_eq!(finalization.meta.inserted.len(), 1); + assert_eq!(finalization.meta.deleted.len(), 1); + db.commit(&finalization); + assert!(db.data_eq(&make_db(&[1, 3, 4]))); + } + + #[test] + fn restore_from_journal() { + let h1 = H256::random(); + let h2 = H256::random(); + let mut db = make_db(&[1, 2]); + let mut overlay = UnfinalizedOverlay::::new(&db).unwrap(); + db.commit(&overlay.insert(&h1, 10, &H256::default(), make_changeset(&[3, 4], &[2]))); + db.commit(&overlay.insert(&h2, 11, &h1, make_changeset(&[5], &[3]))); + assert_eq!(db.meta.len(), 3); + + let overlay2 = UnfinalizedOverlay::::new(&db).unwrap(); + assert_eq!(overlay.levels, overlay2.levels); + assert_eq!(overlay.parents, overlay2.parents); + assert_eq!(overlay.last_finalized, overlay2.last_finalized); + } + + #[test] + fn restore_from_journal_after_finalize() { + let h1 = H256::random(); + let h2 = H256::random(); + let mut db = make_db(&[1, 2]); + let mut overlay = UnfinalizedOverlay::::new(&db).unwrap(); + db.commit(&overlay.insert(&h1, 10, &H256::default(), make_changeset(&[3, 4], &[2]))); + db.commit(&overlay.insert(&h2, 11, &h1, make_changeset(&[5], &[3]))); + db.commit(&overlay.finalize(&h1)); + assert_eq!(overlay.levels.len(), 1); + + let overlay2 = UnfinalizedOverlay::::new(&db).unwrap(); + assert_eq!(overlay.levels, overlay2.levels); + assert_eq!(overlay.parents, overlay2.parents); + assert_eq!(overlay.last_finalized, overlay2.last_finalized); + } + + #[test] + fn insert_finalize_two() { + let h1 = H256::random(); + let h2 = H256::random(); + let mut db = make_db(&[1, 2, 3, 4]); + let mut overlay = UnfinalizedOverlay::::new(&db).unwrap(); + let changeset1 = make_changeset(&[5, 6], &[2]); + let changeset2 = make_changeset(&[7, 8], &[5, 3]); + db.commit(&overlay.insert(&h1, 1, &H256::default(), changeset1)); + assert!(contains(&overlay, 5)); + db.commit(&overlay.insert(&h2, 2, &h1, changeset2)); + assert!(contains(&overlay, 7)); + assert!(contains(&overlay, 5)); + assert_eq!(overlay.levels.len(), 2); + assert_eq!(overlay.parents.len(), 2); + db.commit(&overlay.finalize(&h1)); + assert_eq!(overlay.levels.len(), 1); + assert_eq!(overlay.parents.len(), 1); + assert!(contains(&overlay, 5)); + overlay.clear_overlay(); + assert!(!contains(&overlay, 5)); + assert!(contains(&overlay, 7)); + db.commit(&overlay.finalize(&h2)); + overlay.clear_overlay(); + assert_eq!(overlay.levels.len(), 0); + assert_eq!(overlay.parents.len(), 0); + assert!(db.data_eq(&make_db(&[1, 4, 6, 7, 8]))); + } + + + #[test] + fn complex_tree() { + let mut db = make_db(&[]); + + // - 1 - 1_1 - 1_1_1 + // \ 1_2 - 1_2_1 + // \ 1_2_2 + // \ 1_2_3 + // + // - 2 - 2_1 - 2_1_1 + // \ 2_2 + // + // 1_2_2 is the winner + + let (h_1, c_1) = (H256::random(), make_changeset(&[1], &[])); + let (h_2, c_2) = (H256::random(), make_changeset(&[2], &[])); + + let (h_1_1, c_1_1) = (H256::random(), make_changeset(&[11], &[])); + let (h_1_2, c_1_2) = (H256::random(), make_changeset(&[12], &[])); + let (h_2_1, c_2_1) = (H256::random(), make_changeset(&[21], &[])); + let (h_2_2, c_2_2) = (H256::random(), make_changeset(&[22], &[])); + + let (h_1_1_1, c_1_1_1) = (H256::random(), make_changeset(&[111], &[])); + let (h_1_2_1, c_1_2_1) = (H256::random(), make_changeset(&[121], &[])); + let (h_1_2_2, c_1_2_2) = (H256::random(), make_changeset(&[122], &[])); + let (h_1_2_3, c_1_2_3) = (H256::random(), make_changeset(&[123], &[])); + let (h_2_1_1, c_2_1_1) = (H256::random(), make_changeset(&[211], &[])); + + let mut overlay = UnfinalizedOverlay::::new(&db).unwrap(); + db.commit(&overlay.insert(&h_1, 1, &H256::default(), c_1)); + + db.commit(&overlay.insert(&h_1_1, 2, &h_1, c_1_1)); + db.commit(&overlay.insert(&h_1_2, 2, &h_1, c_1_2)); + + db.commit(&overlay.insert(&h_2, 1, &H256::default(), c_2)); + + db.commit(&overlay.insert(&h_2_1, 2, &h_2, c_2_1)); + db.commit(&overlay.insert(&h_2_2, 2, &h_2, c_2_2)); + + db.commit(&overlay.insert(&h_1_1_1, 3, &h_1_1, c_1_1_1)); + db.commit(&overlay.insert(&h_1_2_1, 3, &h_1_2, c_1_2_1)); + db.commit(&overlay.insert(&h_1_2_2, 3, &h_1_2, c_1_2_2)); + db.commit(&overlay.insert(&h_1_2_3, 3, &h_1_2, c_1_2_3)); + db.commit(&overlay.insert(&h_2_1_1, 3, &h_2_1, c_2_1_1)); + + assert!(contains(&overlay, 2)); + assert!(contains(&overlay, 11)); + assert!(contains(&overlay, 21)); + assert!(contains(&overlay, 111)); + assert!(contains(&overlay, 122)); + assert!(contains(&overlay, 211)); + assert_eq!(overlay.levels.len(), 3); + assert_eq!(overlay.parents.len(), 11); + assert_eq!(overlay.last_finalized, Some((H256::default(), 0))); + + // check if restoration from journal results in the same tree + let overlay2 = UnfinalizedOverlay::::new(&db).unwrap(); + assert_eq!(overlay.levels, overlay2.levels); + assert_eq!(overlay.parents, overlay2.parents); + assert_eq!(overlay.last_finalized, overlay2.last_finalized); + + // finalize 1. 2 and all its children should be discarded + db.commit(&overlay.finalize(&h_1)); + overlay.clear_overlay(); + assert_eq!(overlay.levels.len(), 2); + assert_eq!(overlay.parents.len(), 6); + assert!(!contains(&overlay, 1)); + assert!(!contains(&overlay, 2)); + assert!(!contains(&overlay, 21)); + assert!(!contains(&overlay, 22)); + assert!(!contains(&overlay, 211)); + assert!(contains(&overlay, 111)); + + // finalize 1_2. 1_1 and all its children should be discarded + db.commit(&overlay.finalize(&h_1_2)); + overlay.clear_overlay(); + assert_eq!(overlay.levels.len(), 1); + assert_eq!(overlay.parents.len(), 3); + assert!(!contains(&overlay, 11)); + assert!(!contains(&overlay, 111)); + assert!(contains(&overlay, 121)); + assert!(contains(&overlay, 122)); + assert!(contains(&overlay, 123)); + + // finalize 1_2_2 + db.commit(&overlay.finalize(&h_1_2_2)); + overlay.clear_overlay(); + assert_eq!(overlay.levels.len(), 0); + assert_eq!(overlay.parents.len(), 0); + assert!(db.data_eq(&make_db(&[1, 12, 122]))); + assert_eq!(overlay.last_finalized, Some((h_1_2_2, 3))); + } + + #[test] + fn insert_revert() { + let h1 = H256::random(); + let h2 = H256::random(); + let mut db = make_db(&[1, 2, 3, 4]); + let mut overlay = UnfinalizedOverlay::::new(&db).unwrap(); + assert!(overlay.revert_one().is_none()); + let changeset1 = make_changeset(&[5, 6], &[2]); + let changeset2 = make_changeset(&[7, 8], &[5, 3]); + db.commit(&overlay.insert(&h1, 1, &H256::default(), changeset1)); + db.commit(&overlay.insert(&h2, 2, &h1, changeset2)); + assert!(contains(&overlay, 7)); + db.commit(&overlay.revert_one().unwrap()); + assert_eq!(overlay.parents.len(), 1); + assert!(contains(&overlay, 5)); + assert!(!contains(&overlay, 7)); + db.commit(&overlay.revert_one().unwrap()); + assert_eq!(overlay.levels.len(), 0); + assert_eq!(overlay.parents.len(), 0); + assert!(overlay.revert_one().is_none()); + } + +} + diff --git a/substrate/state-machine/Cargo.toml b/substrate/state-machine/Cargo.toml index 74a46764cf753..17b072c4c6687 100644 --- a/substrate/state-machine/Cargo.toml +++ b/substrate/state-machine/Cargo.toml @@ -15,6 +15,5 @@ triehash = "0.1" substrate-primitives = { path = "../primitives", version = "0.1.0" } hashdb = { git = "https://github.com/paritytech/parity.git" } -kvdb = { git = "https://github.com/paritytech/parity.git" } memorydb = { git = "https://github.com/paritytech/parity.git" } patricia-trie = { git = "https://github.com/paritytech/parity.git" } diff --git a/substrate/state-machine/src/backend.rs b/substrate/state-machine/src/backend.rs index cbd2fc6ccf192..1d3b2108f9e3b 100644 --- a/substrate/state-machine/src/backend.rs +++ b/substrate/state-machine/src/backend.rs @@ -35,6 +35,15 @@ pub trait Backend: TryIntoTrieBackend { /// Get keyed storage associated with specific address, or None if there is nothing associated. fn storage(&self, key: &[u8]) -> Result>, Self::Error>; + /// true if a key exists in storage. + fn exists_storage(&self, key: &[u8]) -> Result { + Ok(self.storage(key)?.is_some()) + } + + /// Retrieve all entries keys of which start with the given prefix and + /// call `f` for each of those keys. + fn for_keys_with_prefix(&self, prefix: &[u8], f: F); + /// Calculate the storage root, with given delta over what is already stored in /// the backend, and produce a "transaction" that can be used to commit. fn storage_root(&self, delta: I) -> ([u8; 32], Self::Transaction) @@ -97,6 +106,8 @@ impl From, Vec>> for InMemory { } } +impl super::Error for Void {} + impl Backend for InMemory { type Error = Void; type Transaction = Vec<(Vec, Option>)>; @@ -105,6 +116,14 @@ impl Backend for InMemory { Ok(self.inner.get(key).map(Clone::clone)) } + fn exists_storage(&self, key: &[u8]) -> Result { + Ok(self.inner.get(key).is_some()) + } + + fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { + self.inner.keys().filter(|key| key.starts_with(prefix)).map(|k| &**k).for_each(f); + } + fn storage_root(&self, delta: I) -> ([u8; 32], Self::Transaction) where I: IntoIterator, Option>)> { diff --git a/substrate/state-machine/src/ext.rs b/substrate/state-machine/src/ext.rs index 6ac27a71ef9e3..5a8ba096f5753 100644 --- a/substrate/state-machine/src/ext.rs +++ b/substrate/state-machine/src/ext.rs @@ -74,6 +74,13 @@ impl<'a, B: 'a + Backend> Ext<'a, B> { let _ = self.storage_root(); self.transaction.expect("transaction always set after calling storage root; qed").0 } + + /// Invalidates the currently cached storage root and the db transaction. + /// + /// Called when there are changes that likely will invalidate the storage root. + fn mark_dirty(&mut self) { + self.transaction = None; + } } #[cfg(test)] @@ -100,11 +107,26 @@ impl<'a, B: 'a> Externalities for Ext<'a, B> self.backend.storage(key).expect("Externalities not allowed to fail within runtime")) } + fn exists_storage(&self, key: &[u8]) -> bool { + match self.overlay.storage(key) { + Some(x) => x.is_some(), + _ => self.backend.exists_storage(key).expect("Externalities not allowed to fail within runtime"), + } + } + fn place_storage(&mut self, key: Vec, value: Option>) { - self.transaction = None; // wipe out the transaction since root will no longer be the same. + self.mark_dirty(); self.overlay.set_storage(key, value); } + fn clear_prefix(&mut self, prefix: &[u8]) { + self.mark_dirty(); + self.overlay.clear_prefix(prefix); + self.backend.for_keys_with_prefix(prefix, |key| { + self.overlay.set_storage(key.to_vec(), None); + }); + } + fn chain_id(&self) -> u64 { 42 } diff --git a/substrate/state-machine/src/lib.rs b/substrate/state-machine/src/lib.rs index af643d78971cc..ab8d5b575d7ef 100644 --- a/substrate/state-machine/src/lib.rs +++ b/substrate/state-machine/src/lib.rs @@ -25,7 +25,6 @@ extern crate hex_literal; extern crate log; extern crate ethereum_types; -extern crate kvdb; extern crate hashdb; extern crate memorydb; extern crate triehash; @@ -47,7 +46,7 @@ mod trie_backend; pub use testing::TestExternalities; pub use ext::Ext; pub use backend::Backend; -pub use trie_backend::{TryIntoTrieBackend, TrieBackend}; +pub use trie_backend::{TryIntoTrieBackend, TrieBackend, TrieH256, Storage, DBValue}; /// The overlayed changes to state to be queried on top of the backend. /// @@ -69,10 +68,37 @@ impl OverlayedChanges { .map(|x| x.as_ref().map(AsRef::as_ref)) } + /// Inserts the given key-value pair into the prospective change set. + /// + /// `None` can be used to delete a value specified by the given key. fn set_storage(&mut self, key: Vec, val: Option>) { self.prospective.insert(key, val); } + /// Removes all key-value pairs which keys share the given prefix. + /// + /// NOTE that this doesn't take place immediately but written into the prospective + /// change set, and still can be reverted by [`discard_prospective`]. + /// + /// [`discard_prospective`]: #method.discard_prospective + fn clear_prefix(&mut self, prefix: &[u8]) { + // Iterate over all prospective and mark all keys that share + // the given prefix as removed (None). + for (key, value) in self.prospective.iter_mut() { + if key.starts_with(prefix) { + *value = None; + } + } + + // Then do the same with keys from commited changes. + // NOTE that we are making changes in the prospective change set. + for key in self.committed.keys() { + if key.starts_with(prefix) { + self.prospective.insert(key.to_owned(), None); + } + } + } + /// Discard prospective changes to state. pub fn discard_prospective(&mut self) { self.prospective.clear(); @@ -96,8 +122,12 @@ impl OverlayedChanges { /// State Machine Error bound. /// /// This should reflect WASM error type bound for future compatibility. -pub trait Error: 'static + fmt::Debug + fmt::Display + Send {} -impl Error for E where E: 'static + fmt::Debug + fmt::Display + Send {} +pub trait Error: 'static + fmt::Debug + fmt::Display + Send { + /// Error implies execution should be retried. + fn needs_retry(&self) -> bool { false } +} + +impl Error for ExecutionError {} /// Externalities Error. /// @@ -133,6 +163,14 @@ pub trait Externalities { self.place_storage(key.to_vec(), None); } + /// Clear a storage entry (`key`) of current contract being called (effective immediately). + fn exists_storage(&self, key: &[u8]) -> bool { + self.storage(key).is_some() + } + + /// Clear storage entries which keys are start with the given prefix. + fn clear_prefix(&mut self, prefix: &[u8]); + /// Set or clear a storage entry (`key`) of current contract being called (effective immediately). fn place_storage(&mut self, key: Vec, value: Option>); @@ -148,14 +186,57 @@ pub trait CodeExecutor: Sized + Send + Sync { /// Externalities error type. type Error: Error; - /// Call a given method in the runtime. + /// Call a given method in the runtime. Returns a tuple of the result (either the output data + /// or an execution error) together with a `bool`, which is true if native execution was used. fn call( &self, ext: &mut E, code: &[u8], method: &str, data: &[u8], - ) -> Result, Self::Error>; + use_native: bool + ) -> (Result, Self::Error>, bool); +} + +/// Strategy for executing a call into the runtime. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum ExecutionStrategy { + /// Execute with the native equivalent if it is compatible with the given wasm module; otherwise fall back to the wasm. + NativeWhenPossible, + /// Use the given wasm module. + AlwaysWasm, + /// Run with both the wasm and the native variant (if compatible). Report any discrepency as an error. + Both, +} + +/// Like `ExecutionStrategy` only it also stores a handler in case of consensus failure. +pub enum ExecutionManager { + /// Execute with the native equivalent if it is compatible with the given wasm module; otherwise fall back to the wasm. + NativeWhenPossible, + /// Use the given wasm module. + AlwaysWasm, + /// Run with both the wasm and the native variant (if compatible). Call `F` in the case of any discrepency. + Both(F), +} + +impl<'a, F> From<&'a ExecutionManager> for ExecutionStrategy { + fn from(s: &'a ExecutionManager) -> Self { + match *s { + ExecutionManager::NativeWhenPossible => ExecutionStrategy::NativeWhenPossible, + ExecutionManager::AlwaysWasm => ExecutionStrategy::AlwaysWasm, + ExecutionManager::Both(_) => ExecutionStrategy::Both, + } + } +} + +/// Evaluate to ExecutionManager::NativeWhenPossible, without having to figure out the type. +pub fn native_when_possible() -> ExecutionManager, E>, Result, E>)->Result, E>> { + ExecutionManager::NativeWhenPossible +} + +/// Evaluate to ExecutionManager::NativeWhenPossible, without having to figure out the type. +pub fn always_wasm() -> ExecutionManager, E>, Result, E>)->Result, E>> { + ExecutionManager::AlwaysWasm } /// Execute a call using the given state backend, overlayed changes, and call executor. @@ -172,30 +253,125 @@ pub fn execute( exec: &Exec, method: &str, call_data: &[u8], -) -> Result<(Vec, B::Transaction), Box> -{ + strategy: ExecutionStrategy, +) -> Result<(Vec, B::Transaction), Box> { + execute_using_consensus_failure_handler( + backend, + overlay, + exec, + method, + call_data, + match strategy { + ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm, + ExecutionStrategy::NativeWhenPossible => ExecutionManager::NativeWhenPossible, + ExecutionStrategy::Both => ExecutionManager::Both(|wasm_result, native_result| { + warn!("Consensus error between wasm {:?} and native {:?}. Using wasm.", wasm_result, native_result); + wasm_result + }), + }, + ) +} + +/// Execute a call using the given state backend, overlayed changes, and call executor. +/// Produces a state-backend-specific "transaction" which can be used to apply the changes +/// to the backing store, such as the disk. +/// +/// On an error, no prospective changes are written to the overlay. +/// +/// Note: changes to code will be in place if this call is made again. For running partial +/// blocks (e.g. a transaction at a time), ensure a different method is used. +pub fn execute_using_consensus_failure_handler< + B: backend::Backend, + Exec: CodeExecutor, + Handler: FnOnce(Result, Exec::Error>, Result, Exec::Error>) -> Result, Exec::Error> +>( + backend: &B, + overlay: &mut OverlayedChanges, + exec: &Exec, + method: &str, + call_data: &[u8], + manager: ExecutionManager, +) -> Result<(Vec, B::Transaction), Box> { + let strategy: ExecutionStrategy = (&manager).into(); + + // make a copy. + let code = ext::Ext::new(overlay, backend).storage(b":code") + .ok_or_else(|| Box::new(ExecutionError::CodeEntryDoesNotExist) as Box)? + .to_vec(); + let result = { - let mut externalities = ext::Ext::new(overlay, backend); - // make a copy. - let code = externalities.storage(b":code") - .ok_or(Box::new(ExecutionError::CodeEntryDoesNotExist) as Box)? - .to_vec(); - - exec.call( - &mut externalities, - &code, - method, - call_data, - ).map(move |out| (out, externalities.transaction())) + let mut orig_prospective = overlay.prospective.clone(); + + let (result, was_native, delta) = loop { + let ((result, was_native), delta) = { + let mut externalities = ext::Ext::new(overlay, backend); + ( + exec.call( + &mut externalities, + &code, + method, + call_data, + // attempt to run native first, if we're not directed to run wasm only + strategy != ExecutionStrategy::AlwaysWasm, + ), + externalities.transaction() + ) + }; + + if result.as_ref().err().map_or(false, |e| e.needs_retry()) { + overlay.prospective = orig_prospective.clone(); + } else { + break (result, was_native, delta) + } + }; + + // run wasm separately if we did run native the first time and we're meant to run both + let (result, delta) = if let (true, ExecutionManager::Both(on_consensus_failure)) = + (was_native, manager) + { + overlay.prospective = orig_prospective.clone(); + + let (wasm_result, wasm_delta) = loop { + let ((result, _), delta) = { + let mut externalities = ext::Ext::new(overlay, backend); + ( + exec.call( + &mut externalities, + &code, + method, + call_data, + false, + ), + externalities.transaction() + ) + }; + + if result.as_ref().err().map_or(false, |e| e.needs_retry()) { + overlay.prospective = orig_prospective.clone(); + } else { + break (result, delta) + } + }; + + if (result.is_ok() && wasm_result.is_ok() && result.as_ref().unwrap() == wasm_result.as_ref().unwrap()/* && delta == wasm_delta*/) + || (result.is_err() && wasm_result.is_err() && format!("{}", result.as_ref().unwrap_err()) == format!("{}", wasm_result.as_ref().unwrap_err())) + { + (result, delta) + } else { + // Consensus error. + (on_consensus_failure(wasm_result, result), wasm_delta) + } + } else { + (result, delta) + }; + result.map(move |out| (out, delta)) }; match result { Ok(x) => { - overlay.commit_prospective(); Ok(x) } Err(e) => { - overlay.discard_prospective(); Err(Box::new(e)) } } @@ -210,34 +386,55 @@ pub fn execute( /// /// Note: changes to code will be in place if this call is made again. For running partial /// blocks (e.g. a transaction at a time), ensure a different method is used. -pub fn prove( +pub fn prove_execution( backend: B, overlay: &mut OverlayedChanges, exec: &Exec, method: &str, call_data: &[u8], -) -> Result<(Vec, Vec>, ::Transaction), Box> -{ +) -> Result<(Vec, Vec>, ::Transaction), Box> { let trie_backend = backend.try_into_trie_backend() .ok_or_else(|| Box::new(ExecutionError::UnableToGenerateProof) as Box)?; let proving_backend = proving_backend::ProvingBackend::new(trie_backend); - let (result, transaction) = execute(&proving_backend, overlay, exec, method, call_data)?; + let (result, transaction) = execute(&proving_backend, overlay, exec, method, call_data, ExecutionStrategy::NativeWhenPossible)?; let proof = proving_backend.extract_proof(); Ok((result, proof, transaction)) } -/// Check execution proof, generated by `prove` call. -pub fn proof_check( +/// Check execution proof, generated by `prove_execution` call. +pub fn execution_proof_check( root: [u8; 32], proof: Vec>, overlay: &mut OverlayedChanges, exec: &Exec, method: &str, call_data: &[u8], -) -> Result<(Vec, memorydb::MemoryDB), Box> +) -> Result<(Vec, memorydb::MemoryDB), Box> { + let backend = proving_backend::create_proof_check_backend(root.into(), proof)?; + execute(&backend, overlay, exec, method, call_data, ExecutionStrategy::NativeWhenPossible) +} + +/// Generate storage read proof. +pub fn prove_read( + backend: B, + key: &[u8], +) -> Result<(Option>, Vec>), Box> +{ + let trie_backend = backend.try_into_trie_backend() + .ok_or_else(|| Box::new(ExecutionError::UnableToGenerateProof) as Box)?; + let proving_backend = proving_backend::ProvingBackend::new(trie_backend); + let result = proving_backend.storage(key).map_err(|e| Box::new(e) as Box)?; + Ok((result, proving_backend.extract_proof())) +} + /// Check storage read proof, generated by `prove` call. +pub fn read_proof_check( + root: [u8; 32], + proof: Vec>, + key: &[u8], +) -> Result>, Box> { let backend = proving_backend::create_proof_check_backend(root.into(), proof)?; - execute(&backend, overlay, exec, method, call_data) + backend.storage(key).map_err(|e| Box::new(e) as Box) } #[cfg(test)] @@ -246,7 +443,11 @@ mod tests { use super::backend::InMemory; use super::ext::Ext; - struct DummyCodeExecutor; + struct DummyCodeExecutor { + native_available: bool, + native_succeeds: bool, + fallback_succeeds: bool, + } impl CodeExecutor for DummyCodeExecutor { type Error = u8; @@ -257,11 +458,19 @@ mod tests { _code: &[u8], _method: &str, _data: &[u8], - ) -> Result, Self::Error> { - Ok(vec![ext.storage(b"value1").unwrap()[0] + ext.storage(b"value2").unwrap()[0]]) + use_native: bool + ) -> (Result, Self::Error>, bool) { + let using_native = use_native && self.native_available; + match (using_native, self.native_succeeds, self.fallback_succeeds) { + (true, true, _) | (false, _, true) => + (Ok(vec![ext.storage(b"value1").unwrap()[0] + ext.storage(b"value2").unwrap()[0]]), using_native), + _ => (Err(0), using_native), + } } } + impl Error for u8 {} + #[test] fn overlayed_storage_works() { let mut overlayed = OverlayedChanges::default(); @@ -323,24 +532,116 @@ mod tests { #[test] fn execute_works() { - assert_eq!(execute(&trie_backend::tests::test_trie(), - &mut Default::default(), &DummyCodeExecutor, "test", &[]).unwrap().0, vec![66]); + assert_eq!(execute( + &trie_backend::tests::test_trie(), + &mut Default::default(), + &DummyCodeExecutor { + native_available: true, + native_succeeds: true, + fallback_succeeds: true, + }, + "test", + &[], + ExecutionStrategy::NativeWhenPossible + ).unwrap().0, vec![66]); } #[test] - fn prove_and_proof_check_works() { + fn dual_execution_strategy_detects_consensus_failure() { + let mut consensus_failed = false; + assert!(execute_using_consensus_failure_handler( + &trie_backend::tests::test_trie(), + &mut Default::default(), + &DummyCodeExecutor { + native_available: true, + native_succeeds: true, + fallback_succeeds: false, + }, + "test", + &[], + ExecutionManager::Both(|we, _ne| { + consensus_failed = true; + println!("HELLO!"); + we + }), + ).is_err()); + assert!(consensus_failed); + } + + #[test] + fn prove_execution_and_proof_check_works() { + let executor = DummyCodeExecutor { + native_available: true, + native_succeeds: true, + fallback_succeeds: true, + }; + // fetch execution proof from 'remote' full node let remote_backend = trie_backend::tests::test_trie(); let remote_root = remote_backend.storage_root(::std::iter::empty()).0; - let (remote_result, remote_proof, _) = prove(remote_backend, - &mut Default::default(), &DummyCodeExecutor, "test", &[]).unwrap(); + let (remote_result, remote_proof, _) = prove_execution(remote_backend, + &mut Default::default(), &executor, "test", &[]).unwrap(); // check proof locally - let (local_result, _) = proof_check(remote_root, remote_proof, - &mut Default::default(), &DummyCodeExecutor, "test", &[]).unwrap(); + let (local_result, _) = execution_proof_check(remote_root, remote_proof, + &mut Default::default(), &executor, "test", &[]).unwrap(); // check that both results are correct assert_eq!(remote_result, vec![66]); assert_eq!(remote_result, local_result); } + + #[test] + fn clear_prefix_in_ext_works() { + let initial: HashMap<_, _> = map![ + b"aaa".to_vec() => b"0".to_vec(), + b"abb".to_vec() => b"1".to_vec(), + b"abc".to_vec() => b"2".to_vec(), + b"bbb".to_vec() => b"3".to_vec() + ]; + let backend = InMemory::from(initial).try_into_trie_backend().unwrap(); + let mut overlay = OverlayedChanges { + committed: map![ + b"aba".to_vec() => Some(b"1312".to_vec()), + b"bab".to_vec() => Some(b"228".to_vec()) + ], + prospective: map![ + b"abd".to_vec() => Some(b"69".to_vec()), + b"bbd".to_vec() => Some(b"42".to_vec()) + ], + }; + + { + let mut ext = Ext::new(&mut overlay, &backend); + ext.clear_prefix(b"ab"); + } + overlay.commit_prospective(); + + assert_eq!( + overlay.committed, + map![ + b"abb".to_vec() => None, + b"abc".to_vec() => None, + b"aba".to_vec() => None, + b"abd".to_vec() => None, + + b"bab".to_vec() => Some(b"228".to_vec()), + b"bbd".to_vec() => Some(b"42".to_vec()) + ], + ); + } + + #[test] + fn prove_read_and_proof_check_works() { + // fetch read proof from 'remote' full node + let remote_backend = trie_backend::tests::test_trie(); + let remote_root = remote_backend.storage_root(::std::iter::empty()).0; + let remote_proof = prove_read(remote_backend, b"value2").unwrap().1; + // check proof locally + let local_result1 = read_proof_check(remote_root, remote_proof.clone(), b"value2").unwrap(); + let local_result2 = read_proof_check(remote_root, remote_proof.clone(), &[0xff]).is_ok(); + // check that results are correct + assert_eq!(local_result1, Some(vec![24])); + assert_eq!(local_result2, false); + } } diff --git a/substrate/state-machine/src/proving_backend.rs b/substrate/state-machine/src/proving_backend.rs index 688dba6ef23bb..70961adc96902 100644 --- a/substrate/state-machine/src/proving_backend.rs +++ b/substrate/state-machine/src/proving_backend.rs @@ -69,6 +69,10 @@ impl Backend for ProvingBackend { .get_with(key, &mut *proof_recorder).map(|x| x.map(|val| val.to_vec())).map_err(map_e) } + fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { + self.backend.for_keys_with_prefix(prefix, f) + } + fn pairs(&self) -> Vec<(Vec, Vec)> { self.backend.pairs() } @@ -134,7 +138,7 @@ mod tests { let proving_backend = test_proving(); assert_eq!(trie_backend.storage(b"key").unwrap(), proving_backend.storage(b"key").unwrap()); assert_eq!(trie_backend.pairs(), proving_backend.pairs()); - + let (trie_root, mut trie_mdb) = trie_backend.storage_root(::std::iter::empty()); let (proving_root, mut proving_mdb) = proving_backend.storage_root(::std::iter::empty()); assert_eq!(trie_root, proving_root); diff --git a/substrate/state-machine/src/testing.rs b/substrate/state-machine/src/testing.rs index e9b4a76db61b5..7b85b523cd47a 100644 --- a/substrate/state-machine/src/testing.rs +++ b/substrate/state-machine/src/testing.rs @@ -35,6 +35,12 @@ impl Externalities for TestExternalities { } } + fn clear_prefix(&mut self, prefix: &[u8]) { + self.retain(|key, _| + !key.starts_with(prefix) + ) + } + fn chain_id(&self) -> u64 { 42 } fn storage_root(&mut self) -> [u8; 32] { diff --git a/substrate/state-machine/src/trie_backend.rs b/substrate/state-machine/src/trie_backend.rs index 5a9af8f57b8f2..629dd3ddb3a9c 100644 --- a/substrate/state-machine/src/trie_backend.rs +++ b/substrate/state-machine/src/trie_backend.rs @@ -18,12 +18,18 @@ use std::collections::HashMap; use std::sync::Arc; -use ethereum_types::H256 as TrieH256; -use hashdb::{DBValue, HashDB}; -use kvdb::KeyValueDB; +use hashdb::HashDB; use memorydb::MemoryDB; use patricia_trie::{TrieDB, TrieDBMut, TrieError, Trie, TrieMut}; use {Backend}; +pub use ethereum_types::H256 as TrieH256; +pub use hashdb::DBValue; + +/// Backend trie storage trait. +pub trait Storage: Send + Sync { + /// Get a trie node. + fn get(&self, key: &TrieH256) -> Result, String>; +} /// Try convert into trie-based backend. pub trait TryIntoTrieBackend { @@ -40,20 +46,20 @@ pub struct TrieBackend { impl TrieBackend { /// Create new trie-based backend. - pub fn with_kvdb(db: Arc, storage_column: Option, root: TrieH256) -> Self { + pub fn with_storage(db: Arc, root: TrieH256) -> Self { TrieBackend { - storage: TrieBackendStorage::KeyValueDb(db, storage_column), + storage: TrieBackendStorage::Storage(db), root, } } /// Create new trie-based backend for genesis block. - pub fn with_kvdb_for_genesis(db: Arc, storage_column: Option) -> Self { + pub fn with_storage_for_genesis(db: Arc) -> Self { let mut root = TrieH256::default(); let mut mdb = MemoryDB::default(); TrieDBMut::new(&mut mdb, &mut root); - Self::with_kvdb(db, storage_column, root) + Self::with_storage(db, root) } /// Create new trie-based backend backed by MemoryDb storage. @@ -76,6 +82,8 @@ impl TrieBackend { } } +impl super::Error for String {} + impl Backend for TrieBackend { type Error = String; type Transaction = MemoryDB; @@ -93,6 +101,37 @@ impl Backend for TrieBackend { .get(key).map(|x| x.map(|val| val.to_vec())).map_err(map_e) } + fn for_keys_with_prefix(&self, prefix: &[u8], mut f: F) { + let mut read_overlay = MemoryDB::default(); + let eph = Ephemeral { + storage: &self.storage, + overlay: &mut read_overlay, + }; + + let mut iter = move || -> Result<(), Box> { + let trie = TrieDB::new(&eph, &self.root)?; + let mut iter = trie.iter()?; + + iter.seek(prefix)?; + + for x in iter { + let (key, _) = x?; + + if !key.starts_with(prefix) { + break; + } + + f(&key); + } + + Ok(()) + }; + + if let Err(e) = iter() { + debug!(target: "trie", "Error while iterating by prefix: {}", e); + } + } + fn pairs(&self) -> Vec<(Vec, Vec)> { let mut read_overlay = MemoryDB::default(); let eph = Ephemeral { @@ -182,7 +221,7 @@ impl<'a> HashDB for Ephemeral<'a> { Some(val) } } - None => match self.storage.get(&key.0[..]) { + None => match self.storage.get(&key) { Ok(x) => x, Err(e) => { warn!(target: "trie", "Failed to read from DB: {}", e); @@ -212,19 +251,19 @@ impl<'a> HashDB for Ephemeral<'a> { #[derive(Clone)] pub enum TrieBackendStorage { /// Key value db + storage column. - KeyValueDb(Arc, Option), + Storage(Arc), /// Hash db. MemoryDb(MemoryDB), } impl TrieBackendStorage { - pub fn get(&self, key: &[u8]) -> Result, String> { + pub fn get(&self, key: &TrieH256) -> Result, String> { match *self { - TrieBackendStorage::KeyValueDb(ref db, storage_column) => - db.get(storage_column, key) + TrieBackendStorage::Storage(ref db) => + db.get(key) .map_err(|e| format!("Trie lookup error: {}", e)), TrieBackendStorage::MemoryDb(ref db) => - Ok(db.get(&TrieH256::from_slice(key))), + Ok(db.get(key)), } } } @@ -232,6 +271,7 @@ impl TrieBackendStorage { #[cfg(test)] pub mod tests { use super::*; + use std::collections::HashSet; fn test_db() -> (MemoryDB, TrieH256) { let mut root = TrieH256::default(); @@ -242,6 +282,9 @@ pub mod tests { trie.insert(b"value1", &[42]).unwrap(); trie.insert(b"value2", &[24]).unwrap(); trie.insert(b":code", b"return 42").unwrap(); + for i in 128u8..255u8 { + trie.insert(&[i], &[i]).unwrap(); + } } (mdb, root) } @@ -287,4 +330,20 @@ pub mod tests { assert!(!tx.drain().is_empty()); assert!(new_root != test_trie().storage_root(::std::iter::empty()).0); } + + #[test] + fn prefix_walking_works() { + let trie = test_trie(); + + let mut seen = HashSet::new(); + trie.for_keys_with_prefix(b"value", |key| { + let for_first_time = seen.insert(key.to_vec()); + assert!(for_first_time, "Seen key '{:?}' more than once", key); + }); + + let mut expected = HashSet::new(); + expected.insert(b"value1".to_vec()); + expected.insert(b"value2".to_vec()); + assert_eq!(seen, expected); + } } diff --git a/substrate/telemetry/Cargo.toml b/substrate/telemetry/Cargo.toml index c1c7705401c99..2e4e8db6d6bd3 100644 --- a/substrate/telemetry/Cargo.toml +++ b/substrate/telemetry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "substrate-telemetry" -version = "0.2.0" +version = "0.3.0" authors = ["Parity Technologies "] description = "Telemetry utils" diff --git a/substrate/telemetry/src/lib.rs b/substrate/telemetry/src/lib.rs index 335a93ee68458..4782f244e11b5 100644 --- a/substrate/telemetry/src/lib.rs +++ b/substrate/telemetry/src/lib.rs @@ -31,7 +31,7 @@ extern crate log; extern crate slog; extern crate slog_scope; -use std::io; +use std::{io, time}; use parking_lot::Mutex; use slog::Drain; pub use slog_scope::with_logger; @@ -44,21 +44,28 @@ pub struct TelemetryConfig { pub on_connect: Box, } +/// Telemetry service guard. +pub type Telemetry = slog_scope::GlobalLoggerGuard; + +/// Size of the channel for passing messages to telemetry thread. +const CHANNEL_SIZE: usize = 262144; + /// Initialise telemetry. pub fn init_telemetry(config: TelemetryConfig) -> slog_scope::GlobalLoggerGuard { + let client = ws::ClientBuilder::new(&config.url).ok().and_then(|mut x| x.connect(None).ok()); let log = slog::Logger::root( slog_async::Async::new( slog_json::Json::default( TelemetryWriter { buffer: vec![], - out: Mutex::new( - ws::ClientBuilder::new(&config.url).ok().and_then(|mut x| x.connect(None).ok()) - ), + out: Mutex::new(client), config, - first_time: true, // ensures that on_connect will be called. + last_time: None, // ensures that on_connect will be called. } ).fuse() - ).build().fuse(), o!() + ).chan_size(CHANNEL_SIZE) + .overflow_strategy(slog_async::OverflowStrategy::DropAndReport) + .build().fuse(), o!() ); slog_scope::set_global_logger(log) } @@ -73,20 +80,49 @@ struct TelemetryWriter { buffer: Vec, out: Mutex>>>, config: TelemetryConfig, - first_time: bool, + last_time: Option, } +/// Every two minutes we reconnect to the telemetry server otherwise we don't get notified +/// of a flakey connection that has been dropped and needs to be reconnected. We can remove +/// this once we introduce a keepalive ping/pong. +const RECONNECT_PERIOD: u64 = 120; + impl TelemetryWriter { fn ensure_connected(&mut self) { - if self.first_time { - info!("Connected to telemetry server: {}", self.config.url); - (self.config.on_connect)(); - self.first_time = false; - } let mut client = self.out.lock(); - if client.is_none() { + + let controlled_disconnect = if let Some(t) = self.last_time { + if t.elapsed().as_secs() > RECONNECT_PERIOD && client.is_some() { + trace!(target: "telemetry", "Performing controlled drop of the telemetry connection."); + let _ = client.as_mut().and_then(|socket| + socket.send_message(&ws::Message::text("{\"msg\":\"system.reconnect\"}")).ok() + ); + *client = None; + true + } else { + false + } + } else { + false + }; + + let just_connected = if client.is_none() { + if !controlled_disconnect { + info!(target: "telemetry", "Connection dropped unexpectedly. Reconnecting to telemetry server..."); + } *client = ws::ClientBuilder::new(&self.config.url).ok().and_then(|mut x| x.connect(None).ok()); - drop(client); + client.is_some() + } else { + self.last_time.is_none() + }; + + drop(client); + if just_connected { + if !controlled_disconnect { + info!("Reconnected to telemetry server: {}", self.config.url); + } + self.last_time = Some(time::Instant::now()); (self.config.on_connect)(); } } @@ -108,7 +144,9 @@ impl io::Write for TelemetryWriter { let mut l = self.out.lock(); let socket_closed = if let Some(ref mut socket) = *l { if let Ok(s) = ::std::str::from_utf8(&self.buffer[..]) { - socket.send_message(&ws::Message::text(s)).is_err() + let r = socket.send_message(&ws::Message::text(s)); + trace!(target: "telemetry", "Sent to telemetry: {} -> {:?}", s, r); + r.is_err() } else { false } } else { false }; if socket_closed { diff --git a/substrate/test-client/Cargo.toml b/substrate/test-client/Cargo.toml index bec520419f48e..4897dae974704 100644 --- a/substrate/test-client/Cargo.toml +++ b/substrate/test-client/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] +rhododendron = "0.2" substrate-bft = { path = "../bft" } substrate-client = { path = "../client" } substrate-codec = { path = "../codec" } diff --git a/substrate/test-client/src/client_ext.rs b/substrate/test-client/src/client_ext.rs index ac8f7ce50838c..be1e9dfe55026 100644 --- a/substrate/test-client/src/client_ext.rs +++ b/substrate/test-client/src/client_ext.rs @@ -20,9 +20,10 @@ use client::{self, Client}; use keyring::Keyring; use runtime_primitives::StorageMap; use runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}; +use executor::NativeExecutor; use runtime; use bft; -use {Backend, Executor, NativeExecutor}; +use {Backend, Executor}; /// Extension trait for a test client. pub trait TestClient { @@ -38,7 +39,7 @@ pub trait TestClient { impl TestClient for Client { fn new_for_tests() -> Self { - client::new_in_mem(NativeExecutor::new(), genesis_storage()).unwrap() + client::new_in_mem(NativeExecutor::with_heap_pages(8, 8), genesis_storage()).unwrap() } fn justify_and_import(&self, origin: client::BlockOrigin, block: runtime::Block) -> client::error::Result<()> { @@ -68,29 +69,29 @@ fn fake_justify(header: &runtime::Header) -> bft::UncheckedJustification( - bft::generic::Vote::Commit(1, hash).into(), + ::rhododendron::Vote::Commit(1, hash).into(), key, header.parent_hash ); match msg { - bft::generic::LocalizedMessage::Vote(vote) => vote.signature, + ::rhododendron::LocalizedMessage::Vote(vote) => vote.signature, _ => panic!("signing vote leads to signed vote"), } }).collect(), - round_number: 1, - } + 1, + ) } fn genesis_config() -> GenesisConfig { GenesisConfig::new_simple(vec![ - Keyring::Alice.to_raw_public(), - Keyring::Bob.to_raw_public(), - Keyring::Charlie.to_raw_public() + Keyring::Alice.to_raw_public().into(), + Keyring::Bob.to_raw_public().into(), + Keyring::Charlie.to_raw_public().into(), ], 1000) } diff --git a/substrate/test-client/src/lib.rs b/substrate/test-client/src/lib.rs index 1500e603a07fe..d50b49b3c7101 100644 --- a/substrate/test-client/src/lib.rs +++ b/substrate/test-client/src/lib.rs @@ -18,6 +18,7 @@ #![warn(missing_docs)] +extern crate rhododendron; extern crate substrate_bft as bft; extern crate substrate_codec as codec; extern crate substrate_keyring as keyring; @@ -33,21 +34,21 @@ mod client_ext; pub use client_ext::TestClient; -mod native_executor { +mod local_executor { #![allow(missing_docs)] use super::runtime; - native_executor_instance!(pub NativeExecutor, runtime::api::dispatch, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm")); + native_executor_instance!(pub LocalExecutor, runtime::api::dispatch, runtime::VERSION, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm")); } /// Native executor used for tests. -pub use self::native_executor::NativeExecutor; +pub use local_executor::LocalExecutor; /// Test client database backend. pub type Backend = client::in_mem::Backend; /// Test client executor. -pub type Executor = client::LocalCallExecutor>; +pub type Executor = client::LocalCallExecutor>; /// Creates new client instance used for tests. pub fn new() -> client::Client { diff --git a/substrate/test-runtime/Cargo.toml b/substrate/test-runtime/Cargo.toml index bd0654e2ef945..f955d0eab3bee 100644 --- a/substrate/test-runtime/Cargo.toml +++ b/substrate/test-runtime/Cargo.toml @@ -16,6 +16,7 @@ substrate-runtime-io = { path = "../runtime-io", default-features = false } substrate-runtime-support = { path = "../runtime-support", default-features = false } substrate-primitives = { path = "../primitives", default-features = false } substrate-runtime-primitives = { path = "../runtime/primitives", default-features = false } +substrate-runtime-version = { path = "../runtime/version", default-features = false } [features] default = ["std"] @@ -31,5 +32,6 @@ std = [ "substrate-runtime-io/std", "substrate-runtime-support/std", "substrate-primitives/std", - "substrate-runtime-primitives/std" + "substrate-runtime-primitives/std", + "substrate-runtime-version/std" ] diff --git a/substrate/test-runtime/src/genesismap.rs b/substrate/test-runtime/src/genesismap.rs index 10bf1751f4c99..2ded178c3fba1 100644 --- a/substrate/test-runtime/src/genesismap.rs +++ b/substrate/test-runtime/src/genesismap.rs @@ -37,7 +37,7 @@ impl GenesisConfig { } pub fn genesis_map(&self) -> HashMap, Vec> { - let wasm_runtime = include_bytes!("../wasm/genesis.wasm").to_vec(); + let wasm_runtime = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm").to_vec(); self.balances.iter() .map(|&(account, balance)| (account.to_keyed_vec(b"balance:"), vec![].and(&balance))) .map(|(k, v)| (twox_128(&k[..])[..].to_vec(), v.to_vec())) diff --git a/substrate/test-runtime/src/lib.rs b/substrate/test-runtime/src/lib.rs index 8454a8c7bd60c..6865ad4e28520 100644 --- a/substrate/test-runtime/src/lib.rs +++ b/substrate/test-runtime/src/lib.rs @@ -43,18 +43,34 @@ extern crate substrate_keyring as keyring; extern crate substrate_primitives as primitives; #[macro_use] extern crate substrate_runtime_io as runtime_io; +#[macro_use] +extern crate substrate_runtime_version as runtime_version; #[cfg(feature = "std")] pub mod genesismap; pub mod system; use rstd::prelude::*; -use codec::Slicable; +use codec::{Encode, Decode}; use runtime_primitives::traits::{BlindCheckable, BlakeTwo256}; use runtime_primitives::Ed25519Signature; +use runtime_version::RuntimeVersion; pub use primitives::hash::H256; +/// Test runtime version. +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: ver_str!("test"), + impl_name: ver_str!("parity-test"), + authoring_version: 1, + spec_version: 1, + impl_version: 1, +}; + +fn version() -> RuntimeVersion { + VERSION +} + /// Calls in transactions. #[derive(Clone, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] @@ -65,18 +81,18 @@ pub struct Transfer { pub nonce: u64, } -impl Slicable for Transfer { - fn encode(&self) -> Vec { - let mut v = Vec::new(); - self.from.using_encoded(|s| v.extend(s)); - self.to.using_encoded(|s| v.extend(s)); - self.amount.using_encoded(|s| v.extend(s)); - self.nonce.using_encoded(|s| v.extend(s)); - v +impl Encode for Transfer { + fn encode_to(&self, dest: &mut T) { + self.from.encode_to(dest); + self.to.encode_to(dest); + self.amount.encode_to(dest); + self.nonce.encode_to(dest); } +} +impl Decode for Transfer { fn decode(input: &mut I) -> Option { - Slicable::decode(input).map(|(from, to, amount, nonce)| Transfer { from, to, amount, nonce }) + Decode::decode(input).map(|(from, to, amount, nonce)| Transfer { from, to, amount, nonce }) } } @@ -88,26 +104,22 @@ pub struct Extrinsic { pub signature: Ed25519Signature, } -impl Slicable for Extrinsic { - fn encode(&self) -> Vec { - let mut v = Vec::new(); - self.transfer.using_encoded(|s| v.extend(s)); - self.signature.using_encoded(|s| v.extend(s)); - v +impl Encode for Extrinsic { + fn encode_to(&self, dest: &mut T) { + self.transfer.encode_to(dest); + self.signature.encode_to(dest); } +} +impl Decode for Extrinsic { fn decode(input: &mut I) -> Option { - Slicable::decode(input).map(|(transfer, signature)| Extrinsic { transfer, signature }) + Decode::decode(input).map(|(transfer, signature)| Extrinsic { transfer, signature }) } } impl BlindCheckable for Extrinsic { type Checked = Self; - type Address = AccountId; - fn sender(&self) -> &Self::Address { - &self.transfer.from - } fn check(self) -> Result { if ::runtime_primitives::verify_encoded_lazy(&self.signature, &self.transfer, &self.transfer.from) { Ok(self) @@ -139,15 +151,15 @@ pub fn run_tests(mut input: &[u8]) -> Vec { print("run_tests..."); let block = Block::decode(&mut input).unwrap(); print("deserialised block."); - let stxs = block.extrinsics.iter().map(Slicable::encode).collect::>(); + let stxs = block.extrinsics.iter().map(Encode::encode).collect::>(); print("reserialised transactions."); [stxs.len() as u8].encode() } pub mod api { use system; - impl_stubs!( + version => |()| super::version(), authorities => |()| system::authorities(), initialise_block => |header| system::initialise_block(header), execute_block => |block| system::execute_block(block), diff --git a/substrate/test-runtime/src/system.rs b/substrate/test-runtime/src/system.rs index f549954aa8a70..cb5ae23eb6c32 100644 --- a/substrate/test-runtime/src/system.rs +++ b/substrate/test-runtime/src/system.rs @@ -20,8 +20,9 @@ use rstd::prelude::*; use runtime_io::{storage_root, enumerated_trie_root}; use runtime_support::storage::{self, StorageValue, StorageMap}; -use runtime_primitives::traits::{Hashing, BlakeTwo256}; -use codec::{KeyedVec, Slicable}; +use runtime_primitives::traits::{Hash as HashT, BlakeTwo256}; +use runtime_primitives::{ApplyError, ApplyOutcome, ApplyResult}; +use codec::{KeyedVec, Encode}; use super::{AccountId, BlockNumber, Extrinsic, H256 as Hash, Block, Header}; const NONCE_OF: &[u8] = b"nonce:"; @@ -65,28 +66,28 @@ pub fn execute_block(block: Block) { let ref header = block.header; // check transaction trie root represents the transactions. - let txs = block.extrinsics.iter().map(Slicable::encode).collect::>(); + let txs = block.extrinsics.iter().map(Encode::encode).collect::>(); let txs = txs.iter().map(Vec::as_slice).collect::>(); let txs_root = enumerated_trie_root(&txs).into(); - info_expect_equal_hash(&header.extrinsics_root, &txs_root); - assert!(header.extrinsics_root == txs_root, "Transaction trie root must be valid."); + info_expect_equal_hash(&txs_root, &header.extrinsics_root); + assert!(txs_root == header.extrinsics_root, "Transaction trie root must be valid."); // execute transactions - block.extrinsics.iter().for_each(execute_transaction_backend); + block.extrinsics.iter().for_each(|e| { execute_transaction_backend(e).map_err(|_| ()).expect("Extrinsic error"); }); // check storage root. let storage_root = storage_root().into(); - info_expect_equal_hash(&header.state_root, &storage_root); - assert!(header.state_root == storage_root, "Storage root must match that calculated."); + info_expect_equal_hash(&storage_root, &header.state_root); + assert!(storage_root == header.state_root, "Storage root must match that calculated."); } /// Execute a transaction outside of the block execution function. /// This doesn't attempt to validate anything regarding the block. -pub fn execute_transaction(utx: Extrinsic) { +pub fn execute_transaction(utx: Extrinsic) -> ApplyResult { let extrinsic_index = ExtrinsicIndex::get(); ExtrinsicData::insert(extrinsic_index, utx.encode()); ExtrinsicIndex::put(extrinsic_index + 1); - execute_transaction_backend(&utx); + execute_transaction_backend(&utx) } /// Finalise the block. @@ -109,13 +110,13 @@ pub fn finalise_block() -> Header { } } -fn execute_transaction_backend(utx: &Extrinsic) { +fn execute_transaction_backend(utx: &Extrinsic) -> ApplyResult { use runtime_primitives::traits::BlindCheckable; // check signature let utx = match utx.clone().check() { Ok(tx) => tx, - Err(_) => panic!("All transactions should be properly signed"), + Err(_) => return Err(ApplyError::BadSignature), }; let tx: ::Transfer = utx.transfer; @@ -123,7 +124,9 @@ fn execute_transaction_backend(utx: &Extrinsic) { // check nonce let nonce_key = tx.from.to_keyed_vec(NONCE_OF); let expected_nonce: u64 = storage::get_or(&nonce_key, 0); - assert!(tx.nonce == expected_nonce, "All transactions should have the correct nonce"); + if !(tx.nonce == expected_nonce) { + return Err(ApplyError::Stale) + } // increment nonce in storage storage::put(&nonce_key, &(expected_nonce + 1)); @@ -133,11 +136,14 @@ fn execute_transaction_backend(utx: &Extrinsic) { let from_balance: u64 = storage::get_or(&from_balance_key, 0); // enact transfer - assert!(tx.amount <= from_balance, "All transactions should transfer at most the sender balance"); + if !(tx.amount <= from_balance) { + return Err(ApplyError::CantPay) + } let to_balance_key = tx.to.to_keyed_vec(BALANCE_OF); let to_balance: u64 = storage::get_or(&to_balance_key, 0); storage::put(&from_balance_key, &(from_balance - tx.amount)); storage::put(&to_balance_key, &(to_balance + tx.amount)); + Ok(ApplyOutcome::Success) } #[cfg(feature = "std")] diff --git a/substrate/test-runtime/wasm/Cargo.lock b/substrate/test-runtime/wasm/Cargo.lock index 9a04185ff1eb3..e78284183ae39 100644 --- a/substrate/test-runtime/wasm/Cargo.lock +++ b/substrate/test-runtime/wasm/Cargo.lock @@ -137,11 +137,6 @@ dependencies = [ name = "environmental" version = "0.1.0" -[[package]] -name = "error-chain" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "ethbloom" version = "0.5.0" @@ -294,16 +289,6 @@ dependencies = [ "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "kvdb" -version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#dec390a89fe038337399315daf15e628ffbb4d8e" -dependencies = [ - "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)", -] - [[package]] name = "lazy_static" version = "0.2.11" @@ -367,6 +352,11 @@ dependencies = [ "rlp 0.2.1 (git+https://github.com/paritytech/parity.git)", ] +[[package]] +name = "nan-preserving-float" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "nodrop" version = "0.1.12" @@ -395,12 +385,10 @@ dependencies = [ [[package]] name = "parity-wasm" -version = "0.27.6" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -690,7 +678,7 @@ dependencies = [ "substrate-runtime-std 0.1.0", "twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)", - "wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -712,6 +700,7 @@ name = "substrate-runtime-primitives" version = "0.1.0" dependencies = [ "integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", @@ -745,6 +734,17 @@ dependencies = [ "substrate-runtime-std 0.1.0", ] +[[package]] +name = "substrate-runtime-version" +version = "0.1.0" +dependencies = [ + "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", +] + [[package]] name = "substrate-state-machine" version = "0.1.0" @@ -753,7 +753,6 @@ dependencies = [ "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.1 (git+https://github.com/paritytech/parity.git)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity.git)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "memorydb 0.1.1 (git+https://github.com/paritytech/parity.git)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -775,6 +774,7 @@ dependencies = [ "substrate-runtime-primitives 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", + "substrate-runtime-version 0.1.0", ] [[package]] @@ -910,12 +910,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasmi" -version = "0.1.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.27.6 (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.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -955,7 +956,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" -"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386" "checksum ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum ethcore-logger 1.12.0 (git+https://github.com/paritytech/parity.git)" = "" @@ -973,7 +973,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)" = "" "checksum keccak-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b7f51f30d7986536accaec4a6a288008dfb3dbffe8a2863a65292bc395a3ae7" "checksum keccak-hash 0.1.2 (git+https://github.com/paritytech/parity.git)" = "" -"checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739" "checksum libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)" = "ac8ebf8343a981e2fa97042b14768f02ed3e1d602eac06cae6166df3c8ced206" @@ -983,11 +982,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" "checksum memorydb 0.1.1 (git+https://github.com/paritytech/parity.git)" = "" +"checksum nan-preserving-float 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34d4f00fcc2f4c9efa8cc971db0da9e28290e28e97af47585e48691ef10ff31f" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum parity-wasm 0.27.6 (registry+https://github.com/rust-lang/crates.io-index)" = "bd4dc02a80a0315b109e48992c46942c79bcdb8fac416dd575d330ed9ced6cbd" +"checksum parity-wasm 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1c91199d14bd5b78ecade323d4a891d094799749c1b9e82d9c590c2e2849a40" "checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" "checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" @@ -1034,7 +1034,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d19da510b59247935ad5f598357b3cc739912666d75d3d28318026478d95bbdb" +"checksum wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b4a6d379e9332b1b1f52c5a87f2481c85c7c931d8ec411963dfb8f26b1ec1e3" "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/substrate/test-runtime/wasm/Cargo.toml b/substrate/test-runtime/wasm/Cargo.toml index 99d86cd6a4c5b..61e7c594cc2af 100644 --- a/substrate/test-runtime/wasm/Cargo.toml +++ b/substrate/test-runtime/wasm/Cargo.toml @@ -11,6 +11,7 @@ substrate-codec = { path = "../../codec", default-features = false } substrate-runtime-std = { path = "../../runtime-std", default-features = false } substrate-runtime-io = { path = "../../runtime-io", default-features = false } substrate-runtime-support = { path = "../../runtime-support", default-features = false } +substrate-runtime-version = { path = "../../runtime/version", default-features = false } substrate-primitives = { path = "../../primitives", default-features = false } substrate-runtime-primitives = { path = "../../runtime/primitives", default-features = false } @@ -24,6 +25,7 @@ std = [ "substrate-runtime-std/std", "substrate-runtime-io/std", "substrate-runtime-support/std", + "substrate-runtime-version/std", "substrate-primitives/std", "substrate-runtime-primitives/std" ] diff --git a/substrate/test-runtime/wasm/build.sh b/substrate/test-runtime/wasm/build.sh index 4cb6edb9c9caa..63d9347bf461c 100755 --- a/substrate/test-runtime/wasm/build.sh +++ b/substrate/test-runtime/wasm/build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e cargo +nightly build --target=wasm32-unknown-unknown --release diff --git a/substrate/test-runtime/wasm/genesis.wasm b/substrate/test-runtime/wasm/genesis.wasm deleted file mode 100644 index 94bf42b3f97dd..0000000000000 Binary files a/substrate/test-runtime/wasm/genesis.wasm and /dev/null differ diff --git a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index e1bdf7abaf56e..6356848ee723a 100644 Binary files a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm and b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm differ diff --git a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm index 7f7322384f277..3dbbf9b9f3ba1 100755 Binary files a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm and b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm differ diff --git a/update-genesis.sh b/update-genesis.sh deleted file mode 100755 index 07632668c49b0..0000000000000 --- a/update-genesis.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -cp polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm polkadot/runtime/wasm/genesis.wasm

, executor: TaskExecutor) -> Self { + Author { + client, + pool, + subscriptions: Subscriptions::new(executor), + } } } -impl AuthorApi for Arc where - T: ExtrinsicPool, - T::Error: 'static, +impl AuthorApi for Author where + B: client::backend::Backend + Send + Sync + 'static, + E: client::CallExecutor + Send + Sync + 'static, + Block: traits::Block + 'static, + Hash: traits::MaybeSerializeDebug + Sync + Send + 'static, + P: ExtrinsicPool, Hash>, + P::Error: 'static, + Ex: Codec, { - fn submit_extrinsic(&self, xt: Ex) -> Result { - self - .submit(vec![xt]) + type Metadata = ::metadata::Metadata; + + fn submit_extrinsic(&self, xt: Bytes) -> Result { + let dxt = Ex::decode(&mut &xt[..]).ok_or(error::Error::from(error::ErrorKind::BadFormat))?; + self.submit_rich_extrinsic(dxt) + } + + fn submit_rich_extrinsic(&self, xt: Ex) -> Result { + let best_block_hash = self.client.info()?.chain.best_hash; + self.pool + .submit(generic::BlockId::hash(best_block_hash), vec![xt]) .map(|mut res| res.pop().expect("One extrinsic passed; one result back; qed")) .map_err(|e| e.into_pool_error() .map(Into::into) .unwrap_or_else(|e| error::ErrorKind::Verification(Box::new(e)).into()) ) } + + fn watch_extrinsic(&self, _metadata: Self::Metadata, subscriber: pubsub::Subscriber>, xt: Bytes) { + + let submit = || -> Result<_> { + let best_block_hash = self.client.info()?.chain.best_hash; + let dxt = Ex::decode(&mut &xt[..]).ok_or(error::Error::from(error::ErrorKind::BadFormat))?; + self.pool + .submit_and_watch(generic::BlockId::hash(best_block_hash), dxt) + .map_err(|e| e.into_pool_error() + .map(Into::into) + .unwrap_or_else(|e| error::ErrorKind::Verification(Box::new(e)).into()) + ) + }; + + let watcher = match submit() { + Ok(watcher) => watcher, + Err(err) => { + // reject the subscriber (ignore errors - we don't care if subscriber is no longer there). + let _ = subscriber.reject(err.into()); + return; + }, + }; + + self.subscriptions.add(subscriber, move |sink| { + sink + .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) + .send_all(watcher.into_stream().map(Ok)) + .map(|_| ()) + }) + } + + fn unwatch_extrinsic(&self, id: SubscriptionId) -> Result { + Ok(self.subscriptions.cancel(id)) + } } diff --git a/substrate/rpc/src/author/tests.rs b/substrate/rpc/src/author/tests.rs index 8e9963613d66e..116ca7ea2c7bc 100644 --- a/substrate/rpc/src/author/tests.rs +++ b/substrate/rpc/src/author/tests.rs @@ -16,9 +16,12 @@ use super::*; -use std::{fmt, sync::Arc}; -use extrinsic_pool::api; +use std::{fmt, sync::Arc, result::Result}; +use codec::Encode; +use extrinsic_pool::{api, txpool, watcher::{self, Watcher}}; use parking_lot::Mutex; +use test_client; +use tokio::runtime; type Extrinsic = u64; type Hash = u64; @@ -26,6 +29,7 @@ type Hash = u64; #[derive(Default)] struct DummyTxPool { submitted: Mutex>, + sender: Mutex>>, } #[derive(Debug)] @@ -40,11 +44,11 @@ impl fmt::Display for Error { } } -impl api::ExtrinsicPool for DummyTxPool { +impl api::ExtrinsicPool for DummyTxPool { type Error = Error; /// Submit extrinsic for inclusion in block. - fn submit(&self, xt: Vec) -> ::std::result::Result, Self::Error> { + fn submit(&self, _block: BlockHash, xt: Vec) -> Result, Self::Error> { let mut submitted = self.submitted.lock(); if submitted.len() < 1 { let hashes = xt.iter().map(|_xt| 1).collect(); @@ -54,17 +58,88 @@ impl api::ExtrinsicPool for DummyTxPool { Err(Error) } } + + fn submit_and_watch(&self, _block: BlockHash, xt: Extrinsic) -> Result, Self::Error> { + let mut submitted = self.submitted.lock(); + if submitted.len() < 1 { + submitted.push(xt); + let mut sender = watcher::Sender::default(); + let watcher = sender.new_watcher(); + *self.sender.lock() = Some(sender); + Ok(watcher) + } else { + Err(Error) + } + } + + fn light_status(&self) -> txpool::LightStatus { + unreachable!() + } + + fn import_notification_stream(&self) -> api::EventStream { + unreachable!() + } } #[test] fn submit_transaction_should_not_cause_error() { - let p = Arc::new(DummyTxPool::default()); + let runtime = runtime::Runtime::new().unwrap(); + let p = Author { + client: Arc::new(test_client::new()), + pool: Arc::new(DummyTxPool::default()), + subscriptions: Subscriptions::new(runtime.executor()), + }; + + assert_matches!( + AuthorApi::submit_extrinsic(&p, u64::encode(&5).into()), + Ok(1) + ); + assert!( + AuthorApi::submit_extrinsic(&p, u64::encode(&5).into()).is_err() + ); +} + +#[test] +fn submit_rich_transaction_should_not_cause_error() { + let runtime = runtime::Runtime::new().unwrap(); + let p = Author { + client: Arc::new(test_client::new()), + pool: Arc::new(DummyTxPool::default()), + subscriptions: Subscriptions::new(runtime.executor()), + }; assert_matches!( - AuthorApi::submit_extrinsic(&p, 5), + AuthorApi::submit_rich_extrinsic(&p, 5), Ok(1) ); assert!( - AuthorApi::submit_extrinsic(&p, 5).is_err() + AuthorApi::submit_rich_extrinsic(&p, 5).is_err() + ); +} + +#[test] +fn should_watch_extrinsic() { + //given + let mut runtime = runtime::Runtime::new().unwrap(); + let pool = Arc::new(DummyTxPool::default()); + let p = Author { + client: Arc::new(test_client::new()), + pool: pool.clone(), + subscriptions: Subscriptions::new(runtime.executor()), + }; + let (subscriber, id_rx, data) = ::jsonrpc_macros::pubsub::Subscriber::new_test("test"); + + // when + p.watch_extrinsic(Default::default(), subscriber, u64::encode(&5).into()); + + // then + assert_eq!(runtime.block_on(id_rx), Ok(Ok(0.into()))); + + // check notifications + pool.sender.lock().as_mut().unwrap().usurped(5); + + assert_eq!( + runtime.block_on(data.into_future()).unwrap().0, + Some(r#"{"jsonrpc":"2.0","method":"test","params":{"result":{"usurped":5},"subscription":0}}"#.into()) ); } diff --git a/substrate/rpc/src/chain/error.rs b/substrate/rpc/src/chain/error.rs index fb55a643ea098..59035a030b14c 100644 --- a/substrate/rpc/src/chain/error.rs +++ b/substrate/rpc/src/chain/error.rs @@ -16,6 +16,8 @@ use rpc; +use errors; + error_chain! { errors { /// Not implemented yet @@ -29,12 +31,8 @@ error_chain! { impl From for rpc::Error { fn from(e: Error) -> Self { match e { - Error(ErrorKind::Unimplemented, _) => rpc::Error { - code: rpc::ErrorCode::ServerError(-1), - message: "Not implemented yet".into(), - data: None, - }, - _ => rpc::Error::internal_error(), + Error(ErrorKind::Unimplemented, _) => errors::unimplemented(), + e => errors::internal(e), } } } diff --git a/substrate/rpc/src/chain/mod.rs b/substrate/rpc/src/chain/mod.rs index 04bd4896b555a..d1d055b5c0ff8 100644 --- a/substrate/rpc/src/chain/mod.rs +++ b/substrate/rpc/src/chain/mod.rs @@ -21,13 +21,12 @@ use std::sync::Arc; use runtime_primitives::traits::Block as BlockT; use runtime_primitives::generic::BlockId; use client::{self, Client, BlockchainEvents}; -use state_machine; use jsonrpc_macros::pubsub; use jsonrpc_pubsub::SubscriptionId; use rpc::Result as RpcResult; use rpc::futures::{Future, Sink, Stream}; -use tokio_core::reactor::Remote; +use tokio::runtime::TaskExecutor; use subscriptions::Subscriptions; @@ -72,10 +71,10 @@ pub struct Chain { impl Chain { /// Create new Chain API RPC handler. - pub fn new(client: Arc>, remote: Remote) -> Self { + pub fn new(client: Arc>, executor: TaskExecutor) -> Self { Chain { client, - subscriptions: Subscriptions::new(remote), + subscriptions: Subscriptions::new(executor), } } } @@ -84,7 +83,6 @@ impl ChainApi for Chain wh Block: BlockT + 'static, B: client::backend::Backend + Send + Sync + 'static, E: client::CallExecutor + Send + Sync + 'static, - client::error::Error: From<<>::State as state_machine::backend::Backend>::Error>, { type Metadata = ::metadata::Metadata; diff --git a/substrate/rpc/src/chain/tests.rs b/substrate/rpc/src/chain/tests.rs index 51fb7b907574a..0ac2506292e8c 100644 --- a/substrate/rpc/src/chain/tests.rs +++ b/substrate/rpc/src/chain/tests.rs @@ -22,8 +22,8 @@ use test_client::runtime::Header; #[test] fn should_return_header() { - let core = ::tokio_core::reactor::Core::new().unwrap(); - let remote = core.remote(); + let core = ::tokio::runtime::Runtime::new().unwrap(); + let remote = core.executor(); let client = Chain { client: Arc::new(test_client::new()), @@ -34,7 +34,7 @@ fn should_return_header() { Ok(Some(ref x)) if x == &Header { parent_hash: 0.into(), number: 0, - state_root: "987aa0851a133413b42c6d9aa3c91b1dddc2ad5337508ee8815116b11e44c64d".into(), + state_root: x.state_root.clone(), extrinsics_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".into(), digest: Default::default(), } @@ -48,8 +48,8 @@ fn should_return_header() { #[test] fn should_notify_about_latest_block() { - let mut core = ::tokio_core::reactor::Core::new().unwrap(); - let remote = core.remote(); + let mut core = ::tokio::runtime::Runtime::new().unwrap(); + let remote = core.executor(); let (subscriber, id, transport) = pubsub::Subscriber::new_test("test"); { @@ -61,17 +61,15 @@ fn should_notify_about_latest_block() { api.subscribe_new_head(Default::default(), subscriber); // assert id assigned - assert_eq!(core.run(id), Ok(Ok(SubscriptionId::Number(0)))); + assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(0)))); let builder = api.client.new_block().unwrap(); api.client.justify_and_import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); } // assert notification send to transport - let (notification, next) = core.run(transport.into_future()).unwrap(); - assert_eq!(notification, Some( - r#"{"jsonrpc":"2.0","method":"test","params":{"result":{"digest":{"logs":[]},"extrinsicsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","number":1,"parentHash":"0x27f04d7574733bb155bbf5a0399fcc99d3c4dbf15bf99862d261bced9444179a","stateRoot":"0x987aa0851a133413b42c6d9aa3c91b1dddc2ad5337508ee8815116b11e44c64d"},"subscription":0}}"#.to_owned() - )); + let (notification, next) = core.block_on(transport.into_future()).unwrap(); + assert!(notification.is_some()); // no more notifications on this channel - assert_eq!(core.run(next.into_future()).unwrap().0, None); + assert_eq!(core.block_on(next.into_future()).unwrap().0, None); } diff --git a/substrate/rpc/src/errors.rs b/substrate/rpc/src/errors.rs new file mode 100644 index 0000000000000..a9b9e27a9cbc6 --- /dev/null +++ b/substrate/rpc/src/errors.rs @@ -0,0 +1,34 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +use rpc; + +pub fn unimplemented() -> rpc::Error { + rpc::Error { + code: rpc::ErrorCode::ServerError(1), + message: "Not implemented yet".into(), + data: None, + } +} + +pub fn internal(e: E) -> rpc::Error { + warn!("Unknown error: {:?}", e); + rpc::Error { + code: rpc::ErrorCode::InternalError, + message: "Unknown error occured".into(), + data: Some(format!("{:?}", e).into()), + } +} diff --git a/substrate/rpc/src/lib.rs b/substrate/rpc/src/lib.rs index 8cd043652ae57..5dcc9d337aab3 100644 --- a/substrate/rpc/src/lib.rs +++ b/substrate/rpc/src/lib.rs @@ -21,12 +21,13 @@ extern crate jsonrpc_core as rpc; extern crate jsonrpc_pubsub; extern crate parking_lot; +extern crate substrate_codec as codec; extern crate substrate_client as client; extern crate substrate_extrinsic_pool as extrinsic_pool; extern crate substrate_primitives as primitives; extern crate substrate_runtime_primitives as runtime_primitives; extern crate substrate_state_machine as state_machine; -extern crate tokio_core; +extern crate tokio; #[macro_use] extern crate error_chain; @@ -41,6 +42,7 @@ extern crate assert_matches; #[cfg(test)] extern crate substrate_test_client as test_client; +mod errors; mod subscriptions; pub mod author; diff --git a/substrate/rpc/src/metadata.rs b/substrate/rpc/src/metadata.rs index c40a6ad0542c1..41bed2b845ffc 100644 --- a/substrate/rpc/src/metadata.rs +++ b/substrate/rpc/src/metadata.rs @@ -18,6 +18,7 @@ use std::sync::Arc; use jsonrpc_pubsub::{Session, PubSubMetadata}; +use rpc::futures::sync::mpsc; /// RPC Metadata. /// @@ -38,9 +39,16 @@ impl PubSubMetadata for Metadata { impl Metadata { /// Create new `Metadata` with session (Pub/Sub) support. - pub fn new(transport: ::rpc::futures::sync::mpsc::Sender) -> Self { + pub fn new(transport: mpsc::Sender) -> Self { Metadata { session: Some(Arc::new(Session::new(transport))), } } + + /// Create new `Metadata` for tests. + #[cfg(test)] + pub fn new_test() -> (mpsc::Receiver, Self) { + let (tx, rx) = mpsc::channel(1); + (rx, Self::new(tx)) + } } diff --git a/substrate/rpc/src/state/error.rs b/substrate/rpc/src/state/error.rs index 57db7d18fe7e9..24adeb29d386a 100644 --- a/substrate/rpc/src/state/error.rs +++ b/substrate/rpc/src/state/error.rs @@ -17,6 +17,8 @@ use client; use rpc; +use errors; + error_chain! { links { Client(client::error::Error, client::error::ErrorKind) #[doc = "Client error"]; @@ -34,12 +36,8 @@ error_chain! { impl From for rpc::Error { fn from(e: Error) -> Self { match e { - Error(ErrorKind::Unimplemented, _) => rpc::Error { - code: rpc::ErrorCode::ServerError(-1), - message: "Not implemented yet".into(), - data: None, - }, - _ => rpc::Error::internal_error(), + Error(ErrorKind::Unimplemented, _) => errors::unimplemented(), + e => errors::internal(e), } } } diff --git a/substrate/rpc/src/state/mod.rs b/substrate/rpc/src/state/mod.rs index 4c68beb507d9f..40d6f70f6c318 100644 --- a/substrate/rpc/src/state/mod.rs +++ b/substrate/rpc/src/state/mod.rs @@ -28,7 +28,6 @@ use runtime_primitives::generic::BlockId; use runtime_primitives::traits::Block as BlockT; use primitives::storage::{StorageKey, StorageData}; use primitives::hexdisplay::HexDisplay; -use state_machine; use self::error::Result; @@ -73,7 +72,6 @@ impl StateApi for Arc> where Block: BlockT + 'static, B: client::backend::Backend + Send + Sync + 'static, E: CallExecutor + Send + Sync + 'static, - client::error::Error: From<<>::State as state_machine::backend::Backend>::Error>, { fn storage_at(&self, key: StorageKey, block: Block::Hash) -> Result { trace!(target: "rpc", "Querying storage at {:?} for key {}", block, HexDisplay::from(&key.0)); @@ -86,7 +84,7 @@ impl StateApi for Arc> where } fn storage_hash_at(&self, key: StorageKey, block: Block::Hash) -> Result { - use runtime_primitives::traits::{Hashing, Header as HeaderT}; + use runtime_primitives::traits::{Hash, Header as HeaderT}; self.storage_at(key, block).map(|x| ::Hashing::hash(&x.0)) } diff --git a/substrate/rpc/src/subscriptions.rs b/substrate/rpc/src/subscriptions.rs index 60536e5a6d801..9013edf742e1c 100644 --- a/substrate/rpc/src/subscriptions.rs +++ b/substrate/rpc/src/subscriptions.rs @@ -22,7 +22,7 @@ use jsonrpc_pubsub::SubscriptionId; use parking_lot::Mutex; use rpc::futures::sync::oneshot; use rpc::futures::{Future, future}; -use tokio_core::reactor::Remote; +use tokio::runtime::TaskExecutor; type Id = u64; @@ -34,16 +34,16 @@ type Id = u64; pub struct Subscriptions { next_id: AtomicUsize, active_subscriptions: Mutex>>, - event_loop: Remote, + executor: TaskExecutor, } impl Subscriptions { /// Creates new `Subscriptions` object. - pub fn new(event_loop: Remote) -> Self { + pub fn new(executor: TaskExecutor) -> Self { Subscriptions { next_id: Default::default(), active_subscriptions: Default::default(), - event_loop, + executor, } } @@ -63,11 +63,10 @@ impl Subscriptions { let future = into_future(sink) .into_future() .select(rx.map_err(|e| warn!("Error timeing out: {:?}", e))) - .map(|_| ()) - .map_err(|_| ()); + .then(|_| Ok(())); self.active_subscriptions.lock().insert(id, tx); - self.event_loop.spawn(|_| future); + self.executor.spawn(future); } } diff --git a/substrate/rpc/src/system/error.rs b/substrate/rpc/src/system/error.rs index 2fe155f23e3fe..42d215caefd33 100644 --- a/substrate/rpc/src/system/error.rs +++ b/substrate/rpc/src/system/error.rs @@ -18,6 +18,8 @@ use rpc; +use errors; + error_chain! { errors { /// Not implemented yet @@ -31,12 +33,8 @@ error_chain! { impl From for rpc::Error { fn from(e: Error) -> Self { match e { - Error(ErrorKind::Unimplemented, _) => rpc::Error { - code: rpc::ErrorCode::ServerError(-1), - message: "Not implemented yet".into(), - data: None, - }, - _ => rpc::Error::internal_error(), + Error(ErrorKind::Unimplemented, _) => errors::unimplemented(), + e => errors::internal(e), } } } diff --git a/substrate/runtime-io/src/lib.rs b/substrate/runtime-io/src/lib.rs index b3373fb46dc09..9d57f537f73d8 100644 --- a/substrate/runtime-io/src/lib.rs +++ b/substrate/runtime-io/src/lib.rs @@ -19,6 +19,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(lang_items))] #![cfg_attr(not(feature = "std"), feature(panic_implementation))] +#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] #![cfg_attr(not(feature = "std"), feature(core_intrinsics))] #![cfg_attr(not(feature = "std"), feature(alloc))] diff --git a/substrate/runtime-io/with_std.rs b/substrate/runtime-io/with_std.rs index 69a7a3665949f..3d3b2552082b3 100644 --- a/substrate/runtime-io/with_std.rs +++ b/substrate/runtime-io/with_std.rs @@ -68,6 +68,20 @@ pub fn clear_storage(key: &[u8]) { ); } +/// Check whether a given `key` exists in storage. +pub fn exists_storage(key: &[u8]) -> bool { + ext::with(|ext| + ext.exists_storage(key) + ).unwrap_or(false) +} + +/// Clear the storage entries key of which starts with the given prefix. +pub fn clear_prefix(prefix: &[u8]) { + ext::with(|ext| + ext.clear_prefix(prefix) + ); +} + /// The current relay chain identifier. pub fn chain_id() -> u64 { ext::with(|ext| @@ -161,13 +175,13 @@ macro_rules! impl_stubs { }; (@METHOD $data: ident $new_name: ident => $invoke:expr) => {{ let mut data = $data; - let input = match $crate::codec::Slicable::decode(&mut data) { + let input = match $crate::codec::Decode::decode(&mut data) { Some(input) => input, None => panic!("Bad input data provided to {}", stringify!($new_name)), }; let output = $invoke(input); - Some($crate::codec::Slicable::encode(&output)) + Some($crate::codec::Encode::encode(&output)) }} } @@ -211,4 +225,23 @@ mod std_tests { assert_eq!(&w, b"Hello world"); }); } + + #[test] + fn clear_prefix_works() { + let mut t: TestExternalities = map![ + b":a".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), + b":abcd".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), + b":abc".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), + b":abdd".to_vec() => b"\x0b\0\0\0Hello world".to_vec() + ]; + + with_externalities(&mut t, || { + clear_prefix(b":abc"); + + assert!(storage(b":a").is_some()); + assert!(storage(b":abdd").is_some()); + assert!(storage(b":abcd").is_none()); + assert!(storage(b":abc").is_none()); + }); + } } diff --git a/substrate/runtime-io/without_std.rs b/substrate/runtime-io/without_std.rs index 3f8e1f31072a2..438b1a84fc976 100644 --- a/substrate/runtime-io/without_std.rs +++ b/substrate/runtime-io/without_std.rs @@ -40,9 +40,9 @@ pub fn panic(info: &::core::panic::PanicInfo) -> ! { } } -#[lang = "oom"] -pub extern fn oom() -> ! { - static OOM_MSG: &str = "Runtime memory exhausted. Aborting"; +#[alloc_error_handler] +pub extern fn oom(_: ::core::alloc::Layout) -> ! { + static OOM_MSG: &str = "Runtime memory exhausted. Aborting"; unsafe { ext_print_utf8(OOM_MSG.as_ptr(), OOM_MSG.len() as u32); @@ -56,6 +56,8 @@ extern "C" { fn ext_print_num(value: u64); fn ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32); fn ext_clear_storage(key_data: *const u8, key_len: u32); + fn ext_exists_storage(key_data: *const u8, key_len: u32) -> u32; + fn ext_clear_prefix(prefix_data: *const u8, prefix_len: u32); fn ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8; fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32; fn ext_storage_root(result: *mut u8); @@ -80,7 +82,7 @@ pub fn storage(key: &[u8]) -> Option> { } } -/// Set the storage to some particular key. +/// Set the storage of some particular key to Some value. pub fn set_storage(key: &[u8], value: &[u8]) { unsafe { ext_set_storage( @@ -90,7 +92,7 @@ pub fn set_storage(key: &[u8], value: &[u8]) { } } -/// Set the storage to some particular key. +/// Clear the storage of some particular key. pub fn clear_storage(key: &[u8]) { unsafe { ext_clear_storage( @@ -99,6 +101,25 @@ pub fn clear_storage(key: &[u8]) { } } +/// Determine whether a particular key exists in storage. +pub fn exists_storage(key: &[u8]) -> bool { + unsafe { + ext_exists_storage( + key.as_ptr(), key.len() as u32 + ) != 0 + } +} + +/// Clear the storage entries key of which starts with the given prefix. +pub fn clear_prefix(prefix: &[u8]) { + unsafe { + ext_clear_prefix( + prefix.as_ptr(), + prefix.len() as u32 + ); + } +} + /// Get `key` from storage, placing the value into `value_out` (as much as possible) and return /// the number of bytes that the key in storage was beyond the offset. pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option { @@ -271,13 +292,13 @@ macro_rules! impl_stubs { } }; - let input = match $crate::codec::Slicable::decode(&mut input) { + let input = match $crate::codec::Decode::decode(&mut input) { Some(input) => input, None => panic!("Bad input data provided to {}", stringify!($name)), }; let output = ($invoke)(input); - let output = $crate::codec::Slicable::encode(&output); + let output = $crate::codec::Encode::encode(&output); let res = output.as_ptr() as u64 + ((output.len() as u64) << 32); // Leak the output vector to avoid it being freed. diff --git a/substrate/runtime-sandbox/Cargo.toml b/substrate/runtime-sandbox/Cargo.toml index c6d4a930907b7..b624b30f8f89b 100755 --- a/substrate/runtime-sandbox/Cargo.toml +++ b/substrate/runtime-sandbox/Cargo.toml @@ -8,14 +8,14 @@ build = "build.rs" rustc_version = "0.2" [dependencies] -wasmi = { version = "0.1", optional = true } +wasmi = { version = "0.3", optional = true } substrate-primitives = { path = "../primitives", default_features = false } substrate-runtime-std = { path = "../runtime-std", default_features = false } substrate-runtime-io = { path = "../runtime-io", default_features = false } substrate-codec = { path = "../codec", default_features = false } [dev-dependencies] -wabt = "0.1.7" +wabt = "0.4" [features] default = ["std"] diff --git a/substrate/runtime-sandbox/with_std.rs b/substrate/runtime-sandbox/with_std.rs index aee9fda813060..70ebc793e20e5 100755 --- a/substrate/runtime-sandbox/with_std.rs +++ b/substrate/runtime-sandbox/with_std.rs @@ -19,7 +19,6 @@ extern crate wasmi; use rstd::collections::btree_map::BTreeMap; use rstd::fmt; - use self::wasmi::{ Externals, FuncInstance, FuncRef, GlobalDescriptor, GlobalRef, ImportResolver, MemoryDescriptor, MemoryInstance, MemoryRef, Module, ModuleInstance, ModuleRef, @@ -104,11 +103,12 @@ fn from_runtime_value(v: RuntimeValue) -> TypedValue { } fn to_runtime_value(v: TypedValue) -> RuntimeValue { + use self::wasmi::nan_preserving_float::{F32, F64}; match v { TypedValue::I32(v) => RuntimeValue::I32(v as i32), TypedValue::I64(v) => RuntimeValue::I64(v as i64), - TypedValue::F32(v_bits) => RuntimeValue::F32(f32::from_bits(v_bits as u32)), - TypedValue::F64(v_bits) => RuntimeValue::F64(f64::from_bits(v_bits as u64)), + TypedValue::F32(v_bits) => RuntimeValue::F32(F32::from_bits(v_bits as u32)), + TypedValue::F64(v_bits) => RuntimeValue::F64(F64::from_bits(v_bits as u64)), } } diff --git a/substrate/runtime-sandbox/without_std.rs b/substrate/runtime-sandbox/without_std.rs index 860d24f43c34b..9efa282ebc290 100755 --- a/substrate/runtime-sandbox/without_std.rs +++ b/substrate/runtime-sandbox/without_std.rs @@ -16,7 +16,7 @@ use rstd::prelude::*; use rstd::{slice, marker, mem}; -use codec::Slicable; +use codec::{Decode, Encode}; use primitives::sandbox as sandbox_primitives; use super::{Error, TypedValue, ReturnValue, HostFuncType}; diff --git a/substrate/runtime-std/without_std.rs b/substrate/runtime-std/without_std.rs index 69553db1dd8c3..b7fbf03a35a32 100644 --- a/substrate/runtime-std/without_std.rs +++ b/substrate/runtime-std/without_std.rs @@ -41,5 +41,5 @@ pub use core::slice; pub use core::result; pub mod collections { - pub use alloc::btree_map; + pub use alloc::collections::btree_map; } diff --git a/substrate/runtime-support/src/dispatch.rs b/substrate/runtime-support/src/dispatch.rs index d9c33bdc4c704..3bda73344791b 100644 --- a/substrate/runtime-support/src/dispatch.rs +++ b/substrate/runtime-support/src/dispatch.rs @@ -22,7 +22,7 @@ pub use std::fmt; pub use rstd::result; #[cfg(feature = "std")] use serde; -pub use codec::{Slicable, Input}; +pub use codec::{Codec, Decode, Encode, Input, Output}; pub type Result = result::Result<(), &'static str>; @@ -39,11 +39,11 @@ pub trait AuxDispatchable { #[cfg(feature = "std")] pub trait AuxCallable { - type Call: AuxDispatchable + Slicable + ::serde::Serialize + Clone + PartialEq + Eq; + type Call: AuxDispatchable + Codec + ::serde::Serialize + Clone + PartialEq + Eq; } #[cfg(not(feature = "std"))] pub trait AuxCallable { - type Call: AuxDispatchable + Slicable + Clone + PartialEq + Eq; + type Call: AuxDispatchable + Codec + Clone + PartialEq + Eq; } // dirty hack to work around serde_derive issue @@ -52,11 +52,11 @@ pub type AuxCallableCallFor = ::Call; #[cfg(feature = "std")] pub trait Callable { - type Call: Dispatchable + Slicable + ::serde::Serialize + Clone + PartialEq + Eq; + type Call: Dispatchable + Codec + ::serde::Serialize + Clone + PartialEq + Eq; } #[cfg(not(feature = "std"))] pub trait Callable { - type Call: Dispatchable + Slicable + Clone + PartialEq + Eq; + type Call: Dispatchable + Codec + Clone + PartialEq + Eq; } // dirty hack to work around serde_derive issue. @@ -64,16 +64,16 @@ pub trait Callable { pub type CallableCallFor = ::Call; #[cfg(feature = "std")] -pub trait Parameter: Slicable + serde::Serialize + Clone + Eq + fmt::Debug {} +pub trait Parameter: Codec + serde::Serialize + Clone + Eq + fmt::Debug {} #[cfg(feature = "std")] -impl Parameter for T where T: Slicable + serde::Serialize + Clone + Eq + fmt::Debug {} +impl Parameter for T where T: Codec + serde::Serialize + Clone + Eq + fmt::Debug {} #[cfg(not(feature = "std"))] -pub trait Parameter: Slicable + Clone + Eq {} +pub trait Parameter: Codec + Clone + Eq {} #[cfg(not(feature = "std"))] -impl Parameter for T where T: Slicable + Clone + Eq {} +impl Parameter for T where T: Codec + Clone + Eq {} /// Declare a struct for this module, then implement dispatch logic to create a pairing of several /// dispatch traits and enums. @@ -395,13 +395,13 @@ macro_rules! __decl_dispatch_module_common { } } - impl<$trait_instance: $trait_name> $crate::dispatch::Slicable for $call_type<$trait_instance> { + impl<$trait_instance: $trait_name> $crate::dispatch::Decode for $call_type<$trait_instance> { fn decode(input: &mut I) -> Option { match input.read_byte()? { $( $id => { $( - let $param_name = $crate::dispatch::Slicable::decode(input)?; + let $param_name = $crate::dispatch::Decode::decode(input)?; )* Some($call_type:: $fn_name( $( $param_name ),* )) } @@ -409,9 +409,10 @@ macro_rules! __decl_dispatch_module_common { _ => None, } } + } - fn encode(&self) -> $crate::dispatch::Vec { - let mut v = $crate::dispatch::Vec::new(); + impl<$trait_instance: $trait_name> $crate::dispatch::Encode for $call_type<$trait_instance> { + fn encode_to(&self, dest: &mut W) { match *self { $( $call_type::$fn_name( @@ -419,19 +420,14 @@ macro_rules! __decl_dispatch_module_common { ref $param_name ),* ) => { - v.push($id as u8); + dest.push_byte($id as u8); $( - $param_name.using_encoded(|s| v.extend(s)); + $param_name.encode_to(dest); )* } )* $call_type::__PhantomItem(_) => unreachable!(), } - v - } - - fn using_encoded R>(&self, f: F) -> R { - f(self.encode().as_slice()) } } @@ -536,32 +532,28 @@ macro_rules! impl_outer_dispatch_common { ( $call_type:ident, $( $camelcase:ident = $id:expr, )* ) => { - impl $crate::dispatch::Slicable for $call_type { + impl $crate::dispatch::Decode for $call_type { fn decode(input: &mut I) -> Option { match input.read_byte()? { $( $id => - Some($call_type::$camelcase( $crate::dispatch::Slicable::decode(input)? )), + Some($call_type::$camelcase( $crate::dispatch::Decode::decode(input)? )), )* _ => None, } } + } - fn encode(&self) -> $crate::dispatch::Vec { - let mut v = $crate::dispatch::Vec::new(); + impl $crate::dispatch::Encode for $call_type { + fn encode_to(&self, dest: &mut W) { match *self { $( $call_type::$camelcase( ref sub ) => { - v.push($id as u8); - sub.using_encoded(|s| v.extend(s)); + dest.push_byte($id as u8); + sub.encode_to(dest); } )* } - v - } - - fn using_encoded R>(&self, f: F) -> R { - f(self.encode().as_slice()) } } diff --git a/substrate/runtime-support/src/hashable.rs b/substrate/runtime-support/src/hashable.rs index 79a5c352b3b54..386f44c686d96 100644 --- a/substrate/runtime-support/src/hashable.rs +++ b/substrate/runtime-support/src/hashable.rs @@ -16,7 +16,7 @@ //! Hashable trait. -use codec::Slicable; +use codec::Codec; use runtime_io::{blake2_256, twox_128, twox_256}; pub trait Hashable: Sized { @@ -25,7 +25,7 @@ pub trait Hashable: Sized { fn twox_256(&self) -> [u8; 32]; } -impl Hashable for T { +impl Hashable for T { fn blake2_256(&self) -> [u8; 32] { blake2_256(&self.encode()) } diff --git a/substrate/runtime-support/src/storage/generator.rs b/substrate/runtime-support/src/storage/generator.rs index d91e860f9ee51..ed15dc845cf96 100644 --- a/substrate/runtime-support/src/storage/generator.rs +++ b/substrate/runtime-support/src/storage/generator.rs @@ -59,38 +59,38 @@ pub trait Storage { fn exists(&self, key: &[u8]) -> bool; /// Load the bytes of a key from storage. Can panic if the type is incorrect. - fn get(&self, key: &[u8]) -> Option; + fn get(&self, key: &[u8]) -> Option; /// Load the bytes of a key from storage. Can panic if the type is incorrect. Will panic if /// it's not there. - fn require(&self, key: &[u8]) -> T { self.get(key).expect("Required values must be in storage") } + fn require(&self, key: &[u8]) -> T { self.get(key).expect("Required values must be in storage") } /// Load the bytes of a key from storage. Can panic if the type is incorrect. The type's /// default is returned if it's not there. - fn get_or_default(&self, key: &[u8]) -> T { self.get(key).unwrap_or_default() } + fn get_or_default(&self, key: &[u8]) -> T { self.get(key).unwrap_or_default() } /// Put a value in under a key. - fn put(&self, key: &[u8], val: &T); + fn put(&self, key: &[u8], val: &T); /// Remove the bytes of a key from storage. fn kill(&self, key: &[u8]); /// Take a value from storage, deleting it after reading. - fn take(&self, key: &[u8]) -> Option { + fn take(&self, key: &[u8]) -> Option { let value = self.get(key); self.kill(key); value } /// Take a value from storage, deleting it after reading. - fn take_or_panic(&self, key: &[u8]) -> T { self.take(key).expect("Required values must be in storage") } + fn take_or_panic(&self, key: &[u8]) -> T { self.take(key).expect("Required values must be in storage") } /// Take a value from storage, deleting it after reading. - fn take_or_default(&self, key: &[u8]) -> T { self.take(key).unwrap_or_default() } + fn take_or_default(&self, key: &[u8]) -> T { self.take(key).unwrap_or_default() } } /// A strongly-typed value kept in storage. -pub trait StorageValue { +pub trait StorageValue { /// The type that get/take returns. type Query; @@ -120,7 +120,7 @@ pub trait StorageValue { } /// A strongly-typed list in storage. -pub trait StorageList { +pub trait StorageList { /// Get the prefix key in storage. fn prefix() -> &'static [u8]; @@ -150,7 +150,7 @@ pub trait StorageList { } /// A strongly-typed map in storage. -pub trait StorageMap { +pub trait StorageMap { /// The type that get/take returns. type Query; @@ -233,7 +233,7 @@ macro_rules! __storage_items_internal { /// Get the storage key used to fetch a value corresponding to a specific key. fn key_for(x: &$kty) -> Vec { let mut key = $prefix.to_vec(); - key.extend($crate::codec::Slicable::encode(x)); + $crate::codec::Encode::encode_to(x, &mut key); key } @@ -284,7 +284,7 @@ macro_rules! __storage_items_internal { /// Get the storage key used to fetch a value at a given index. fn key_for(index: u32) -> Vec { let mut key = $prefix.to_vec(); - key.extend($crate::codec::Slicable::encode(&index)); + $crate::codec::Encode::encode_to(&index, &mut key); key } @@ -496,7 +496,7 @@ macro_rules! __decl_storage_item { /// Get the storage key used to fetch a value corresponding to a specific key. fn key_for(x: &$kty) -> Vec { let mut key = $prefix.to_vec(); - key.extend($crate::codec::Slicable::encode(x)); + $crate::codec::Encode::encode_to(x, &mut key); key } @@ -991,7 +991,7 @@ macro_rules! __decl_storage_items { mod tests { use std::collections::HashMap; use std::cell::RefCell; - use codec::Slicable; + use codec::Codec; use super::*; impl Storage for RefCell, Vec>> { @@ -999,11 +999,11 @@ mod tests { self.borrow_mut().get(key).is_some() } - fn get(&self, key: &[u8]) -> Option { + fn get(&self, key: &[u8]) -> Option { self.borrow_mut().get(key).map(|v| T::decode(&mut &v[..]).unwrap()) } - fn put(&self, key: &[u8], val: &T) { + fn put(&self, key: &[u8], val: &T) { self.borrow_mut().insert(key.to_owned(), val.encode()); } diff --git a/substrate/runtime-support/src/storage/mod.rs b/substrate/runtime-support/src/storage/mod.rs index 635a30848f5a2..3009b5f36bf1c 100644 --- a/substrate/runtime-support/src/storage/mod.rs +++ b/substrate/runtime-support/src/storage/mod.rs @@ -19,7 +19,7 @@ use rstd::prelude::*; use rstd::borrow::Borrow; use runtime_io::{self, twox_128}; -use codec::{Slicable, KeyedVec, Input}; +use codec::{Codec, Decode, KeyedVec, Input}; pub mod generator; @@ -39,43 +39,59 @@ impl<'a> Input for IncrementalInput<'a> { } } +// TODO: only introduce this wrapper for types where it makes sense, ideally have it within the module declaration. + +struct AppendZeroes<'a, I: Input + 'a> { + input: &'a mut I, +} + +impl<'a, I: Input + 'a> Input for AppendZeroes<'a, I> { + fn read(&mut self, into: &mut [u8]) -> usize { + let r = self.input.read(into); + for z in &mut into[r..] { + *z = 0; + }; + into.len() + } +} + /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. -pub fn get(key: &[u8]) -> Option { +pub fn get(key: &[u8]) -> Option { let key = twox_128(key); runtime_io::read_storage(&key[..], &mut [0; 0][..], 0).map(|_| { let mut input = IncrementalInput { key: &key[..], pos: 0, }; - Slicable::decode(&mut input).expect("storage is not null, therefore must be a valid type") + Decode::decode(&mut AppendZeroes { input: &mut input } ).expect("storage is not null, therefore must be a valid type") }) } /// Return the value of the item in storage under `key`, or the type's default if there is no /// explicit entry. -pub fn get_or_default(key: &[u8]) -> T { +pub fn get_or_default(key: &[u8]) -> T { get(key).unwrap_or_else(Default::default) } /// Return the value of the item in storage under `key`, or `default_value` if there is no /// explicit entry. -pub fn get_or(key: &[u8], default_value: T) -> T { +pub fn get_or(key: &[u8], default_value: T) -> T { get(key).unwrap_or(default_value) } /// Return the value of the item in storage under `key`, or `default_value()` if there is no /// explicit entry. -pub fn get_or_else T>(key: &[u8], default_value: F) -> T { +pub fn get_or_else T>(key: &[u8], default_value: F) -> T { get(key).unwrap_or_else(default_value) } /// Put `value` in storage under `key`. -pub fn put(key: &[u8], value: &T) { +pub fn put(key: &[u8], value: &T) { value.using_encoded(|slice| runtime_io::set_storage(&twox_128(key)[..], slice)); } /// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise. -pub fn take(key: &[u8]) -> Option { +pub fn take(key: &[u8]) -> Option { let r = get(key); if r.is_some() { kill(key); @@ -85,26 +101,25 @@ pub fn take(key: &[u8]) -> Option { /// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage, /// the default for its type. -pub fn take_or_default(key: &[u8]) -> T { +pub fn take_or_default(key: &[u8]) -> T { take(key).unwrap_or_else(Default::default) } /// Return the value of the item in storage under `key`, or `default_value` if there is no /// explicit entry. Ensure there is no explicit entry on return. -pub fn take_or(key: &[u8], default_value: T) -> T { +pub fn take_or(key: &[u8], default_value: T) -> T { take(key).unwrap_or(default_value) } /// Return the value of the item in storage under `key`, or `default_value()` if there is no /// explicit entry. Ensure there is no explicit entry on return. -pub fn take_or_else T>(key: &[u8], default_value: F) -> T { +pub fn take_or_else T>(key: &[u8], default_value: F) -> T { take(key).unwrap_or_else(default_value) } /// Check to see if `key` has an explicit entry in storage. pub fn exists(key: &[u8]) -> bool { - let mut x = [0u8; 0]; - runtime_io::read_storage(&twox_128(key)[..], &mut x[..], 0).is_some() + runtime_io::exists_storage(&twox_128(key)[..]) } /// Ensure `key` has no explicit entry in storage. @@ -131,12 +146,12 @@ impl ::GenericStorage for RuntimeStorage { } /// Load the bytes of a key from storage. Can panic if the type is incorrect. - fn get(&self, key: &[u8]) -> Option { + fn get(&self, key: &[u8]) -> Option { super::storage::get(key) } /// Put a value in under a key. - fn put(&self, key: &[u8], val: &T) { + fn put(&self, key: &[u8], val: &T) { super::storage::put(key, val) } @@ -146,13 +161,13 @@ impl ::GenericStorage for RuntimeStorage { } /// Take a value from storage, deleting it after reading. - fn take(&self, key: &[u8]) -> Option { + fn take(&self, key: &[u8]) -> Option { super::storage::take(key) } } /// A trait for working with macro-generated storage values under the substrate storage API. -pub trait StorageValue { +pub trait StorageValue { /// The type that get/take return. type Query; @@ -175,7 +190,7 @@ pub trait StorageValue { fn take() -> Self::Query; } -impl StorageValue for U where U: generator::StorageValue { +impl StorageValue for U where U: generator::StorageValue { type Query = U::Query; fn key() -> &'static [u8] { @@ -199,7 +214,7 @@ impl StorageValue for U where U: generator::StorageValue { } /// A strongly-typed list in storage. -pub trait StorageList { +pub trait StorageList { /// Get the prefix key in storage. fn prefix() -> &'static [u8]; @@ -228,7 +243,7 @@ pub trait StorageList { fn clear(); } -impl StorageList for U where U: generator::StorageList { +impl StorageList for U where U: generator::StorageList { fn prefix() -> &'static [u8] { >::prefix() } @@ -267,7 +282,7 @@ impl StorageList for U where U: generator::StorageList { } /// A strongly-typed map in storage. -pub trait StorageMap { +pub trait StorageMap { /// The type that get/take return. type Query; @@ -293,7 +308,7 @@ pub trait StorageMap { fn take>(key: KeyArg) -> Self::Query; } -impl StorageMap for U where U: generator::StorageMap { +impl StorageMap for U where U: generator::StorageMap { type Query = U::Query; fn prefix() -> &'static [u8] { @@ -327,7 +342,7 @@ impl StorageMap for U where U: generator::Sto /// A trait to conveniently store a vector of storable data. pub trait StorageVec { - type Item: Default + Sized + Slicable; + type Item: Default + Sized + Codec; const PREFIX: &'static [u8]; /// Get the current set of items. @@ -386,44 +401,44 @@ pub trait StorageVec { pub mod unhashed { use rstd::borrow::Borrow; - use super::{runtime_io, Slicable, KeyedVec, Vec, IncrementalInput}; + use super::{runtime_io, Codec, Decode, KeyedVec, Vec, IncrementalInput}; /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. - pub fn get(key: &[u8]) -> Option { + pub fn get(key: &[u8]) -> Option { runtime_io::read_storage(key, &mut [0; 0][..], 0).map(|_| { let mut input = IncrementalInput { key, pos: 0, }; - Slicable::decode(&mut input).expect("stroage is not null, therefore must be a valid type") + Decode::decode(&mut input).expect("storage is not null, therefore must be a valid type") }) } /// Return the value of the item in storage under `key`, or the type's default if there is no /// explicit entry. - pub fn get_or_default(key: &[u8]) -> T { + pub fn get_or_default(key: &[u8]) -> T { get(key).unwrap_or_else(Default::default) } /// Return the value of the item in storage under `key`, or `default_value` if there is no /// explicit entry. - pub fn get_or(key: &[u8], default_value: T) -> T { + pub fn get_or(key: &[u8], default_value: T) -> T { get(key).unwrap_or(default_value) } /// Return the value of the item in storage under `key`, or `default_value()` if there is no /// explicit entry. - pub fn get_or_else T>(key: &[u8], default_value: F) -> T { + pub fn get_or_else T>(key: &[u8], default_value: F) -> T { get(key).unwrap_or_else(default_value) } /// Put `value` in storage under `key`. - pub fn put(key: &[u8], value: &T) { + pub fn put(key: &[u8], value: &T) { value.using_encoded(|slice| runtime_io::set_storage(key, slice)); } /// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise. - pub fn take(key: &[u8]) -> Option { + pub fn take(key: &[u8]) -> Option { let r = get(key); if r.is_some() { kill(key); @@ -433,19 +448,19 @@ pub mod unhashed { /// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage, /// the default for its type. - pub fn take_or_default(key: &[u8]) -> T { + pub fn take_or_default(key: &[u8]) -> T { take(key).unwrap_or_else(Default::default) } /// Return the value of the item in storage under `key`, or `default_value` if there is no /// explicit entry. Ensure there is no explicit entry on return. - pub fn take_or(key: &[u8], default_value: T) -> T { + pub fn take_or(key: &[u8], default_value: T) -> T { take(key).unwrap_or(default_value) } /// Return the value of the item in storage under `key`, or `default_value()` if there is no /// explicit entry. Ensure there is no explicit entry on return. - pub fn take_or_else T>(key: &[u8], default_value: F) -> T { + pub fn take_or_else T>(key: &[u8], default_value: F) -> T { take(key).unwrap_or_else(default_value) } @@ -459,6 +474,11 @@ pub mod unhashed { runtime_io::clear_storage(key); } + /// Ensure keys with the given `prefix` have no entries in storage. + pub fn kill_prefix(prefix: &[u8]) { + runtime_io::clear_prefix(prefix); + } + /// Get a Vec of bytes from storage. pub fn get_raw(key: &[u8]) -> Option> { runtime_io::storage(key) @@ -471,7 +491,7 @@ pub mod unhashed { /// A trait to conveniently store a vector of storable data. pub trait StorageVec { - type Item: Default + Sized + Slicable; + type Item: Default + Sized + Codec; const PREFIX: &'static [u8]; /// Get the current set of items. diff --git a/substrate/runtime/consensus/src/lib.rs b/substrate/runtime/consensus/src/lib.rs index d4a84e32ede9c..13d40afe5eab1 100644 --- a/substrate/runtime/consensus/src/lib.rs +++ b/substrate/runtime/consensus/src/lib.rs @@ -42,14 +42,14 @@ use rstd::prelude::*; use runtime_support::{storage, Parameter}; use runtime_support::dispatch::Result; use runtime_support::storage::unhashed::StorageVec; -use primitives::traits::RefInto; +use primitives::traits::{RefInto, MaybeSerializeDebug, MaybeEmpty}; use primitives::bft::MisbehaviorReport; pub const AUTHORITY_AT: &'static [u8] = b":auth:"; pub const AUTHORITY_COUNT: &'static [u8] = b":auth:len"; -struct AuthorityStorageVec(rstd::marker::PhantomData); -impl StorageVec for AuthorityStorageVec { +struct AuthorityStorageVec(rstd::marker::PhantomData); +impl StorageVec for AuthorityStorageVec { type Item = S; const PREFIX: &'static [u8] = AUTHORITY_AT; } @@ -59,8 +59,8 @@ pub const CODE: &'static [u8] = b":code"; pub type KeyValue = (Vec, Vec); pub trait Trait: system::Trait { - type PublicAux: RefInto; - type SessionKey: Parameter + Default; + type PublicAux: RefInto + MaybeEmpty; // MaybeEmpty is for Timestamp's usage. + type SessionKey: Parameter + Default + MaybeSerializeDebug; } decl_module! { @@ -69,6 +69,7 @@ decl_module! { #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum Call where aux: T::PublicAux { fn report_misbehavior(aux, report: MisbehaviorReport) -> Result = 0; + fn remark(aux, remark: Vec) -> Result = 1; } #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -104,6 +105,11 @@ impl Module { Ok(()) } + /// Make some on-chain remark. + fn remark(_aux: &T::PublicAux, _remark: Vec) -> Result { + Ok(()) + } + /// Set the current set of authorities' session keys. /// /// Called by `next_session` only. @@ -118,8 +124,12 @@ impl Module { } #[cfg(any(feature = "std", test))] +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] pub struct GenesisConfig { pub authorities: Vec, + #[serde(with = "substrate_primitives::bytes")] pub code: Vec, } @@ -136,14 +146,14 @@ impl Default for GenesisConfig { #[cfg(any(feature = "std", test))] impl primitives::BuildStorage for GenesisConfig { - fn build_storage(self) -> runtime_io::TestExternalities { - use codec::{Slicable, KeyedVec}; + fn build_storage(self) -> ::std::result::Result { + use codec::{Encode, KeyedVec}; let auth_count = self.authorities.len() as u32; let mut r: runtime_io::TestExternalities = self.authorities.into_iter().enumerate().map(|(i, v)| ((i as u32).to_keyed_vec(AUTHORITY_AT), v.encode()) ).collect(); r.insert(AUTHORITY_COUNT.to_vec(), auth_count.encode()); r.insert(CODE.to_vec(), self.code); - r + Ok(r) } } diff --git a/substrate/runtime/contract/Cargo.toml b/substrate/runtime/contract/Cargo.toml index 30c3564063b02..23291d4d67e48 100644 --- a/substrate/runtime/contract/Cargo.toml +++ b/substrate/runtime/contract/Cargo.toml @@ -4,22 +4,42 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] +serde = { version = "1.0", default_features = false } +serde_derive = { version = "1.0", optional = true } substrate-codec = { path = "../../codec", default_features = false } +substrate-runtime-consensus = { path = "../../runtime/consensus", default_features = false } +substrate-runtime-primitives = { path = "../../runtime/primitives" } +substrate-runtime-io = { path = "../../runtime-io", default_features = false } substrate-runtime-std = { path = "../../runtime-std", default_features = false } substrate-runtime-sandbox = { path = "../../runtime-sandbox", default_features = false } -parity-wasm = { version = "0.30", default_features = false } -pwasm-utils = { version = "0.2", default_features = false } +substrate-runtime-staking = { path = "../../runtime/staking", default_features = false } +substrate-runtime-support = { path = "../../runtime-support", default_features = false } +substrate-runtime-system = { path = "../../runtime/system", default_features = false } +substrate-runtime-session = { path = "../session", default_features = false } +substrate-runtime-timestamp = { path = "../timestamp", default_features = false } +parity-wasm = { version = "0.31", default_features = false } +pwasm-utils = { version = "0.3", default_features = false } [dev-dependencies] -wabt = "0.1.7" +wabt = "0.4" assert_matches = "1.1" [features] default = ["std"] std = [ + "serde_derive", + "serde/std", "substrate-codec/std", + "substrate-runtime-primitives/std", + "substrate-runtime-consensus/std", + "substrate-runtime-io/std", "substrate-runtime-std/std", "substrate-runtime-sandbox/std", + "substrate-runtime-staking/std", + "substrate-runtime-support/std", + "substrate-runtime-system/std", + "substrate-runtime-timestamp/std", + "substrate-runtime-session/std", "parity-wasm/std", "pwasm-utils/std", ] diff --git a/substrate/runtime/contract/src/account_db.rs b/substrate/runtime/contract/src/account_db.rs new file mode 100644 index 0000000000000..efa5c150c1ddd --- /dev/null +++ b/substrate/runtime/contract/src/account_db.rs @@ -0,0 +1,181 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +//! Auxilliaries to help with managing partial changes to accounts state. + +use super::{CodeOf, StorageOf, Trait}; +use double_map::StorageDoubleMap; +use rstd::cell::RefCell; +use rstd::collections::btree_map::{BTreeMap, Entry}; +use rstd::prelude::*; +use runtime_support::StorageMap; +use staking; +use system; + +pub struct ChangeEntry { + balance: Option, + code: Option>, + storage: BTreeMap, Option>>, +} + +// Cannot derive(Default) since it erroneously bounds T by Default. +impl Default for ChangeEntry { + fn default() -> Self { + ChangeEntry { + balance: Default::default(), + code: Default::default(), + storage: Default::default(), + } + } +} + +pub type ChangeSet = BTreeMap<::AccountId, ChangeEntry>; + +pub trait AccountDb { + fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option>; + fn get_code(&self, account: &T::AccountId) -> Vec; + fn get_balance(&self, account: &T::AccountId) -> T::Balance; + + fn commit(&mut self, change_set: ChangeSet); +} + +pub struct DirectAccountDb; +impl AccountDb for DirectAccountDb { + fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option> { + >::get(account.clone(), location.to_vec()) + } + fn get_code(&self, account: &T::AccountId) -> Vec { + >::get(account) + } + fn get_balance(&self, account: &T::AccountId) -> T::Balance { + staking::Module::::free_balance(account) + } + fn commit(&mut self, s: ChangeSet) { + for (address, changed) in s.into_iter() { + if let Some(balance) = changed.balance { + if let staking::UpdateBalanceOutcome::AccountKilled = + staking::Module::::set_free_balance_creating(&address, balance) + { + // Account killed. This will ultimately lead to calling `OnAccountKill` callback + // which will make removal of CodeOf and StorageOf for this account. + // In order to avoid writing over the deleted properties we `continue` here. + continue; + } + } + if let Some(code) = changed.code { + >::insert(&address, &code); + } + for (k, v) in changed.storage.into_iter() { + if let Some(value) = v { + >::insert(address.clone(), k, value); + } else { + >::remove(address.clone(), k); + } + } + } + } +} + +pub struct OverlayAccountDb<'a, T: Trait + 'a> { + local: RefCell>, + underlying: &'a AccountDb, +} +impl<'a, T: Trait> OverlayAccountDb<'a, T> { + pub fn new(underlying: &'a AccountDb) -> OverlayAccountDb<'a, T> { + OverlayAccountDb { + local: RefCell::new(ChangeSet::new()), + underlying, + } + } + + pub fn into_change_set(self) -> ChangeSet { + self.local.into_inner() + } + + pub fn set_storage( + &mut self, + account: &T::AccountId, + location: Vec, + value: Option>, + ) { + self.local + .borrow_mut() + .entry(account.clone()) + .or_insert(Default::default()) + .storage + .insert(location, value); + } + pub fn set_code(&mut self, account: &T::AccountId, code: Vec) { + self.local + .borrow_mut() + .entry(account.clone()) + .or_insert(Default::default()) + .code = Some(code); + } + pub fn set_balance(&mut self, account: &T::AccountId, balance: T::Balance) { + self.local + .borrow_mut() + .entry(account.clone()) + .or_insert(Default::default()) + .balance = Some(balance); + } +} + +impl<'a, T: Trait> AccountDb for OverlayAccountDb<'a, T> { + fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option> { + self.local + .borrow() + .get(account) + .and_then(|a| a.storage.get(location)) + .cloned() + .unwrap_or_else(|| self.underlying.get_storage(account, location)) + } + fn get_code(&self, account: &T::AccountId) -> Vec { + self.local + .borrow() + .get(account) + .and_then(|a| a.code.clone()) + .unwrap_or_else(|| self.underlying.get_code(account)) + } + fn get_balance(&self, account: &T::AccountId) -> T::Balance { + self.local + .borrow() + .get(account) + .and_then(|a| a.balance) + .unwrap_or_else(|| self.underlying.get_balance(account)) + } + fn commit(&mut self, s: ChangeSet) { + let mut local = self.local.borrow_mut(); + + for (address, changed) in s.into_iter() { + match local.entry(address) { + Entry::Occupied(e) => { + let mut value = e.into_mut(); + if changed.balance.is_some() { + value.balance = changed.balance; + } + if changed.code.is_some() { + value.code = changed.code; + } + value.storage.extend(changed.storage.into_iter()); + } + Entry::Vacant(e) => { + e.insert(changed); + } + } + } + } +} diff --git a/substrate/runtime/contract/src/double_map.rs b/substrate/runtime/contract/src/double_map.rs new file mode 100644 index 0000000000000..7c4db02f35f3b --- /dev/null +++ b/substrate/runtime/contract/src/double_map.rs @@ -0,0 +1,90 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo 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. + +// Substrate Demo 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 Substrate Demo. If not, see . + +//! An implementation of double map backed by storage. +//! +//! This implementation is somewhat specialized to the tracking of the storage of accounts. + +use rstd::prelude::*; +use codec::{Codec, Encode}; +use runtime_support::storage::unhashed; +use runtime_io::{blake2_256, twox_128}; + +/// Returns only a first part of the storage key. +/// +/// Hashed by XX. +fn first_part_of_key(k1: M::Key1) -> [u8; 16] { + let mut raw_prefix = Vec::new(); + raw_prefix.extend(M::PREFIX); + raw_prefix.extend(Encode::encode(&k1)); + twox_128(&raw_prefix) +} + +/// Returns a compound key that consist of the two parts: (prefix, `k1`) and `k2`. +/// +/// The first part is hased by XX and then concatenated with a blake2 hash of `k2`. +fn full_key(k1: M::Key1, k2: M::Key2) -> Vec { + let first_part = first_part_of_key::(k1); + let second_part = blake2_256(&Encode::encode(&k2)); + + let mut k = Vec::new(); + k.extend(&first_part); + k.extend(&second_part); + k +} + +/// An implementation of a map with a two keys. +/// +/// It provides an important ability to efficiently remove all entries +/// that have a common first key. +/// +/// # Mapping of keys to a storage path +/// +/// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts. +/// The first part is a XX hash of a concatenation of the `PREFIX` and `Key1`. And the second part +/// is a blake2 hash of a `Key2`. +/// +/// Blake2 is used for `Key2` is because it will be used as a for a key for contract's storage and +/// thus will be susceptible for a untrusted input. +pub trait StorageDoubleMap { + type Key1: Codec; + type Key2: Codec; + type Value: Codec + Default; + + const PREFIX: &'static [u8]; + + /// Insert an entry into this map. + fn insert(k1: Self::Key1, k2: Self::Key2, val: Self::Value) { + unhashed::put(&full_key::(k1, k2)[..], &val); + } + + /// Remove an entry from this map. + fn remove(k1: Self::Key1, k2: Self::Key2) { + unhashed::kill(&full_key::(k1, k2)[..]); + } + + /// Get an entry from this map. + /// + /// If there is entry stored under the given keys, returns `None`. + fn get(k1: Self::Key1, k2: Self::Key2) -> Option { + unhashed::get(&full_key::(k1, k2)[..]) + } + + /// Removes all entries that shares the `k1` as the first key. + fn remove_prefix(k1: Self::Key1) { + unhashed::kill_prefix(&first_part_of_key::(k1)) + } +} diff --git a/substrate/runtime/contract/src/exec.rs b/substrate/runtime/contract/src/exec.rs new file mode 100644 index 0000000000000..403fe050e6e13 --- /dev/null +++ b/substrate/runtime/contract/src/exec.rs @@ -0,0 +1,259 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +use super::{CodeOf, ContractAddressFor, Module, Trait}; +use account_db::{AccountDb, OverlayAccountDb}; +use gas::GasMeter; +use vm; + +use rstd::prelude::*; +use runtime_primitives::traits::{Zero, CheckedAdd, CheckedSub}; +use runtime_support::StorageMap; +use staking; +use system; + +pub struct CreateReceipt { + pub address: T::AccountId, +} + +pub struct CallReceipt { + pub return_data: Vec, +} + +pub struct ExecutionContext<'a, T: Trait + 'a> { + // typically should be dest + pub self_account: T::AccountId, + pub overlay: OverlayAccountDb<'a, T>, + pub depth: usize, +} + +impl<'a, T: Trait> ExecutionContext<'a, T> { + /// Make a call to the specified address. + pub fn call( + &mut self, + caller: T::AccountId, + dest: T::AccountId, + value: T::Balance, + gas_meter: &mut GasMeter, + _data: &[u8], + ) -> Result { + let dest_code = >::get(&dest); + + // TODO: check the new depth + + let call_base_fee = >::call_base_fee(); + if gas_meter.charge(call_base_fee).is_out_of_gas() { + return Err("not enough gas to pay base call fee"); + } + + let (exec_result, change_set) = { + let mut overlay = OverlayAccountDb::new(&self.overlay); + + if value > T::Balance::zero() { + transfer( + gas_meter, + false, + &self.self_account, + &dest, + value, + &mut overlay, + )?; + } + + let mut nested = ExecutionContext { + overlay: overlay, + self_account: dest.clone(), + depth: self.depth + 1, + }; + let exec_result = if !dest_code.is_empty() { + vm::execute( + &dest_code, + &mut CallContext { + ctx: &mut nested, + _caller: caller, + }, + gas_meter, + ).map_err(|_| "vm execute returned error while call")? + } else { + // that was a plain transfer + vm::ExecutionResult { + return_data: Vec::new(), + } + }; + + (exec_result, nested.overlay.into_change_set()) + }; + + self.overlay.commit(change_set); + + Ok(CallReceipt { + return_data: exec_result.return_data, + }) + } + + pub fn create( + &mut self, + caller: T::AccountId, + endowment: T::Balance, + gas_meter: &mut GasMeter, + ctor: &[u8], + _data: &[u8], + ) -> Result, &'static str> { + let create_base_fee = >::create_base_fee(); + if gas_meter.charge(create_base_fee).is_out_of_gas() { + return Err("not enough gas to pay base create fee"); + } + + let dest = T::DetermineContractAddress::contract_address_for(ctor, &self.self_account); + if >::exists(&dest) { + // TODO: Is it enough? + return Err("contract already exists"); + } + + let change_set = { + let mut overlay = OverlayAccountDb::new(&self.overlay); + + if endowment > T::Balance::zero() { + transfer( + gas_meter, + true, + &self.self_account, + &dest, + endowment, + &mut overlay, + )?; + } + + let mut nested = ExecutionContext { + overlay: overlay, + self_account: dest.clone(), + depth: self.depth + 1, + }; + let exec_result = { + vm::execute( + ctor, + &mut CallContext { + ctx: &mut nested, + _caller: caller, + }, + gas_meter, + ).map_err(|_| "vm execute returned error while create")? + }; + + nested.overlay.set_code(&dest, exec_result.return_data); + nested.overlay.into_change_set() + }; + + self.overlay.commit(change_set); + + Ok(CreateReceipt { + address: dest, + }) + } +} + +fn transfer( + gas_meter: &mut GasMeter, + contract_create: bool, + transactor: &T::AccountId, + dest: &T::AccountId, + value: T::Balance, + overlay: &mut OverlayAccountDb, +) -> Result<(), &'static str> { + let would_create = overlay.get_balance(transactor).is_zero(); + + let fee: T::Balance = if contract_create { + >::contract_fee() + } else { + if would_create { + >::creation_fee() + } else { + >::transfer_fee() + } + }; + + if gas_meter.charge_by_balance(fee).is_out_of_gas() { + return Err("not enough gas to pay transfer fee"); + } + + let from_balance = overlay.get_balance(transactor); + let new_from_balance = match from_balance.checked_sub(&value) { + Some(b) => b, + None => return Err("balance too low to send value"), + }; + if would_create && value < >::existential_deposit() { + return Err("value too low to create account"); + } + if >::bondage(transactor) > >::block_number() { + return Err("bondage too high to send value"); + } + + let to_balance = overlay.get_balance(dest); + let new_to_balance = match to_balance.checked_add(&value) { + Some(b) => b, + None => return Err("destination balance too high to receive value"), + }; + + if transactor != dest { + overlay.set_balance(transactor, new_from_balance); + overlay.set_balance(dest, new_to_balance); + } + + Ok(()) +} + +struct CallContext<'a, 'b: 'a, T: Trait + 'b> { + ctx: &'a mut ExecutionContext<'b, T>, + _caller: T::AccountId, +} + +impl<'a, 'b: 'a, T: Trait + 'b> vm::Ext for CallContext<'a, 'b, T> { + fn get_storage(&self, key: &[u8]) -> Option> { + self.ctx.overlay.get_storage(&self.ctx.self_account, key) + } + + fn set_storage(&mut self, key: &[u8], value: Option>) { + self.ctx + .overlay + .set_storage(&self.ctx.self_account, key.to_vec(), value) + } + + fn create( + &mut self, + code: &[u8], + endowment: T::Balance, + gas_meter: &mut GasMeter, + data: &[u8], + ) -> Result, ()> { + let caller = self.ctx.self_account.clone(); + self.ctx + .create(caller, endowment, gas_meter, code, &data) + .map_err(|_| ()) + } + + fn call( + &mut self, + to: &T::AccountId, + value: T::Balance, + gas_meter: &mut GasMeter, + data: &[u8], + ) -> Result { + let caller = self.ctx.self_account.clone(); + self.ctx + .call(caller, to.clone(), value, gas_meter, data) + .map_err(|_| ()) + } +} diff --git a/substrate/runtime/contract/src/gas.rs b/substrate/runtime/contract/src/gas.rs new file mode 100644 index 0000000000000..662ddc4fbd3ad --- /dev/null +++ b/substrate/runtime/contract/src/gas.rs @@ -0,0 +1,150 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +use {Trait, Module}; +use runtime_primitives::traits::{As, CheckedMul, CheckedSub, Zero}; +use staking; + +#[must_use] +#[derive(Debug, PartialEq, Eq)] +pub enum GasMeterResult { + Proceed, + OutOfGas, +} + +impl GasMeterResult { + pub fn is_out_of_gas(&self) -> bool { + match *self { + GasMeterResult::OutOfGas => true, + GasMeterResult::Proceed => false, + } + } +} + +pub struct GasMeter { + gas_left: T::Gas, + gas_price: T::Balance, +} +impl GasMeter { + #[cfg(test)] + pub fn with_limit(gas_limit: T::Gas, gas_price: T::Balance) -> GasMeter { + GasMeter { + gas_left: gas_limit, + gas_price, + } + } + + /// Account for used gas. + /// + /// Returns `OutOfGas` if there is not enough gas or addition of the specified + /// amount of gas has lead to overflow. On success returns `Proceed`. + /// + /// NOTE that `amount` is always consumed, i.e. if there is not enough gas + /// then the counter will be set to zero. + pub fn charge(&mut self, amount: T::Gas) -> GasMeterResult { + let new_value = match self.gas_left.checked_sub(&amount) { + None => None, + Some(val) if val.is_zero() => None, + Some(val) => Some(val), + }; + + // We always consume the gas even if there is not enough gas. + self.gas_left = new_value.unwrap_or_else(Zero::zero); + + match new_value { + Some(_) => GasMeterResult::Proceed, + None => GasMeterResult::OutOfGas, + } + } + + /// Account for used gas expressed in balance units. + /// + /// Same as [`charge`], but amount to be charged is converted from units of balance to + /// units of gas. + /// + /// [`charge`]: #method.charge + pub fn charge_by_balance(&mut self, amount: T::Balance) -> GasMeterResult { + let amount_in_gas: T::Balance = amount / self.gas_price; + let amount_in_gas: T::Gas = >::sa(amount_in_gas); + self.charge(amount_in_gas) + } + + /// Allocate some amount of gas and perform some work with + /// a newly created nested gas meter. + /// + /// Invokes `f` with either the gas meter that has `amount` gas left or + /// with `None`, if this gas meter has not enough gas to allocate given `amount`. + /// + /// All unused gas in the nested gas meter is returned to this gas meter. + pub fn with_nested>) -> R>( + &mut self, + amount: T::Gas, + f: F, + ) -> R { + // NOTE that it is ok to allocate all available gas since it still ensured + // by `charge` that it doesn't reach zero. + if self.gas_left < amount { + f(None) + } else { + self.gas_left = self.gas_left - amount; + let mut nested = GasMeter { + gas_left: amount, + gas_price: self.gas_price, + }; + + let r = f(Some(&mut nested)); + + self.gas_left = self.gas_left + nested.gas_left; + + r + } + } + + /// Returns how much gas left from the initial budget. + pub fn gas_left(&self) -> T::Gas { + self.gas_left + } +} + +/// Buy the given amount of gas. +/// +/// Cost is calculated by multiplying the gas cost (taken from the storage) by the `gas_limit`. +/// The funds are deducted from `transactor`. +pub fn buy_gas( + transactor: &T::AccountId, + gas_limit: T::Gas, +) -> Result, &'static str> { + let gas_price = >::gas_price(); + let b = >::free_balance(transactor); + let cost = >::as_(gas_limit.clone()) + .checked_mul(&gas_price) + .ok_or("overflow multiplying gas limit by price")?; + if b < cost + >::existential_deposit() { + return Err("not enough funds for transaction fee"); + } + >::set_free_balance(transactor, b - cost); + Ok(GasMeter { + gas_left: gas_limit, + gas_price, + }) +} + +/// Refund the unused gas. +pub fn refund_unused_gas(transactor: &T::AccountId, gas_meter: GasMeter) { + let b = >::free_balance(transactor); + let refund = >::as_(gas_meter.gas_left) * gas_meter.gas_price; + >::set_free_balance(transactor, b + refund); +} diff --git a/substrate/runtime/contract/src/genesis_config.rs b/substrate/runtime/contract/src/genesis_config.rs new file mode 100644 index 0000000000000..d841f22806a6a --- /dev/null +++ b/substrate/runtime/contract/src/genesis_config.rs @@ -0,0 +1,48 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +//! Build the contract module part of the genesis block storage. + +use {Trait, ContractFee, CallBaseFee, CreateBaseFee, GasPrice, MaxDepth}; + +use runtime_primitives; +use runtime_io::{self, twox_128}; +use runtime_support::StorageValue; +use codec::Encode; + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +pub struct GenesisConfig { + pub contract_fee: T::Balance, + pub call_base_fee: T::Gas, + pub create_base_fee: T::Gas, + pub gas_price: T::Balance, + pub max_depth: u32, +} + +impl runtime_primitives::BuildStorage for GenesisConfig { + fn build_storage(self) -> Result { + let r: runtime_io::TestExternalities = map![ + twox_128(>::key()).to_vec() => self.contract_fee.encode(), + twox_128(>::key()).to_vec() => self.call_base_fee.encode(), + twox_128(>::key()).to_vec() => self.create_base_fee.encode(), + twox_128(>::key()).to_vec() => self.gas_price.encode(), + twox_128(>::key()).to_vec() => self.max_depth.encode() + ]; + Ok(r) + } +} diff --git a/substrate/runtime/contract/src/lib.rs b/substrate/runtime/contract/src/lib.rs index bc51673fd44db..123574b27c0ac 100644 --- a/substrate/runtime/contract/src/lib.rs +++ b/substrate/runtime/contract/src/lib.rs @@ -14,637 +14,241 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Crate for executing smart-contracts. +//! Smart-contract module for runtime; Allows deployment and execution of smart-contracts +//! expressed in WebAssembly. //! -//! It provides an means for executing contracts represented in WebAssembly (Wasm for short). -//! Contracts are able to create other contracts, transfer funds to each other and operate on a simple key-value storage. +//! This module provides an ability to create smart-contract accounts and send them messages. +//! A smart-contract is an account with associated code and storage. When such an account receives a message, +//! the code associated with that account gets executed. +//! +//! The code is allowed to alter the storage entries of the associated account, +//! create smart-contracts or send messages to existing smart-contracts. +//! +//! For any actions invoked by the smart-contracts fee must be paid. The fee is paid in gas. +//! Gas is bought upfront. Any unused is refunded after the transaction (regardless of the +//! execution outcome). If all gas is used, then changes made for the specific call or create +//! are reverted (including balance transfers). +//! +//! Failures are typically not cascading. That, for example, means that if contract A calls B and B errors +//! somehow, then A can decide if it should proceed or error. +//! TODO: That is not the case now, since call/create externalities traps on any error now. #![cfg_attr(not(feature = "std"), no_std)] -#![warn(missing_docs)] + +#[cfg(feature = "std")] +#[macro_use] +extern crate serde_derive; + +#[cfg(feature = "std")] +extern crate serde; extern crate parity_wasm; extern crate pwasm_utils; -extern crate substrate_runtime_std as rstd; -extern crate substrate_runtime_sandbox as sandbox; extern crate substrate_codec as codec; +extern crate substrate_runtime_io as runtime_io; +extern crate substrate_runtime_sandbox as sandbox; -#[cfg(test)] -#[macro_use] -extern crate assert_matches; - -#[cfg(test)] -extern crate wabt; +#[cfg_attr(feature = "std", macro_use)] +extern crate substrate_runtime_std as rstd; -use rstd::prelude::*; -use codec::Slicable; +extern crate substrate_runtime_consensus as consensus; +extern crate substrate_runtime_staking as staking; +extern crate substrate_runtime_system as system; -use parity_wasm::elements::{self, External, MemoryType}; -use pwasm_utils::rules; +#[cfg(test)] +extern crate substrate_runtime_timestamp as timestamp; +#[cfg(test)] +extern crate substrate_runtime_session as session; -/// An interface that provides an access to the external environment in which the -/// smart-contract is executed. -/// -/// This interface is specialised to an account of the executing code, so all -/// operations are implicitly performed on that account. -pub trait Ext { - /// The indentifier of an account. - type AccountId: Slicable + Clone; - /// The balance of an account. - type Balance: Slicable; - - /// Returns the storage entry of the executing account by the given key. - fn get_storage(&self, key: &[u8]) -> Option>; - - /// Sets the storage entry by the given key to the specified value. - fn set_storage(&mut self, key: &[u8], value: Option>); - - // TODO: Return the address of the created contract. - /// Create a new account for a contract. - /// - /// The newly created account will be associated with the `code`. `value` specifies the amount of value - /// transfered from this to the newly created account. - fn create(&mut self, code: &[u8], value: Self::Balance); +#[macro_use] +extern crate substrate_runtime_support as runtime_support; - /// Transfer some funds to the specified account. - fn transfer(&mut self, to: &Self::AccountId, value: Self::Balance); -} +extern crate substrate_runtime_primitives as runtime_primitives; -/// Error that can occur while preparing or executing wasm smart-contract. -#[derive(Debug, PartialEq, Eq)] -pub enum Error { - /// Error happened while serializing the module. - Serialization, +#[cfg(test)] +#[macro_use] +extern crate assert_matches; - /// Error happened while deserializing the module. - Deserialization, +#[cfg(test)] +extern crate wabt; - /// Internal memory declaration has been found in the module. - InternalMemoryDeclared, +mod account_db; +mod double_map; +mod exec; +mod vm; +mod gas; +mod genesis_config; - /// Gas instrumentation failed. - /// - /// This most likely indicates the module isn't valid. - GasInstrumentation, +#[cfg(test)] +mod tests; - /// Stack instrumentation failed. - /// - /// This most likely indicates the module isn't valid. - StackHeightInstrumentation, +pub use genesis_config::GenesisConfig; +use exec::ExecutionContext; +use account_db::{AccountDb, OverlayAccountDb}; +use double_map::StorageDoubleMap; - /// Error happened during invocation of the contract's entrypoint. - /// - /// Most likely because of trap. - Invoke, +use codec::Codec; +use runtime_primitives::traits::{As, RefInto, SimpleArithmetic}; +use runtime_support::dispatch::Result; +use runtime_support::{Parameter, StorageMap}; - /// Error happened during instantiation. - /// - /// This might indicate that `start` function trapped, or module isn't - /// instantiable and/or unlinkable. - Instantiate, +pub trait Trait: system::Trait + staking::Trait + consensus::Trait { + /// Function type to get the contract address given the creator. + type DetermineContractAddress: ContractAddressFor; - /// Memory creation error. - /// - /// This might happen when the memory import has invalid descriptor or - /// requested too much resources. - Memory, + // As is needed for wasm-utils + type Gas: Parameter + Codec + SimpleArithmetic + Copy + As + As + As; } -struct Runtime<'a, T: Ext + 'a> { - ext: &'a mut T, - memory: sandbox::Memory, - gas_used: u64, - gas_limit: u64, -} -impl<'a, T: Ext + 'a> Runtime<'a, T> { - fn memory(&self) -> &sandbox::Memory { - &self.memory - } - fn ext(&self) -> &T { - self.ext - } - fn ext_mut(&mut self) -> &mut T { - self.ext - } - /// Account for used gas. - /// - /// Returns `false` if there is not enough gas or addition of the specified - /// amount of gas has lead to overflow. On success returns `true`. - /// - /// Intuition about the return value sense is to answer the question 'are we allowed to continue?' - fn charge_gas(&mut self, amount: u64) -> bool { - match self.gas_used.checked_add(amount) { - None => false, - Some(val) if val > self.gas_limit => false, - Some(val) => { - self.gas_used = val; - true - } - } - } +pub trait ContractAddressFor { + fn contract_address_for(code: &[u8], origin: &AccountId) -> AccountId; } -/// Execute the given code as a contract. -pub fn execute<'a, T: Ext>( - code: &[u8], - ext: &'a mut T, - gas_limit: u64, -) -> Result<(), Error> { - // ext_gas(amount: u32) - // - // Account for used gas. Traps if gas used is greater than gas limit. - // - // - amount: How much gas is used. - fn ext_gas(e: &mut Runtime, args: &[sandbox::TypedValue]) -> Result { - let amount = args[0].as_i32().unwrap() as u32; - if e.charge_gas(amount as u64) { - Ok(sandbox::ReturnValue::Unit) - } else { - Err(sandbox::HostError) - } +decl_module! { + /// Contracts module. + pub struct Module; + + #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] + pub enum Call where aux: T::PublicAux { + // TODO: Change AccountId to staking::Address + fn call( + aux, + dest: T::AccountId, + value: T::Balance, + gas_limit: T::Gas, + data: Vec + ) -> Result = 0; + + fn create( + aux, + value: T::Balance, + gas_limit: T::Gas, + ctor: Vec, + data: Vec + ) -> Result = 1; } - - // ext_put_storage(location_ptr: u32, value_non_null: u32, value_ptr: u32); - // - // Change the value at the given location in storage or remove it. - // - // - location_ptr: pointer into the linear - // memory where the location of the requested value is placed. - // - value_non_null: if set to 0, then the entry - // at the given location will be removed. - // - value_ptr: pointer into the linear memory - // where the value to set is placed. If `value_non_null` is set to 0, then this parameter is ignored. - fn ext_set_storage( - e: &mut Runtime, - args: &[sandbox::TypedValue], - ) -> Result { - let location_ptr = args[0].as_i32().unwrap() as u32; - let value_non_null = args[1].as_i32().unwrap() as u32; - let value_ptr = args[2].as_i32().unwrap() as u32; - - let mut location = [0; 32]; - - e.memory().get(location_ptr, &mut location)?; - - let value = if value_non_null != 0 { - let mut value = [0; 32]; - e.memory().get(value_ptr, &mut value)?; - Some(value.to_vec()) - } else { - None - }; - e.ext_mut().set_storage( - &location, - value, - ); - - Ok(sandbox::ReturnValue::Unit) - } - - // ext_get_storage(location_ptr: u32, dest_ptr: u32); - // - // Retrieve the value at the given location from the strorage. - // If there is no entry at the given location then all-zero-value - // will be returned. - // - // - location_ptr: pointer into the linear - // memory where the location of the requested value is placed. - // - dest_ptr: pointer where contents of the specified storage location - // should be placed. - fn ext_get_storage(e: &mut Runtime, args: &[sandbox::TypedValue]) -> Result { - let location_ptr = args[0].as_i32().unwrap() as u32; - let dest_ptr = args[1].as_i32().unwrap() as u32; - - let mut location = [0; 32]; - e.memory().get(location_ptr, &mut location)?; - - if let Some(value) = e.ext().get_storage(&location) { - e.memory().set(dest_ptr, &value)?; - } else { - e.memory().set(dest_ptr, &[0u8; 32])?; - } - - Ok(sandbox::ReturnValue::Unit) - } - - // ext_transfer(transfer_to: u32, transfer_to_len: u32, value_ptr: u32, value_len: u32) - fn ext_transfer(e: &mut Runtime, args: &[sandbox::TypedValue]) -> Result { - let transfer_to_ptr = args[0].as_i32().unwrap() as u32; - let transfer_to_len = args[1].as_i32().unwrap() as u32; - let value_ptr = args[2].as_i32().unwrap() as u32; - let value_len = args[3].as_i32().unwrap() as u32; - - let mut transfer_to = Vec::new(); - transfer_to.resize(transfer_to_len as usize, 0); - e.memory().get(transfer_to_ptr, &mut transfer_to)?; - let transfer_to = T::AccountId::decode(&mut &transfer_to[..]).unwrap(); - - let mut value_buf = Vec::new(); - value_buf.resize(value_len as usize, 0); - e.memory().get(value_ptr, &mut value_buf)?; - let value = T::Balance::decode(&mut &value_buf[..]).unwrap(); - - e.ext_mut().transfer(&transfer_to, value); - - Ok(sandbox::ReturnValue::Unit) - } - - // ext_create(code_ptr: u32, code_len: u32, value_ptr: u32, value_len: u32) - fn ext_create(e: &mut Runtime, args: &[sandbox::TypedValue]) -> Result { - let code_ptr = args[0].as_i32().unwrap() as u32; - let code_len = args[1].as_i32().unwrap() as u32; - let value_ptr = args[2].as_i32().unwrap() as u32; - let value_len = args[3].as_i32().unwrap() as u32; - - let mut value_buf = Vec::new(); - value_buf.resize(value_len as usize, 0); - e.memory().get(value_ptr, &mut value_buf)?; - let value = T::Balance::decode(&mut &value_buf[..]).unwrap(); - - let mut code = Vec::new(); - code.resize(code_len as usize, 0u8); - e.memory().get(code_ptr, &mut code)?; - - e.ext_mut().create(&code, value); - - Ok(sandbox::ReturnValue::Unit) - } - - let PreparedContract { - instrumented_code, - memory, - } = prepare_contract(code)?; - - let mut imports = sandbox::EnvironmentDefinitionBuilder::new(); - imports.add_host_func("env", "gas", ext_gas::); - imports.add_host_func("env", "ext_set_storage", ext_set_storage::); - imports.add_host_func("env", "ext_get_storage", ext_get_storage::); - imports.add_host_func("env", "ext_transfer", ext_transfer::); - imports.add_host_func("env", "ext_create", ext_create::); - // TODO: ext_balance, ext_address, ext_callvalue, etc. - imports.add_memory("env", "memory", memory.clone()); - - let mut runtime = Runtime { - ext, - memory, - gas_limit, - gas_used: 0, - }; - - let mut instance = - sandbox::Instance::new(&instrumented_code, &imports, &mut runtime) - .map_err(|_| Error::Instantiate)?; - instance - .invoke(b"call", &[], &mut runtime) - .map(|_| ()) - .map_err(|_| Error::Invoke) } -#[derive(Clone)] -struct Config { - /// Gas cost of a growing memory by single page. - grow_mem_cost: u32, - - /// Gas cost of a regular operation. - regular_op_cost: u32, - - /// How tall the stack is allowed to grow? - /// - /// See https://wiki.parity.io/WebAssembly-StackHeight to find out - /// how the stack frame cost is calculated. - max_stack_height: u32, - - //// What is the maximal memory pages amount is allowed to have for - /// a contract. - max_memory_pages: u32, +decl_storage! { + trait Store for Module; + + // The fee required to create a contract. At least as big as staking's ReclaimRebate. + ContractFee get(contract_fee): b"con:contract_fee" => required T::Balance; + // The fee charged for a call into a contract. + CallBaseFee get(call_base_fee): b"con:base_call_fee" => required T::Gas; + // The fee charged for a create of a contract. + CreateBaseFee get(create_base_fee): b"con:base_create_fee" => required T::Gas; + // The price of one unit of gas. + GasPrice get(gas_price): b"con:gas_price" => required T::Balance; + // The maximum nesting level of a call/create stack. + MaxDepth get(max_depth): b"con:max_depth" => required u32; + + // The code associated with an account. + pub CodeOf: b"con:cod:" => default map [ T::AccountId => Vec ]; // TODO Vec values should be optimised to not do a length prefix. } -impl Default for Config { - fn default() -> Config { - Config { - grow_mem_cost: 1, - regular_op_cost: 1, - max_stack_height: 64 * 1024, - max_memory_pages: 16, - } - } -} +// TODO: consider storing upper-bound for contract's gas limit in fixed-length runtime +// code in contract itself and use that. -struct ContractModule { - // An `Option` is used here for loaning (`take()`-ing) the module. - // Invariant: Can't be `None` (i.e. on enter and on exit from the function - // the value *must* be `Some`). - module: Option, - config: Config, +/// The storage items associated with an account/key. +/// +/// TODO: keys should also be able to take AsRef to ensure Vecs can be passed as &[u8] +pub(crate) struct StorageOf(::rstd::marker::PhantomData); +impl double_map::StorageDoubleMap for StorageOf { + const PREFIX: &'static [u8] = b"con:sto:"; + type Key1 = T::AccountId; + type Key2 = Vec; + type Value = Vec; } -impl ContractModule { - fn new(original_code: &[u8], config: Config) -> Result { - let module = - elements::deserialize_buffer(original_code).map_err(|_| Error::Deserialization)?; - Ok(ContractModule { - module: Some(module), - config, - }) - } +impl Module { + /// Make a call to a specified account, optionally transferring some balance. + fn call( + aux: &::PublicAux, + dest: T::AccountId, + value: T::Balance, + gas_limit: T::Gas, + data: Vec, + ) -> Result { + let aux = aux.ref_into(); + + // Pay for the gas upfront. + // + // NOTE: it is very important to avoid any state changes before + // paying for the gas. + let mut gas_meter = gas::buy_gas::(aux, gas_limit)?; + + let mut ctx = ExecutionContext { + self_account: aux.clone(), + depth: 0, + overlay: OverlayAccountDb::::new(&account_db::DirectAccountDb), + }; + let result = ctx.call(aux.clone(), dest, value, &mut gas_meter, &data); - /// Ensures that module doesn't declare internal memories. - /// - /// In this runtime we only allow wasm module to import memory from the environment. - /// Memory section contains declarations of internal linear memories, so if we find one - /// we reject such a module. - fn ensure_no_internal_memory(&self) -> Result<(), Error> { - let module = self.module - .as_ref() - .expect("On entry to the function `module` can't be None; qed"); - if module - .memory_section() - .map_or(false, |ms| ms.entries().len() > 0) - { - return Err(Error::InternalMemoryDeclared); + if let Ok(_) = result { + // Commit all changes that made it thus far into the persistant storage. + account_db::DirectAccountDb.commit(ctx.overlay.into_change_set()); } - Ok(()) - } - - fn inject_gas_metering(&mut self) -> Result<(), Error> { - let gas_rules = rules::Set::new(self.config.regular_op_cost, Default::default()) - .with_grow_cost(self.config.grow_mem_cost) - .with_forbidden_floats(); - - let module = self.module - .take() - .expect("On entry to the function `module` can't be `None`; qed"); - - let contract_module = pwasm_utils::inject_gas_counter(module, &gas_rules) - .map_err(|_| Error::GasInstrumentation)?; - - self.module = Some(contract_module); - Ok(()) - } - fn inject_stack_height_metering(&mut self) -> Result<(), Error> { - let module = self.module - .take() - .expect("On entry to the function `module` can't be `None`; qed"); + // Refund cost of the unused gas. + // + // NOTE: this should go after the commit to the storage, since the storage changes + // can alter the balance of the caller. + gas::refund_unused_gas::(aux, gas_meter); - let contract_module = - pwasm_utils::stack_height::inject_limiter(module, self.config.max_stack_height) - .map_err(|_| Error::StackHeightInstrumentation)?; - - self.module = Some(contract_module); - Ok(()) - } - - /// Find the memory import entry and return it's descriptor. - fn find_mem_import(&self) -> Option<&MemoryType> { - let import_section = self.module - .as_ref() - .expect("On entry to the function `module` can't be `None`; qed") - .import_section()?; - for import in import_section.entries() { - if let ("env", "memory", &External::Memory(ref memory_type)) = - (import.module(), import.field(), import.external()) - { - return Some(memory_type); - } - } - None + result.map(|_| ()) } - fn into_wasm_code(mut self) -> Result, Error> { - elements::serialize( - self.module - .take() - .expect("On entry to the function `module` can't be `None`; qed"), - ).map_err(|_| Error::Serialization) - } -} - -struct PreparedContract { - instrumented_code: Vec, - memory: sandbox::Memory, -} - -fn prepare_contract(original_code: &[u8]) -> Result { - let config = Config::default(); - - let mut contract_module = ContractModule::new(original_code, config.clone())?; - contract_module.ensure_no_internal_memory()?; - contract_module.inject_gas_metering()?; - contract_module.inject_stack_height_metering()?; - - // Inspect the module to extract the initial and maximum page count. - let memory = match contract_module.find_mem_import() { - Some(memory_type) => { - let limits = memory_type.limits(); - match (limits.initial(), limits.maximum()) { - (initial, Some(maximum)) if initial > maximum => { - // Requested initial number of pages should not exceed the requested maximum. - return Err(Error::Memory); - } - (_, Some(maximum)) if maximum > config.max_memory_pages => { - // Maximum number of pages should not exceed the configured maximum. - return Err(Error::Memory); - } - (_, None) => { - // Maximum number of pages should be always declared. - // This isn't a hard requirement and can be treated as a maxiumum set - // to configured maximum. - return Err(Error::Memory) - } - (initial, maximum) => sandbox::Memory::new( - initial, - maximum, - ) - } - }, - - // If none memory imported then just crate an empty placeholder. - // Any access to it will lead to out of bounds trap. - None => sandbox::Memory::new(0, Some(0)), - }.map_err(|_| Error::Memory)?; - - Ok(PreparedContract { - instrumented_code: contract_module.into_wasm_code()?, - memory, - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use std::fmt; - use wabt; - use std::collections::HashMap; - - #[derive(Debug, PartialEq, Eq)] - struct CreateEntry { - code: Vec, - endownment: u64, - } - #[derive(Debug, PartialEq, Eq)] - struct TransferEntry { - to: u64, - value: u64, - } - #[derive(Default)] - struct MockExt { - storage: HashMap, Vec>, - creates: Vec, - transfers: Vec, - } - impl Ext for MockExt { - type AccountId = u64; - type Balance = u64; - - fn get_storage(&self, key: &[u8]) -> Option> { - self.storage.get(key).cloned() - } - fn set_storage(&mut self, key: &[u8], value: Option>) { - *self.storage.entry(key.to_vec()).or_insert(Vec::new()) = value.unwrap_or(Vec::new()); - } - fn create(&mut self, code: &[u8], value: Self::Balance) { - self.creates.push( - CreateEntry { - code: code.to_vec(), - endownment: value, - } - ); - } - fn transfer(&mut self, to: &Self::AccountId, value: Self::Balance) { - self.transfers.push( - TransferEntry { - to: *to, - value, - } - ); - } - } + /// Create a new contract, optionally transfering some balance to the created account. + /// + /// Creation is executed as follows:ExecutionContext + /// + /// - the destination address is computed based on the sender and hash of the code. + /// - account is created at the computed address. + /// - the `ctor_code` is executed in the context of the newly created account. Buffer returned + /// after the execution is saved as the `code` of the account. That code will be invoked + /// upon any message received by this account. + fn create( + aux: &::PublicAux, + endowment: T::Balance, + gas_limit: T::Gas, + ctor_code: Vec, + data: Vec, + ) -> Result { + let aux = aux.ref_into(); + + // Pay for the gas upfront. + // + // NOTE: it is very important to avoid any state changes before + // paying for the gas. + let mut gas_meter = gas::buy_gas::(aux, gas_limit)?; + + let mut ctx = ExecutionContext { + self_account: aux.clone(), + depth: 0, + overlay: OverlayAccountDb::::new(&account_db::DirectAccountDb), + }; + let result = ctx.create(aux.clone(), endowment, &mut gas_meter, &ctor_code, &data); - impl fmt::Debug for PreparedContract { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "PreparedContract {{ .. }}") + if let Ok(_) = result { + // Commit all changes that made it thus far into the persistant storage. + account_db::DirectAccountDb.commit(ctx.overlay.into_change_set()); } - } - - fn parse_and_prepare_wat(wat: &str) -> Result { - let wasm = wabt::Wat2Wasm::new() - .validate(false) - .convert(wat) - .unwrap(); - prepare_contract(wasm.as_ref()) - } - - #[test] - fn internal_memory_declaration() { - let r = parse_and_prepare_wat( - r#"(module (memory 1 1))"#, - ); - assert_matches!(r, Err(Error::InternalMemoryDeclared)); - } - #[test] - fn memory() { - // This test assumes that maximum page number is configured to a certain number. - assert_eq!(Config::default().max_memory_pages, 16); - - let r = parse_and_prepare_wat( - r#"(module (import "env" "memory" (memory 1 1)))"#, - ); - assert_matches!(r, Ok(_)); - - // No memory import - let r = parse_and_prepare_wat( - r#"(module)"#, - ); - assert_matches!(r, Ok(_)); - - // incorrect import name. That's kinda ok, since this will fail - // at later stage when imports will be resolved. - let r = parse_and_prepare_wat( - r#"(module (import "vne" "memory" (memory 1 1)))"#, - ); - assert_matches!(r, Ok(_)); - - // initial exceed maximum - let r = parse_and_prepare_wat( - r#"(module (import "env" "memory" (memory 16 1)))"#, - ); - assert_matches!(r, Err(Error::Memory)); - - // no maximum - let r = parse_and_prepare_wat( - r#"(module (import "env" "memory" (memory 1)))"#, - ); - assert_matches!(r, Err(Error::Memory)); - - // requested maximum exceed configured maximum - let r = parse_and_prepare_wat( - r#"(module (import "env" "memory" (memory 1 17)))"#, - ); - assert_matches!(r, Err(Error::Memory)); - } + // Refund cost of the unused gas. + // + // NOTE: this should go after the commit to the storage, since the storage changes + // can alter the balance of the caller. + gas::refund_unused_gas::(aux, gas_meter); - const CODE_TRANSFER: &str = r#" -(module - ;; ext_transfer(transfer_to: u32, transfer_to_len: u32, value_ptr: u32, value_len: u32) - (import "env" "ext_transfer" (func $ext_transfer (param i32 i32 i32 i32))) - - (import "env" "memory" (memory 1 1)) - - (func (export "call") - (call $ext_transfer - (i32.const 4) ;; Pointer to "Transfer to" address. - (i32.const 8) ;; Length of "Transfer to" address. - (i32.const 12) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - ) - ) - - ;; Destination AccountId to transfer the funds. - ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 4) "\02\00\00\00\00\00\00\00") - - ;; Amount of value to transfer. - ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 12) "\06\00\00\00\00\00\00\00") -) -"#; - - #[test] - fn contract_transfer() { - let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); - - let mut mock_ext = MockExt::default(); - execute(&code_transfer, &mut mock_ext, 50_000).unwrap(); - - assert_eq!(&mock_ext.transfers, &[TransferEntry { - to: 2, - value: 6, - }]); + result.map(|_| ()) } +} - const CODE_MEM: &str = -r#" -(module - ;; Internal memory is not allowed. - (memory 1 1) - - (func (export "call") - nop - ) -) -"#; - - #[test] - fn contract_internal_mem() { - let code_mem = wabt::wat2wasm(CODE_MEM).unwrap(); - - let mut mock_ext = MockExt::default(); - - assert_matches!( - execute(&code_mem, &mut mock_ext, 100_000), - Err(_) - ); +impl staking::OnAccountKill for Module { + fn on_account_kill(who: &T::AccountId) { + >::remove(who); + >::remove_prefix(who.clone()); } } diff --git a/substrate/runtime/contract/src/tests.rs b/substrate/runtime/contract/src/tests.rs new file mode 100644 index 0000000000000..503fb780c3010 --- /dev/null +++ b/substrate/runtime/contract/src/tests.rs @@ -0,0 +1,493 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +use double_map::StorageDoubleMap; +use runtime_io::with_externalities; +use runtime_primitives::testing::{Digest, H256, Header}; +use runtime_primitives::traits::{BlakeTwo256, HasPublicAux, Identity}; +use runtime_primitives::BuildStorage; +use runtime_support::StorageMap; +use wabt; +use { + consensus, runtime_io, session, staking, system, timestamp, CodeOf, ContractAddressFor, + GenesisConfig, Module, StorageOf, Trait, +}; + +#[derive(Clone, Eq, PartialEq)] +pub struct Test; +impl HasPublicAux for Test { + type PublicAux = u64; +} +impl consensus::Trait for Test { + type PublicAux = ::PublicAux; + type SessionKey = u64; +} +impl system::Trait for Test { + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type Digest = Digest; + type AccountId = u64; + type Header = Header; +} +impl timestamp::Trait for Test { + const TIMESTAMP_SET_POSITION: u32 = 0; + type Moment = u64; +} +impl staking::Trait for Test { + type Balance = u64; + type AccountIndex = u64; + type OnAccountKill = Contract; +} +impl session::Trait for Test { + type ConvertAccountIdToSessionKey = Identity; + type OnSessionChange = Staking; +} +impl Trait for Test { + type Gas = u64; + type DetermineContractAddress = DummyContractAddressFor; +} + +type Staking = staking::Module; +type Contract = Module; + +pub struct DummyContractAddressFor; +impl ContractAddressFor for DummyContractAddressFor { + fn contract_address_for(_code: &[u8], origin: &u64) -> u64 { + origin + 1 + } +} + +fn new_test_ext(existential_deposit: u64, gas_price: u64) -> runtime_io::TestExternalities { + let mut t = system::GenesisConfig::::default() + .build_storage() + .unwrap(); + t.extend( + consensus::GenesisConfig:: { + code: vec![], + authorities: vec![], + }.build_storage() + .unwrap(), + ); + t.extend( + session::GenesisConfig:: { + session_length: 1, + validators: vec![10, 20], + broken_percent_late: 100, + }.build_storage() + .unwrap(), + ); + t.extend( + staking::GenesisConfig:: { + sessions_per_era: 1, + current_era: 0, + balances: vec![], + intentions: vec![], + validator_count: 2, + bonding_duration: 0, + transaction_base_fee: 0, + transaction_byte_fee: 0, + existential_deposit: existential_deposit, + transfer_fee: 0, + creation_fee: 0, + reclaim_rebate: 0, + early_era_slash: 0, + session_reward: 0, + }.build_storage() + .unwrap(), + ); + t.extend( + timestamp::GenesisConfig::::default() + .build_storage() + .unwrap(), + ); + t.extend( + GenesisConfig:: { + contract_fee: 21, + call_base_fee: 135, + create_base_fee: 175, + gas_price, + max_depth: 1024, + }.build_storage() + .unwrap(), + ); + t +} + +const CODE_TRANSFER: &str = r#" +(module + ;; ext_transfer(transfer_to: u32, transfer_to_len: u32, value_ptr: u32, value_len: u32) + (import "env" "ext_transfer" (func $ext_transfer (param i32 i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + (func (export "call") + (call $ext_transfer + (i32.const 4) ;; Pointer to "Transfer to" address. + (i32.const 8) ;; Length of "Transfer to" address. + (i32.const 12) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + ) + ) + ;; Destination AccountId to transfer the funds. + ;; Represented by u64 (8 bytes long) in little endian. + (data (i32.const 4) "\09\00\00\00\00\00\00\00") + ;; Amount of value to transfer. + ;; Represented by u64 (8 bytes long) in little endian. + (data (i32.const 12) "\06\00\00\00\00\00\00\00") +) +"#; + +#[test] +fn contract_transfer() { + const CONTRACT_SHOULD_TRANSFER_VALUE: u64 = 6; + const CONTRACT_SHOULD_TRANSFER_TO: u64 = 9; + + let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); + + with_externalities(&mut new_test_ext(0, 2), || { + >::insert(1, code_transfer.to_vec()); + + Staking::set_free_balance(&0, 100_000_000); + Staking::set_free_balance(&1, 11); + + assert_ok!(Contract::call(&0, 1, 3, 100_000, Vec::new())); + + assert_eq!( + Staking::free_balance(&0), + // 3 - value sent with the transaction + // 2 * 6 - gas used by the contract (6) multiplied by gas price (2) + // 2 * 135 - base gas fee for call (by transaction) + // 2 * 135 - base gas fee for call (by the contract) + 100_000_000 - 3 - (2 * 6) - (2 * 135) - (2 * 135), + ); + assert_eq!( + Staking::free_balance(&1), + 11 + 3 - CONTRACT_SHOULD_TRANSFER_VALUE, + ); + assert_eq!( + Staking::free_balance(&CONTRACT_SHOULD_TRANSFER_TO), + CONTRACT_SHOULD_TRANSFER_VALUE, + ); + }); +} + +#[test] +fn contract_transfer_oog() { + const CONTRACT_SHOULD_TRANSFER_TO: u64 = 9; + + let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); + + with_externalities(&mut new_test_ext(0, 2), || { + >::insert(1, code_transfer.to_vec()); + + Staking::set_free_balance(&0, 100_000_000); + Staking::set_free_balance(&1, 11); + + assert_err!( + Contract::call(&0, 1, 3, 276, Vec::new()), + "vm execute returned error while call" + ); + + assert_eq!( + Staking::free_balance(&0), + // 3 - value sent with the transaction + // 2 * 6 - gas used by the contract (6) multiplied by gas price (2) + // 2 * 135 - base gas fee for call (by transaction) + // 2 * 135 - base gas fee for call (by contract) + 100_000_000 - (2 * 6) - (2 * 135) - (2 * 135), + ); + assert_eq!( + Staking::free_balance(&1), + 11, + ); + assert_eq!( + Staking::free_balance(&CONTRACT_SHOULD_TRANSFER_TO), + 0, + ); + }); + +} + +/// Convert a byte slice to a string with hex values. +/// +/// Each value is preceeded with a `\` character. +fn escaped_bytestring(bytes: &[u8]) -> String { + use std::fmt::Write; + let mut result = String::new(); + for b in bytes { + write!(result, "\\{:02x}", b).unwrap(); + } + result +} + +/// Create a constructor for the specified code. +/// +/// When constructor is executed, it will call `ext_return` with code that +/// specified in `child_bytecode`. +fn code_ctor(child_bytecode: &[u8]) -> String { + format!( + r#" +(module + ;; ext_return(data_ptr: u32, data_len: u32) -> ! + (import "env" "ext_return" (func $ext_return (param i32 i32))) + (import "env" "memory" (memory 1 1)) + (func (export "call") + (call $ext_return + (i32.const 4) + (i32.const {code_len}) + ) + ;; ext_return is diverging, i.e. doesn't return. + unreachable + ) + (data (i32.const 4) "{escaped_bytecode}") +) +"#, + escaped_bytecode = escaped_bytestring(child_bytecode), + code_len = child_bytecode.len(), + ) +} + +/// Returns code that uses `ext_create` runtime call. +/// +/// Takes bytecode of the contract that needs to be deployed. +fn code_create(constructor: &[u8]) -> String { + format!( + r#" +(module + ;; ext_create(code_ptr: u32, code_len: u32, value_ptr: u32, value_len: u32) + (import "env" "ext_create" (func $ext_create (param i32 i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + (func (export "call") + (call $ext_create + (i32.const 12) ;; Pointer to `code` + (i32.const {code_len}) ;; Length of `code` + (i32.const 4) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer + ) + ) + ;; Amount of value to transfer. + ;; Represented by u64 (8 bytes long) in little endian. + (data (i32.const 4) "\03\00\00\00\00\00\00\00") + ;; Embedded wasm code. + (data (i32.const 12) "{escaped_constructor}") +) +"#, + escaped_constructor = escaped_bytestring(constructor), + code_len = constructor.len(), + ) +} + +#[test] +fn contract_create() { + let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); + let code_ctor_transfer = wabt::wat2wasm(&code_ctor(&code_transfer)).unwrap(); + let code_create = wabt::wat2wasm(&code_create(&code_ctor_transfer)).unwrap(); + + with_externalities(&mut new_test_ext(0, 2), || { + Staking::set_free_balance(&0, 100_000_000); + Staking::set_free_balance(&1, 0); + Staking::set_free_balance(&9, 30); + + >::insert(1, code_create.to_vec()); + + // When invoked, the contract at address `1` must create a contract with 'transfer' code. + assert_ok!(Contract::call(&0, 1, 11, 100_000, Vec::new())); + + let derived_address = ::DetermineContractAddress::contract_address_for( + &code_ctor_transfer, + &1, + ); + + // 11 - value sent with the transaction + // 2 * 128 - gas spent by the deployer contract (128) multiplied by gas price (2) + // 2 * 135 - base gas fee for call (top level) + // 2 * 175 - base gas fee for create (by contract) + // ((21 / 2) * 2) - price per account creation + let expected_gas_after_create = + 100_000_000 - 11 - (2 * 128) - (2 * 135) - (2 * 175) - ((21 / 2) * 2); + assert_eq!(Staking::free_balance(&0), expected_gas_after_create); + assert_eq!(Staking::free_balance(&1), 8); + assert_eq!(Staking::free_balance(&derived_address), 3); + + // Initiate transfer to the newly created contract. + assert_ok!(Contract::call(&0, derived_address, 22, 100_000, Vec::new())); + + assert_eq!( + Staking::free_balance(&0), + // 22 - value sent with the transaction + // (2 * 6) - gas used by the contract + // (2 * 135) - base gas fee for call (top level) + // (2 * 135) - base gas fee for call (by transfer contract) + expected_gas_after_create - 22 - (2 * 6) - (2 * 135) - (2 * 135), + ); + assert_eq!(Staking::free_balance(&derived_address), 22 - 3); + assert_eq!(Staking::free_balance(&9), 36); + }); +} + +#[test] +fn top_level_create() { + let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); + let code_ctor_transfer = wabt::wat2wasm(&code_ctor(&code_transfer)).unwrap(); + + with_externalities(&mut new_test_ext(0, 3), || { + let derived_address = ::DetermineContractAddress::contract_address_for( + &code_ctor_transfer, + &0, + ); + + Staking::set_free_balance(&0, 100_000_000); + Staking::set_free_balance(&derived_address, 30); + + assert_ok!(Contract::create( + &0, + 11, + 100_000, + code_ctor_transfer.clone(), + Vec::new(), + )); + + // 11 - value sent with the transaction + // (3 * 122) - gas spent by the ctor + // (3 * 175) - base gas fee for create (175) (top level) multipled by gas price (3) + // ((21 / 3) * 3) - price for contract creation + assert_eq!( + Staking::free_balance(&0), + 100_000_000 - 11 - (3 * 122) - (3 * 175) - ((21 / 3) * 3) + ); + assert_eq!(Staking::free_balance(&derived_address), 30 + 11); + + assert_eq!(>::get(&derived_address), code_transfer); + }); +} + +const CODE_NOP: &'static str = r#" +(module + (func (export "call") + nop + ) +) +"#; + +#[test] +fn refunds_unused_gas() { + let code_nop = wabt::wat2wasm(CODE_NOP).unwrap(); + + with_externalities(&mut new_test_ext(0, 2), || { + >::insert(1, code_nop.to_vec()); + + Staking::set_free_balance(&0, 100_000_000); + + assert_ok!(Contract::call(&0, 1, 0, 100_000, Vec::new(),)); + + assert_eq!(Staking::free_balance(&0), 100_000_000 - 4 - (2 * 135),); + }); +} + +#[test] +fn call_with_zero_value() { + with_externalities(&mut new_test_ext(0, 2), || { + >::insert(1, vec![]); + + Staking::set_free_balance(&0, 100_000_000); + + assert_ok!(Contract::call(&0, 1, 0, 100_000, Vec::new(),)); + + assert_eq!(Staking::free_balance(&0), 100_000_000 - (2 * 135),); + }); +} + +#[test] +fn create_with_zero_endowment() { + let code_nop = wabt::wat2wasm(CODE_NOP).unwrap(); + + with_externalities(&mut new_test_ext(0, 2), || { + Staking::set_free_balance(&0, 100_000_000); + + assert_ok!(Contract::create(&0, 0, 100_000, code_nop, Vec::new(),)); + + assert_eq!( + Staking::free_balance(&0), + // 4 - for the gas spent by the constructor + // 2 * 175 - base gas fee for create (175) multiplied by gas price (2) (top level) + 100_000_000 - 4 - (2 * 175), + ); + }); +} + +#[test] +fn account_removal_removes_storage() { + with_externalities(&mut new_test_ext(100, 2), || { + // Setup two accounts with free balance above than exsistential threshold. + { + Staking::set_free_balance(&1, 110); + >::insert(1, b"foo".to_vec(), b"1".to_vec()); + >::insert(1, b"bar".to_vec(), b"2".to_vec()); + + Staking::set_free_balance(&2, 110); + >::insert(2, b"hello".to_vec(), b"3".to_vec()); + >::insert(2, b"world".to_vec(), b"4".to_vec()); + } + + // Transfer funds from account 1 of such amount that after this transfer + // the balance of account 1 is will be below than exsistential threshold. + // + // This should lead to the removal of all storage associated with this account. + assert_ok!(Staking::transfer(&1, 2.into(), 20)); + + // Verify that all entries from account 1 is removed, while + // entries from account 2 is in place. + { + assert_eq!(>::get(1, b"foo".to_vec()), None); + assert_eq!(>::get(1, b"bar".to_vec()), None); + + assert_eq!( + >::get(2, b"hello".to_vec()), + Some(b"3".to_vec()) + ); + assert_eq!( + >::get(2, b"world".to_vec()), + Some(b"4".to_vec()) + ); + } + }); +} + +const CODE_UNREACHABLE: &'static str = r#" +(module + (func (export "call") + nop + unreachable + ) +) +"#; + +#[test] +fn top_level_call_refunds_even_if_fails() { + let code_unreachable = wabt::wat2wasm(CODE_UNREACHABLE).unwrap(); + with_externalities(&mut new_test_ext(0, 4), || { + >::insert(1, code_unreachable.to_vec()); + + Staking::set_free_balance(&0, 100_000_000); + + assert_err!( + Contract::call(&0, 1, 0, 100_000, Vec::new()), + "vm execute returned error while call" + ); + + assert_eq!(Staking::free_balance(&0), 100_000_000 - (4 * 3) - (4 * 135),); + }); +} diff --git a/substrate/runtime/contract/src/vm.rs b/substrate/runtime/contract/src/vm.rs new file mode 100644 index 0000000000000..1e594883eeb15 --- /dev/null +++ b/substrate/runtime/contract/src/vm.rs @@ -0,0 +1,762 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +//! Crate for executing smart-contracts. +//! +//! It provides an means for executing contracts represented in WebAssembly (Wasm for short). +//! Contracts are able to create other contracts, transfer funds +//! to each other and operate on a simple key-value storage. + +use codec::Decode; +use parity_wasm::elements::{self, External, MemoryType}; +use pwasm_utils; +use pwasm_utils::rules; +use rstd::prelude::*; +use sandbox; +use gas::{GasMeter, GasMeterResult}; +use runtime_primitives::traits::{As, CheckedMul}; +use {Trait}; +use exec::{CallReceipt, CreateReceipt}; + +/// An interface that provides an access to the external environment in which the +/// smart-contract is executed. +/// +/// This interface is specialised to an account of the executing code, so all +/// operations are implicitly performed on that account. +pub trait Ext { + /// Returns the storage entry of the executing account by the given key. + fn get_storage(&self, key: &[u8]) -> Option>; + + /// Sets the storage entry by the given key to the specified value. + fn set_storage(&mut self, key: &[u8], value: Option>); + + // TODO: Return the address of the created contract. + /// Create a new account for a contract. + /// + /// The newly created account will be associated with the `code`. `value` specifies the amount of value + /// transfered from this to the newly created account. + fn create( + &mut self, + code: &[u8], + value: T::Balance, + gas_meter: &mut GasMeter, + data: &[u8], + ) -> Result, ()>; + + /// Call (possibly transfering some amount of funds) into the specified account. + fn call( + &mut self, + to: &T::AccountId, + value: T::Balance, + gas_meter: &mut GasMeter, + data: &[u8], + ) -> Result; +} + +/// Error that can occur while preparing or executing wasm smart-contract. +#[derive(Debug, PartialEq, Eq)] +pub enum Error { + /// Error happened while serializing the module. + Serialization, + + /// Error happened while deserializing the module. + Deserialization, + + /// Internal memory declaration has been found in the module. + InternalMemoryDeclared, + + /// Gas instrumentation failed. + /// + /// This most likely indicates the module isn't valid. + GasInstrumentation, + + /// Stack instrumentation failed. + /// + /// This most likely indicates the module isn't valid. + StackHeightInstrumentation, + + /// Error happened during invocation of the contract's entrypoint. + /// + /// Most likely because of trap. + Invoke, + + /// Error happened during instantiation. + /// + /// This might indicate that `start` function trapped, or module isn't + /// instantiable and/or unlinkable. + Instantiate, + + /// Memory creation error. + /// + /// This might happen when the memory import has invalid descriptor or + /// requested too much resources. + Memory, +} + +/// Enumerates all possible *special* trap conditions. +/// +/// In this runtime traps used not only for signaling about errors but also +/// to just terminate quickly in some cases. +enum SpecialTrap { + // TODO: Can we pass wrapped memory instance instead of copying? + /// Signals that trap was generated in response to call `ext_return` host function. + Return(Vec), +} + +struct Runtime<'a, T: Trait + 'a, E: Ext + 'a> { + ext: &'a mut E, + config: &'a Config, + memory: sandbox::Memory, + gas_meter: &'a mut GasMeter, + special_trap: Option, +} +impl<'a, T: Trait, E: Ext + 'a> Runtime<'a, T, E> { + fn memory(&self) -> &sandbox::Memory { + &self.memory + } + /// Save a data buffer as a result of the execution. + /// + /// This function also charges gas for the returning. + /// + /// Returns `Err` if there is not enough gas. + fn store_return_data(&mut self, data: Vec) -> Result<(), ()> { + let data_len = >::sa(data.len() as u64); + let price = (self.config.return_data_per_byte_cost) + .checked_mul(&data_len) + .ok_or_else(|| ())?; + + match self.gas_meter.charge(price) { + GasMeterResult::Proceed => { + self.special_trap = Some(SpecialTrap::Return(data)); + Ok(()) + } + GasMeterResult::OutOfGas => Err(()), + } + } +} + +fn to_execution_result>( + runtime: Runtime, + run_err: Option, +) -> Result { + // Check the exact type of the error. It could be plain trap or + // special runtime trap the we must recognize. + let return_data = match (run_err, runtime.special_trap) { + // No traps were generated. Proceed normally. + (None, None) => Vec::new(), + // Special case. The trap was the result of the execution `return` host function. + (Some(sandbox::Error::Execution), Some(SpecialTrap::Return(rd))) => rd, + // Any other kind of a trap should result in a failure. + (Some(_), _) => return Err(Error::Invoke), + // Any other case (such as special trap flag without actual trap) signifies + // a logic error. + _ => unreachable!(), + }; + + Ok(ExecutionResult { + return_data, + }) +} + +/// The result of execution of a smart-contract. +#[derive(PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct ExecutionResult { + /// The result produced by the execution of the contract. + /// + /// The contract can designate some buffer at the execution time via a special function. + /// If contract called this function with non-empty buffer it will be copied here. + /// + /// Note that gas is already charged for returning the data. + pub return_data: Vec, +} + +/// Execute the given code as a contract. +pub fn execute<'a, T: Trait, E: Ext>( + code: &[u8], + ext: &'a mut E, + gas_meter: &mut GasMeter, +) -> Result { + // TODO: Receive data as an argument + + // ext_gas(amount: u32) + // + // Account for used gas. Traps if gas used is greater than gas limit. + // + // - amount: How much gas is used. + fn ext_gas>( + e: &mut Runtime, + args: &[sandbox::TypedValue], + ) -> Result { + let amount = args[0].as_i32().unwrap() as u32; + let amount = >::sa(amount); + + match e.gas_meter.charge(amount) { + GasMeterResult::Proceed => Ok(sandbox::ReturnValue::Unit), + GasMeterResult::OutOfGas => Err(sandbox::HostError), + } + } + + // ext_put_storage(location_ptr: u32, value_non_null: u32, value_ptr: u32); + // + // Change the value at the given location in storage or remove it. + // + // - location_ptr: pointer into the linear + // memory where the location of the requested value is placed. + // - value_non_null: if set to 0, then the entry + // at the given location will be removed. + // - value_ptr: pointer into the linear memory + // where the value to set is placed. If `value_non_null` is set to 0, then this parameter is ignored. + fn ext_set_storage>( + e: &mut Runtime, + args: &[sandbox::TypedValue], + ) -> Result { + let location_ptr = args[0].as_i32().unwrap() as u32; + let value_non_null = args[1].as_i32().unwrap() as u32; + let value_ptr = args[2].as_i32().unwrap() as u32; + + let mut location = [0; 32]; + + e.memory().get(location_ptr, &mut location)?; + + let value = if value_non_null != 0 { + let mut value = [0; 32]; + e.memory().get(value_ptr, &mut value)?; + Some(value.to_vec()) + } else { + None + }; + e.ext.set_storage(&location, value); + + Ok(sandbox::ReturnValue::Unit) + } + + // ext_get_storage(location_ptr: u32, dest_ptr: u32); + // + // Retrieve the value at the given location from the strorage. + // If there is no entry at the given location then all-zero-value + // will be returned. + // + // - location_ptr: pointer into the linear + // memory where the location of the requested value is placed. + // - dest_ptr: pointer where contents of the specified storage location + // should be placed. + fn ext_get_storage>( + e: &mut Runtime, + args: &[sandbox::TypedValue], + ) -> Result { + let location_ptr = args[0].as_i32().unwrap() as u32; + let dest_ptr = args[1].as_i32().unwrap() as u32; + + let mut location = [0; 32]; + e.memory().get(location_ptr, &mut location)?; + + if let Some(value) = e.ext.get_storage(&location) { + e.memory().set(dest_ptr, &value)?; + } else { + e.memory().set(dest_ptr, &[0u8; 32])?; + } + + Ok(sandbox::ReturnValue::Unit) + } + + // ext_transfer(transfer_to: u32, transfer_to_len: u32, value_ptr: u32, value_len: u32) + fn ext_transfer>( + e: &mut Runtime, + args: &[sandbox::TypedValue], + ) -> Result { + let transfer_to_ptr = args[0].as_i32().unwrap() as u32; + let transfer_to_len = args[1].as_i32().unwrap() as u32; + let value_ptr = args[2].as_i32().unwrap() as u32; + let value_len = args[3].as_i32().unwrap() as u32; + + let mut transfer_to = Vec::new(); + transfer_to.resize(transfer_to_len as usize, 0); + e.memory().get(transfer_to_ptr, &mut transfer_to)?; + let transfer_to = T::AccountId::decode(&mut &transfer_to[..]).unwrap(); + + let mut value_buf = Vec::new(); + value_buf.resize(value_len as usize, 0); + e.memory().get(value_ptr, &mut value_buf)?; + let value = T::Balance::decode(&mut &value_buf[..]).unwrap(); + + // TODO: Read input data from memory. + let input_data = Vec::new(); + + // TODO: Let user to choose how much gas to allocate for the execution. + let nested_gas_limit = e.gas_meter.gas_left(); + let ext = &mut e.ext; + let call_outcome = e.gas_meter.with_nested(nested_gas_limit, |nested_meter| { + match nested_meter { + Some(nested_meter) => ext.call(&transfer_to, value, nested_meter, &input_data), + // there is not enough gas to allocate for the nested call. + None => Err(()), + } + }); + + match call_outcome { + // TODO: Find a way how to pass return_data back to the this sandbox. + Ok(CallReceipt { .. }) => Ok(sandbox::ReturnValue::Unit), + // TODO: Return a status code value that can be handled by the caller instead of a trap. + Err(_) => Err(sandbox::HostError), + } + } + + // ext_create(code_ptr: u32, code_len: u32, value_ptr: u32, value_len: u32) + fn ext_create>( + e: &mut Runtime, + args: &[sandbox::TypedValue], + ) -> Result { + let code_ptr = args[0].as_i32().unwrap() as u32; + let code_len = args[1].as_i32().unwrap() as u32; + let value_ptr = args[2].as_i32().unwrap() as u32; + let value_len = args[3].as_i32().unwrap() as u32; + + let mut value_buf = Vec::new(); + value_buf.resize(value_len as usize, 0); + e.memory().get(value_ptr, &mut value_buf)?; + let value = T::Balance::decode(&mut &value_buf[..]).unwrap(); + + let mut code = Vec::new(); + code.resize(code_len as usize, 0u8); + e.memory().get(code_ptr, &mut code)?; + + // TODO: Read input data from the sandbox. + let input_data = Vec::new(); + + // TODO: Let user to choose how much gas to allocate for the execution. + let nested_gas_limit = e.gas_meter.gas_left(); + let ext = &mut e.ext; + let create_outcome = e.gas_meter.with_nested(nested_gas_limit, |nested_meter| { + match nested_meter { + Some(nested_meter) => ext.create(&code, value, nested_meter, &input_data), + // there is not enough gas to allocate for the nested call. + None => Err(()), + } + }); + + match create_outcome { + // TODO: Copy an address of the created contract in the sandbox. + Ok(CreateReceipt { .. }) => Ok(sandbox::ReturnValue::Unit), + // TODO: Return a status code value that can be handled by the caller instead of a trap. + Err(_) => Err(sandbox::HostError), + } + } + + // ext_return(data_ptr: u32, data_len: u32) -> ! + fn ext_return>( + e: &mut Runtime, + args: &[sandbox::TypedValue], + ) -> Result { + let data_ptr = args[0].as_i32().unwrap() as u32; + let data_len = args[1].as_i32().unwrap() as u32; + + let mut data_buf = Vec::new(); + data_buf.resize(data_len as usize, 0); + e.memory().get(data_ptr, &mut data_buf)?; + + e.store_return_data(data_buf) + .map_err(|_| sandbox::HostError)?; + + // The trap mechanism is used to immediately terminate the execution. + // This trap should be handled appropriately before returning the result + // to the user of this crate. + Err(sandbox::HostError) + } + + let config = Config::default(); + + let PreparedContract { + instrumented_code, + memory, + } = prepare_contract(code, &config)?; + + let mut imports = sandbox::EnvironmentDefinitionBuilder::new(); + imports.add_host_func("env", "gas", ext_gas::); + imports.add_host_func("env", "ext_set_storage", ext_set_storage::); + imports.add_host_func("env", "ext_get_storage", ext_get_storage::); + // TODO: Rename it to ext_call. + imports.add_host_func("env", "ext_transfer", ext_transfer::); + imports.add_host_func("env", "ext_create", ext_create::); + imports.add_host_func("env", "ext_return", ext_return::); + // TODO: ext_balance, ext_address, ext_callvalue, etc. + imports.add_memory("env", "memory", memory.clone()); + + let mut runtime = Runtime { + ext, + config: &config, + memory, + gas_meter, + special_trap: None, + }; + + let mut instance = sandbox::Instance::new(&instrumented_code, &imports, &mut runtime) + .map_err(|_| Error::Instantiate)?; + + let run_result = instance.invoke(b"call", &[], &mut runtime); + + to_execution_result(runtime, run_result.err()) +} + +// TODO: Extract it to the root of the crate +#[derive(Clone)] +struct Config { + /// Gas cost of a growing memory by single page. + grow_mem_cost: T::Gas, + + /// Gas cost of a regular operation. + regular_op_cost: T::Gas, + + /// Gas cost per one byte returned. + return_data_per_byte_cost: T::Gas, + + /// How tall the stack is allowed to grow? + /// + /// See https://wiki.parity.io/WebAssembly-StackHeight to find out + /// how the stack frame cost is calculated. + max_stack_height: u32, + + //// What is the maximal memory pages amount is allowed to have for + /// a contract. + max_memory_pages: u32, +} + +impl Default for Config { + fn default() -> Config { + Config { + grow_mem_cost: T::Gas::sa(1), + regular_op_cost: T::Gas::sa(1), + return_data_per_byte_cost: T::Gas::sa(1), + max_stack_height: 64 * 1024, + max_memory_pages: 16, + } + } +} + +struct ContractModule<'a, T: Trait + 'a> { + // An `Option` is used here for loaning (`take()`-ing) the module. + // Invariant: Can't be `None` (i.e. on enter and on exit from the function + // the value *must* be `Some`). + module: Option, + config: &'a Config, +} + +impl<'a, T: Trait> ContractModule<'a, T> { + fn new(original_code: &[u8], config: &'a Config) -> Result, Error> { + let module = + elements::deserialize_buffer(original_code).map_err(|_| Error::Deserialization)?; + Ok(ContractModule { + module: Some(module), + config, + }) + } + + /// Ensures that module doesn't declare internal memories. + /// + /// In this runtime we only allow wasm module to import memory from the environment. + /// Memory section contains declarations of internal linear memories, so if we find one + /// we reject such a module. + fn ensure_no_internal_memory(&self) -> Result<(), Error> { + let module = self + .module + .as_ref() + .expect("On entry to the function `module` can't be None; qed"); + if module + .memory_section() + .map_or(false, |ms| ms.entries().len() > 0) + { + return Err(Error::InternalMemoryDeclared); + } + Ok(()) + } + + fn inject_gas_metering(&mut self) -> Result<(), Error> { + let gas_rules = rules::Set::new(self.config.regular_op_cost.as_(), Default::default()) + .with_grow_cost(self.config.grow_mem_cost.as_()) + .with_forbidden_floats(); + + let module = self + .module + .take() + .expect("On entry to the function `module` can't be `None`; qed"); + + let contract_module = pwasm_utils::inject_gas_counter(module, &gas_rules) + .map_err(|_| Error::GasInstrumentation)?; + + self.module = Some(contract_module); + Ok(()) + } + + fn inject_stack_height_metering(&mut self) -> Result<(), Error> { + let module = self + .module + .take() + .expect("On entry to the function `module` can't be `None`; qed"); + + let contract_module = + pwasm_utils::stack_height::inject_limiter(module, self.config.max_stack_height) + .map_err(|_| Error::StackHeightInstrumentation)?; + + self.module = Some(contract_module); + Ok(()) + } + + /// Find the memory import entry and return it's descriptor. + fn find_mem_import(&self) -> Option<&MemoryType> { + let import_section = self + .module + .as_ref() + .expect("On entry to the function `module` can't be `None`; qed") + .import_section()?; + for import in import_section.entries() { + if let ("env", "memory", &External::Memory(ref memory_type)) = + (import.module(), import.field(), import.external()) + { + return Some(memory_type); + } + } + None + } + + fn into_wasm_code(mut self) -> Result, Error> { + elements::serialize( + self.module + .take() + .expect("On entry to the function `module` can't be `None`; qed"), + ).map_err(|_| Error::Serialization) + } +} + +struct PreparedContract { + instrumented_code: Vec, + memory: sandbox::Memory, +} + +fn prepare_contract(original_code: &[u8], config: &Config) -> Result { + let mut contract_module = ContractModule::new(original_code, config)?; + contract_module.ensure_no_internal_memory()?; + contract_module.inject_gas_metering()?; + contract_module.inject_stack_height_metering()?; + + // Inspect the module to extract the initial and maximum page count. + let memory = if let Some(memory_type) = contract_module.find_mem_import() { + let limits = memory_type.limits(); + match (limits.initial(), limits.maximum()) { + (initial, Some(maximum)) if initial > maximum => { + // Requested initial number of pages should not exceed the requested maximum. + return Err(Error::Memory); + } + (_, Some(maximum)) if maximum > config.max_memory_pages => { + // Maximum number of pages should not exceed the configured maximum. + return Err(Error::Memory); + } + (_, None) => { + // Maximum number of pages should be always declared. + // This isn't a hard requirement and can be treated as a maxiumum set + // to configured maximum. + return Err(Error::Memory); + } + (initial, maximum) => sandbox::Memory::new(initial, maximum), + } + } else { + // If none memory imported then just crate an empty placeholder. + // Any access to it will lead to out of bounds trap. + sandbox::Memory::new(0, Some(0)) + }; + let memory = memory.map_err(|_| Error::Memory)?; + + Ok(PreparedContract { + instrumented_code: contract_module.into_wasm_code()?, + memory, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::HashMap; + use std::fmt; + use wabt; + use gas::GasMeter; + use ::tests::Test; + + #[derive(Debug, PartialEq, Eq)] + struct CreateEntry { + code: Vec, + endowment: u64, + data: Vec, + } + #[derive(Debug, PartialEq, Eq)] + struct TransferEntry { + to: u64, + value: u64, + } + #[derive(Default)] + struct MockExt { + storage: HashMap, Vec>, + creates: Vec, + transfers: Vec, + next_account_id: u64, + } + impl Ext for MockExt { + fn get_storage(&self, key: &[u8]) -> Option> { + self.storage.get(key).cloned() + } + fn set_storage(&mut self, key: &[u8], value: Option>) { + *self.storage.entry(key.to_vec()).or_insert(Vec::new()) = value.unwrap_or(Vec::new()); + } + fn create( + &mut self, + code: &[u8], + endowment: u64, + _gas_meter: &mut GasMeter, + data: &[u8], + ) -> Result, ()> { + self.creates.push(CreateEntry { + code: code.to_vec(), + endowment, + data: data.to_vec(), + }); + let address = self.next_account_id; + self.next_account_id += 1; + + Ok(CreateReceipt { + address, + }) + } + fn call( + &mut self, + to: &u64, + value: u64, + _gas_meter: &mut GasMeter, + _data: &[u8], + ) -> Result { + self.transfers.push(TransferEntry { to: *to, value }); + // Assume for now that it was just a plain transfer. + // TODO: Add tests for different call outcomes. + Ok(CallReceipt { + return_data: Vec::new(), + }) + } + } + + impl fmt::Debug for PreparedContract { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "PreparedContract {{ .. }}") + } + } + + fn parse_and_prepare_wat(wat: &str) -> Result { + let wasm = wabt::Wat2Wasm::new().validate(false).convert(wat).unwrap(); + let config = Config::::default(); + prepare_contract(wasm.as_ref(), &config) + } + + #[test] + fn internal_memory_declaration() { + let r = parse_and_prepare_wat(r#"(module (memory 1 1))"#); + assert_matches!(r, Err(Error::InternalMemoryDeclared)); + } + + #[test] + fn memory() { + // This test assumes that maximum page number is configured to a certain number. + assert_eq!(Config::::default().max_memory_pages, 16); + + let r = parse_and_prepare_wat(r#"(module (import "env" "memory" (memory 1 1)))"#); + assert_matches!(r, Ok(_)); + + // No memory import + let r = parse_and_prepare_wat(r#"(module)"#); + assert_matches!(r, Ok(_)); + + // incorrect import name. That's kinda ok, since this will fail + // at later stage when imports will be resolved. + let r = parse_and_prepare_wat(r#"(module (import "vne" "memory" (memory 1 1)))"#); + assert_matches!(r, Ok(_)); + + // initial exceed maximum + let r = parse_and_prepare_wat(r#"(module (import "env" "memory" (memory 16 1)))"#); + assert_matches!(r, Err(Error::Memory)); + + // no maximum + let r = parse_and_prepare_wat(r#"(module (import "env" "memory" (memory 1)))"#); + assert_matches!(r, Err(Error::Memory)); + + // requested maximum exceed configured maximum + let r = parse_and_prepare_wat(r#"(module (import "env" "memory" (memory 1 17)))"#); + assert_matches!(r, Err(Error::Memory)); + } + + const CODE_TRANSFER: &str = r#" +(module + ;; ext_transfer(transfer_to: u32, transfer_to_len: u32, value_ptr: u32, value_len: u32) + (import "env" "ext_transfer" (func $ext_transfer (param i32 i32 i32 i32))) + + (import "env" "memory" (memory 1 1)) + + (func (export "call") + (call $ext_transfer + (i32.const 4) ;; Pointer to "Transfer to" address. + (i32.const 8) ;; Length of "Transfer to" address. + (i32.const 12) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + ) + ) + + ;; Destination AccountId to transfer the funds. + ;; Represented by u64 (8 bytes long) in little endian. + (data (i32.const 4) "\02\00\00\00\00\00\00\00") + + ;; Amount of value to transfer. + ;; Represented by u64 (8 bytes long) in little endian. + (data (i32.const 12) "\06\00\00\00\00\00\00\00") +) +"#; + + #[test] + fn contract_transfer() { + let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); + + let mut mock_ext = MockExt::default(); + execute(&code_transfer, &mut mock_ext, &mut GasMeter::with_limit(50_000, 1)).unwrap(); + + assert_eq!(&mock_ext.transfers, &[TransferEntry { to: 2, value: 6 }]); + } + + const CODE_MEM: &str = r#" +(module + ;; Internal memory is not allowed. + (memory 1 1) + + (func (export "call") + nop + ) +) +"#; + + #[test] + fn contract_internal_mem() { + let code_mem = wabt::wat2wasm(CODE_MEM).unwrap(); + + let mut mock_ext = MockExt::default(); + + assert_matches!( + execute(&code_mem, &mut mock_ext, &mut GasMeter::with_limit(100_000, 1)), + Err(_) + ); + } +} diff --git a/substrate/runtime/council/Cargo.toml b/substrate/runtime/council/Cargo.toml index 42270c35fca3a..5bfda8899e149 100644 --- a/substrate/runtime/council/Cargo.toml +++ b/substrate/runtime/council/Cargo.toml @@ -22,6 +22,9 @@ substrate-runtime-session = { path = "../session", default_features = false } substrate-runtime-staking = { path = "../staking", default_features = false } substrate-runtime-system = { path = "../system", default_features = false } +[dev-dependencies] +substrate-runtime-timestamp = { path = "../timestamp" } + [features] default = ["std"] std = [ diff --git a/substrate/runtime/council/src/lib.rs b/substrate/runtime/council/src/lib.rs index 8701cb6149447..56d87ea59bff5 100644 --- a/substrate/runtime/council/src/lib.rs +++ b/substrate/runtime/council/src/lib.rs @@ -38,6 +38,8 @@ extern crate substrate_runtime_democracy as democracy; extern crate substrate_runtime_session as session; extern crate substrate_runtime_staking as staking; extern crate substrate_runtime_system as system; +#[cfg(test)] +extern crate substrate_runtime_timestamp as timestamp; use rstd::prelude::*; use primitives::traits::{Zero, One, RefInto, As, AuxLookup}; @@ -359,7 +361,7 @@ impl Module { let (_, _, expiring) = Self::next_finalise().ok_or("cannot present outside of presentation period")?; let stakes = Self::snapshoted_stakes(); let voters = Self::voters(); - let bad_presentation_punishment = Self::present_slash_per_voter() * T::Balance::sa(voters.len()); + let bad_presentation_punishment = Self::present_slash_per_voter() * T::Balance::sa(voters.len() as u64); ensure!(>::can_slash(aux.ref_into(), bad_presentation_punishment), "presenter must have sufficient slashable funds"); let mut leaderboard = Self::leaderboard().ok_or("leaderboard must exist while present phase active")?; @@ -543,8 +545,11 @@ impl Module { } #[cfg(any(feature = "std", test))] +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] pub struct GenesisConfig { - // for the voting onto the council + // for the voting onto the council pub candidacy_bond: T::Balance, pub voter_bond: T::Balance, pub present_slash_per_voter: T::Balance, @@ -585,26 +590,25 @@ impl Default for GenesisConfig { #[cfg(any(feature = "std", test))] impl primitives::BuildStorage for GenesisConfig { - fn build_storage(self) -> runtime_io::TestExternalities { - use codec::Slicable; - use runtime_io::twox_128; - - map![ - twox_128(>::key()).to_vec() => self.candidacy_bond.encode(), - twox_128(>::key()).to_vec() => self.voter_bond.encode(), - twox_128(>::key()).to_vec() => self.present_slash_per_voter.encode(), - twox_128(>::key()).to_vec() => self.carry_count.encode(), - twox_128(>::key()).to_vec() => self.presentation_duration.encode(), - twox_128(>::key()).to_vec() => self.approval_voting_period.encode(), - twox_128(>::key()).to_vec() => self.term_duration.encode(), - twox_128(>::key()).to_vec() => self.desired_seats.encode(), - twox_128(>::key()).to_vec() => self.inactive_grace_period.encode(), - twox_128(>::key()).to_vec() => self.active_council.encode(), - - twox_128(>::key()).to_vec() => self.cooloff_period.encode(), - twox_128(>::key()).to_vec() => self.voting_period.encode(), - twox_128(>::key()).to_vec() => vec![0u8; 0].encode() - ] + fn build_storage(self) -> ::std::result::Result { + use codec::Encode; + + Ok(map![ + Self::hash(>::key()).to_vec() => self.candidacy_bond.encode(), + Self::hash(>::key()).to_vec() => self.voter_bond.encode(), + Self::hash(>::key()).to_vec() => self.present_slash_per_voter.encode(), + Self::hash(>::key()).to_vec() => self.carry_count.encode(), + Self::hash(>::key()).to_vec() => self.presentation_duration.encode(), + Self::hash(>::key()).to_vec() => self.approval_voting_period.encode(), + Self::hash(>::key()).to_vec() => self.term_duration.encode(), + Self::hash(>::key()).to_vec() => self.desired_seats.encode(), + Self::hash(>::key()).to_vec() => self.inactive_grace_period.encode(), + Self::hash(>::key()).to_vec() => self.active_council.encode(), + + Self::hash(>::key()).to_vec() => self.cooloff_period.encode(), + Self::hash(>::key()).to_vec() => self.voting_period.encode(), + Self::hash(>::key()).to_vec() => vec![0u8; 0].encode() + ]) } } @@ -646,27 +650,33 @@ mod tests { } impl session::Trait for Test { type ConvertAccountIdToSessionKey = Identity; + type OnSessionChange = staking::Module; } impl staking::Trait for Test { type Balance = u64; - type DetermineContractAddress = staking::DummyContractAddressFor; type AccountIndex = u64; + type OnAccountKill = (); } impl democracy::Trait for Test { type Proposal = Proposal; } + impl timestamp::Trait for Test { + const TIMESTAMP_SET_POSITION: u32 = 0; + type Moment = u64; + } impl Trait for Test {} pub fn new_test_ext(with_council: bool) -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::::default().build_storage(); + let mut t = system::GenesisConfig::::default().build_storage().unwrap(); t.extend(consensus::GenesisConfig::{ code: vec![], authorities: vec![], - }.build_storage()); + }.build_storage().unwrap()); t.extend(session::GenesisConfig::{ session_length: 1, //??? or 2? validators: vec![10, 20], - }.build_storage()); + broken_percent_late: 100, + }.build_storage().unwrap()); t.extend(staking::GenesisConfig::{ sessions_per_era: 1, current_era: 0, @@ -679,14 +689,15 @@ mod tests { existential_deposit: 0, transfer_fee: 0, creation_fee: 0, - contract_fee: 0, reclaim_rebate: 0, - }.build_storage()); + early_era_slash: 0, + session_reward: 0, + }.build_storage().unwrap()); t.extend(democracy::GenesisConfig::{ launch_period: 1, voting_period: 3, minimum_deposit: 1, - }.build_storage()); + }.build_storage().unwrap()); t.extend(GenesisConfig::{ candidacy_bond: 9, voter_bond: 3, @@ -704,7 +715,8 @@ mod tests { term_duration: 5, cooloff_period: 2, voting_period: 1, - }.build_storage()); + }.build_storage().unwrap()); + t.extend(timestamp::GenesisConfig::::default().build_storage().unwrap()); t } diff --git a/substrate/runtime/council/src/voting.rs b/substrate/runtime/council/src/voting.rs index 8470d1b420404..ecc5e074f7783 100644 --- a/substrate/runtime/council/src/voting.rs +++ b/substrate/runtime/council/src/voting.rs @@ -18,7 +18,7 @@ use rstd::prelude::*; use rstd::borrow::Borrow; -use primitives::traits::{Executable, RefInto, Hashing}; +use primitives::traits::{Executable, RefInto, Hash}; use runtime_io::print; use substrate_runtime_support::dispatch::Result; use substrate_runtime_support::{StorageValue, StorageMap, IsSubType}; diff --git a/substrate/runtime/democracy/Cargo.toml b/substrate/runtime/democracy/Cargo.toml index 2b52f72ff8700..eb0f54671f1d9 100644 --- a/substrate/runtime/democracy/Cargo.toml +++ b/substrate/runtime/democracy/Cargo.toml @@ -19,6 +19,9 @@ substrate-runtime-session = { path = "../session", default_features = false } substrate-runtime-staking = { path = "../staking", default_features = false } substrate-runtime-system = { path = "../system", default_features = false } +[dev-dependencies] +substrate-runtime-timestamp = { path = "../timestamp" } + [features] default = ["std"] std = [ diff --git a/substrate/runtime/democracy/src/lib.rs b/substrate/runtime/democracy/src/lib.rs index c6affbcb2db1f..9f9c00d056ab5 100644 --- a/substrate/runtime/democracy/src/lib.rs +++ b/substrate/runtime/democracy/src/lib.rs @@ -41,6 +41,8 @@ extern crate substrate_runtime_consensus as consensus; extern crate substrate_runtime_session as session; extern crate substrate_runtime_staking as staking; extern crate substrate_runtime_system as system; +#[cfg(test)] +extern crate substrate_runtime_timestamp as timestamp; use rstd::prelude::*; use rstd::result; @@ -115,7 +117,7 @@ impl Module { /// Get the amount locked in support of `proposal`; `None` if proposal isn't a valid proposal /// index. pub fn locked_for(proposal: PropIndex) -> Option { - Self::deposit_of(proposal).map(|(d, l)| d * T::Balance::sa(l.len())) + Self::deposit_of(proposal).map(|(d, l)| d * T::Balance::sa(l.len() as u64)) } /// Return true if `ref_index` is an on-going referendum. @@ -294,6 +296,9 @@ impl Executable for Module { } #[cfg(any(feature = "std", test))] +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] pub struct GenesisConfig { pub launch_period: T::BlockNumber, pub voting_period: T::BlockNumber, @@ -333,18 +338,17 @@ impl Default for GenesisConfig { #[cfg(any(feature = "std", test))] impl primitives::BuildStorage for GenesisConfig { - fn build_storage(self) -> runtime_io::TestExternalities { - use codec::Slicable; - use runtime_io::twox_128; - - map![ - twox_128(>::key()).to_vec() => self.launch_period.encode(), - twox_128(>::key()).to_vec() => self.voting_period.encode(), - twox_128(>::key()).to_vec() => self.minimum_deposit.encode(), - twox_128(>::key()).to_vec() => (0 as ReferendumIndex).encode(), - twox_128(>::key()).to_vec() => (0 as ReferendumIndex).encode(), - twox_128(>::key()).to_vec() => (0 as PropIndex).encode() - ] + fn build_storage(self) -> ::std::result::Result { + use codec::Encode; + + Ok(map![ + Self::hash(>::key()).to_vec() => self.launch_period.encode(), + Self::hash(>::key()).to_vec() => self.voting_period.encode(), + Self::hash(>::key()).to_vec() => self.minimum_deposit.encode(), + Self::hash(>::key()).to_vec() => (0 as ReferendumIndex).encode(), + Self::hash(>::key()).to_vec() => (0 as ReferendumIndex).encode(), + Self::hash(>::key()).to_vec() => (0 as PropIndex).encode() + ]) } } @@ -356,6 +360,7 @@ mod tests { use primitives::BuildStorage; use primitives::traits::{HasPublicAux, Identity, BlakeTwo256}; use primitives::testing::{Digest, Header}; + use session::OnSessionChange; impl_outer_dispatch! { #[derive(Debug, Clone, Eq, Serialize, Deserialize, PartialEq)] @@ -387,26 +392,32 @@ mod tests { } impl session::Trait for Test { type ConvertAccountIdToSessionKey = Identity; + type OnSessionChange = staking::Module; } impl staking::Trait for Test { type Balance = u64; - type DetermineContractAddress = staking::DummyContractAddressFor; type AccountIndex = u64; + type OnAccountKill = (); + } + impl timestamp::Trait for Test { + const TIMESTAMP_SET_POSITION: u32 = 0; + type Moment = u64; } impl Trait for Test { type Proposal = Proposal; } fn new_test_ext() -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::::default().build_storage(); + let mut t = system::GenesisConfig::::default().build_storage().unwrap(); t.extend(consensus::GenesisConfig::{ code: vec![], authorities: vec![], - }.build_storage()); + }.build_storage().unwrap()); t.extend(session::GenesisConfig::{ session_length: 1, //??? or 2? validators: vec![10, 20], - }.build_storage()); + broken_percent_late: 100, + }.build_storage().unwrap()); t.extend(staking::GenesisConfig::{ sessions_per_era: 1, current_era: 0, @@ -419,14 +430,16 @@ mod tests { existential_deposit: 0, transfer_fee: 0, creation_fee: 0, - contract_fee: 0, reclaim_rebate: 0, - }.build_storage()); + early_era_slash: 0, + session_reward: 0, + }.build_storage().unwrap()); t.extend(GenesisConfig::{ launch_period: 1, voting_period: 1, minimum_deposit: 1, - }.build_storage()); + }.build_storage().unwrap()); + t.extend(timestamp::GenesisConfig::::default().build_storage().unwrap()); t } @@ -481,7 +494,7 @@ mod tests { assert_eq!(Democracy::tally(r), (10, 0)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::check_new_era(); + Staking::on_session_change(true, 0); assert_eq!(Staking::era_length(), 2); }); @@ -559,19 +572,19 @@ mod tests { System::set_block_number(1); assert_ok!(Democracy::vote(&1, 0, true)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::check_new_era(); + Staking::on_session_change(true, 0); assert_eq!(Staking::bonding_duration(), 4); System::set_block_number(2); assert_ok!(Democracy::vote(&1, 1, true)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::check_new_era(); + Staking::on_session_change(true, 0); assert_eq!(Staking::bonding_duration(), 3); System::set_block_number(3); assert_ok!(Democracy::vote(&1, 2, true)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::check_new_era(); + Staking::on_session_change(true, 0); assert_eq!(Staking::bonding_duration(), 2); }); } @@ -592,7 +605,7 @@ mod tests { assert_eq!(Democracy::tally(r), (10, 0)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::check_new_era(); + Staking::on_session_change(true, 0); assert_eq!(Staking::era_length(), 2); }); @@ -607,7 +620,7 @@ mod tests { assert_ok!(Democracy::cancel_referendum(r)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::check_new_era(); + Staking::on_session_change(true, 0); assert_eq!(Staking::era_length(), 1); }); @@ -625,7 +638,7 @@ mod tests { assert_eq!(Democracy::tally(r), (0, 10)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::check_new_era(); + Staking::on_session_change(true, 0); assert_eq!(Staking::era_length(), 1); }); @@ -646,7 +659,7 @@ mod tests { assert_eq!(Democracy::tally(r), (110, 100)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::check_new_era(); + Staking::on_session_change(true, 0); assert_eq!(Staking::era_length(), 2); }); @@ -663,7 +676,7 @@ mod tests { assert_eq!(Democracy::tally(r), (60, 50)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::check_new_era(); + Staking::on_session_change(true, 0); assert_eq!(Staking::era_length(), 1); }); @@ -684,7 +697,7 @@ mod tests { assert_eq!(Democracy::tally(r), (100, 50)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::check_new_era(); + Staking::on_session_change(true, 0); assert_eq!(Staking::era_length(), 2); }); diff --git a/substrate/runtime/democracy/src/vote_threshold.rs b/substrate/runtime/democracy/src/vote_threshold.rs index 8512417b03cc8..b9976d36424a0 100644 --- a/substrate/runtime/democracy/src/vote_threshold.rs +++ b/substrate/runtime/democracy/src/vote_threshold.rs @@ -17,7 +17,7 @@ //! Voting thresholds. use primitives::traits::{Zero, IntegerSquareRoot}; -use codec::{Input, Slicable}; +use codec::{Decode, Encode, Input}; use rstd::ops::{Add, Mul, Div, Rem}; /// A means of determining if a vote is past pass threshold. @@ -32,7 +32,7 @@ pub enum VoteThreshold { SimpleMajority, } -impl Slicable for VoteThreshold { +impl Decode for VoteThreshold { fn decode(input: &mut I) -> Option { input.read_byte().and_then(|v| match v { 0 => Some(VoteThreshold::SuperMajorityApprove), @@ -41,7 +41,9 @@ impl Slicable for VoteThreshold { _ => None, }) } +} +impl Encode for VoteThreshold { fn using_encoded R>(&self, f: F) -> R { f(&[match *self { VoteThreshold::SuperMajorityApprove => 0u8, diff --git a/substrate/runtime/executive/Cargo.toml b/substrate/runtime/executive/Cargo.toml index 64e2f89d06eed..4b8307170ab94 100644 --- a/substrate/runtime/executive/Cargo.toml +++ b/substrate/runtime/executive/Cargo.toml @@ -19,6 +19,7 @@ substrate-primitives = { path = "../../primitives" } substrate-runtime-session = { path = "../session" } substrate-runtime-staking = { path = "../staking" } substrate-runtime-consensus = { path = "../consensus" } +substrate-runtime-timestamp = { path = "../timestamp" } [features] default = ["std"] diff --git a/substrate/runtime/executive/src/lib.rs b/substrate/runtime/executive/src/lib.rs index 078632c6c5957..0f01b7a7cb960 100644 --- a/substrate/runtime/executive/src/lib.rs +++ b/substrate/runtime/executive/src/lib.rs @@ -30,6 +30,8 @@ extern crate substrate_runtime_io as runtime_io; extern crate substrate_codec as codec; extern crate substrate_runtime_primitives as primitives; extern crate substrate_runtime_system as system; +#[cfg(test)] +extern crate substrate_runtime_timestamp as timestamp; #[cfg(test)] #[macro_use] @@ -52,8 +54,8 @@ use rstd::marker::PhantomData; use rstd::result; use runtime_support::StorageValue; use primitives::traits::{self, Header, Zero, One, Checkable, Applyable, CheckEqual, Executable, - MakePayment, Hashing, AuxLookup}; -use codec::Slicable; + MakePayment, Hash, AuxLookup}; +use codec::{Codec, Encode}; use system::extrinsics_root; use primitives::{ApplyOutcome, ApplyError}; @@ -80,14 +82,15 @@ pub struct Executive< >(PhantomData<(System, Block, Lookup, Payment, Finalisation)>); impl< + Address, System: system::Trait, Block: traits::Block, - Lookup: AuxLookup::Address, Target=System::AccountId>, + Lookup: AuxLookup, Payment: MakePayment, Finalisation: Executable, > Executive where - Block::Extrinsic: Checkable + Slicable, - ::Checked: Applyable + Block::Extrinsic: Checkable Result> + Codec, + Result>>::Checked: Applyable { /// Start the execution of a particular block. pub fn initialise_block(header: &System::Header) { @@ -170,7 +173,7 @@ impl< /// Actually apply an extrinsic given its `encoded_len`; this doesn't note its hash. fn apply_extrinsic_no_note_with_len(uxt: Block::Extrinsic, encoded_len: usize) -> result::Result { // Verify the signature is good. - let xt = uxt.check(Lookup::lookup).map_err(internal::ApplyError::BadSignature)?; + let xt = uxt.check_with(Lookup::lookup).map_err(internal::ApplyError::BadSignature)?; if xt.sender() != &Default::default() { // check index @@ -250,11 +253,16 @@ mod tests { } impl session::Trait for Test { type ConvertAccountIdToSessionKey = Identity; + type OnSessionChange = staking::Module; } impl staking::Trait for Test { type Balance = u64; - type DetermineContractAddress = staking::DummyContractAddressFor; type AccountIndex = u64; + type OnAccountKill = (); + } + impl timestamp::Trait for Test { + const TIMESTAMP_SET_POSITION: u32 = 0; + type Moment = u64; } type TestXt = primitives::testing::TestXt>; @@ -262,7 +270,7 @@ mod tests { #[test] fn staking_balance_transfer_dispatch_works() { - let mut t = system::GenesisConfig::::default().build_storage(); + let mut t = system::GenesisConfig::::default().build_storage().unwrap(); t.extend(staking::GenesisConfig:: { sessions_per_era: 0, current_era: 0, @@ -275,9 +283,10 @@ mod tests { existential_deposit: 0, transfer_fee: 0, creation_fee: 0, - contract_fee: 0, reclaim_rebate: 0, - }.build_storage()); + early_era_slash: 0, + session_reward: 0, + }.build_storage().unwrap()); let xt = primitives::testing::TestXt((1, 0, Call::transfer(2.into(), 69))); with_externalities(&mut t, || { Executive::initialise_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default())); @@ -288,10 +297,11 @@ mod tests { } fn new_test_ext() -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::::default().build_storage(); - t.extend(consensus::GenesisConfig::::default().build_storage()); - t.extend(session::GenesisConfig::::default().build_storage()); - t.extend(staking::GenesisConfig::::default().build_storage()); + let mut t = system::GenesisConfig::::default().build_storage().unwrap(); + t.extend(consensus::GenesisConfig::::default().build_storage().unwrap()); + t.extend(session::GenesisConfig::::default().build_storage().unwrap()); + t.extend(staking::GenesisConfig::::default().build_storage().unwrap()); + t.extend(timestamp::GenesisConfig::::default().build_storage().unwrap()); t } @@ -302,7 +312,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("4fd406d2d62a841f7e2f956b52ce9ed98111c9eb6b3a9051aa4667b470030832").into(), + state_root: hex!("8fad93b6b9e5251a2e4913598fd0d74a138c0e486eb1133ff8081b429b0c56f2").into(), extrinsics_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), digest: Digest { logs: vec![], }, }, @@ -336,7 +346,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("4fd406d2d62a841f7e2f956b52ce9ed98111c9eb6b3a9051aa4667b470030832").into(), + state_root: hex!("8fad93b6b9e5251a2e4913598fd0d74a138c0e486eb1133ff8081b429b0c56f2").into(), extrinsics_root: [0u8; 32].into(), digest: Digest { logs: vec![], }, }, @@ -344,4 +354,15 @@ mod tests { }); }); } + + #[test] + fn bad_extrinsic_not_inserted() { + let mut t = new_test_ext(); + let xt = primitives::testing::TestXt((1, 42, Call::transfer(33.into(), 69))); + with_externalities(&mut t, || { + Executive::initialise_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default())); + assert!(Executive::apply_extrinsic(xt).is_err()); + assert_eq!(>::extrinsic_index(), 0); + }); + } } diff --git a/substrate/runtime/primitives/Cargo.toml b/substrate/runtime/primitives/Cargo.toml index 185621611943f..418319fc0802c 100644 --- a/substrate/runtime/primitives/Cargo.toml +++ b/substrate/runtime/primitives/Cargo.toml @@ -13,6 +13,7 @@ substrate-primitives = { path = "../../primitives", default_features = false } substrate-runtime-std = { path = "../../runtime-std", default_features = false } substrate-runtime-io = { path = "../../runtime-io", default_features = false } substrate-runtime-support = { path = "../../runtime-support", default_features = false } +log = {version = "0.3", optional = true } [dev-dependencies] serde_json = "1.0" @@ -23,6 +24,7 @@ std = [ "num-traits/std", "serde", "serde_derive", + "log", "substrate-runtime-std/std", "substrate-runtime-io/std", "substrate-runtime-support/std", diff --git a/substrate/runtime/primitives/src/bft.rs b/substrate/runtime/primitives/src/bft.rs index 111c265233af2..12c8c141cac38 100644 --- a/substrate/runtime/primitives/src/bft.rs +++ b/substrate/runtime/primitives/src/bft.rs @@ -17,7 +17,7 @@ //! Message formats for the BFT consensus layer. use rstd::prelude::*; -use codec::{Slicable, Input}; +use codec::{Decode, Encode, Input, Output}; use substrate_primitives::{AuthorityId, Signature}; #[derive(Clone, Copy, PartialEq, Eq)] @@ -51,59 +51,58 @@ pub enum Action { AdvanceRound(u32), } -impl Slicable for Action { - fn encode(&self) -> Vec { - let mut v = Vec::new(); +impl Encode for Action { + fn encode_to(&self, dest: &mut T) { match *self { Action::Propose(ref round, ref block) => { - v.push(ActionKind::Propose as u8); - round.using_encoded(|s| v.extend(s)); - block.using_encoded(|s| v.extend(s)); + dest.push_byte(ActionKind::Propose as u8); + dest.push(round); + dest.push(block); } Action::ProposeHeader(ref round, ref hash) => { - v.push(ActionKind::ProposeHeader as u8); - round.using_encoded(|s| v.extend(s)); - hash.using_encoded(|s| v.extend(s)); + dest.push_byte(ActionKind::ProposeHeader as u8); + dest.push(round); + dest.push(hash); } Action::Prepare(ref round, ref hash) => { - v.push(ActionKind::Prepare as u8); - round.using_encoded(|s| v.extend(s)); - hash.using_encoded(|s| v.extend(s)); + dest.push_byte(ActionKind::Prepare as u8); + dest.push(round); + dest.push(hash); } Action::Commit(ref round, ref hash) => { - v.push(ActionKind::Commit as u8); - round.using_encoded(|s| v.extend(s)); - hash.using_encoded(|s| v.extend(s)); + dest.push_byte(ActionKind::Commit as u8); + dest.push(round); + dest.push(hash); } Action::AdvanceRound(ref round) => { - v.push(ActionKind::AdvanceRound as u8); - round.using_encoded(|s| v.extend(s)); + dest.push_byte(ActionKind::AdvanceRound as u8); + dest.push(round); } } - - v } +} +impl Decode for Action { fn decode(value: &mut I) -> Option { match i8::decode(value) { Some(x) if x == ActionKind::Propose as i8 => { - let (round, block) = Slicable::decode(value)?; + let (round, block) = Decode::decode(value)?; Some(Action::Propose(round, block)) } Some(x) if x == ActionKind::ProposeHeader as i8 => { - let (round, hash) = Slicable::decode(value)?; + let (round, hash) = Decode::decode(value)?; Some(Action::ProposeHeader(round, hash)) } Some(x) if x == ActionKind::Prepare as i8 => { - let (round, hash) = Slicable::decode(value)?; + let (round, hash) = Decode::decode(value)?; Some(Action::Prepare(round, hash)) } Some(x) if x == ActionKind::Commit as i8 => { - let (round, hash) = Slicable::decode(value)?; + let (round, hash) = Decode::decode(value)?; Some(Action::Commit(round, hash)) } Some(x) if x == ActionKind::AdvanceRound as i8 => { - Slicable::decode(value).map(Action::AdvanceRound) + Decode::decode(value).map(Action::AdvanceRound) } _ => None, } @@ -123,17 +122,18 @@ pub struct Message { pub action: Action, } -impl Slicable for Message { - fn encode(&self) -> Vec { - let mut v = self.parent.encode(); - self.action.using_encoded(|s| v.extend(s)); - v +impl Encode for Message { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.parent); + dest.push(&self.action); } +} +impl Decode for Message { fn decode(value: &mut I) -> Option { Some(Message { - parent: Slicable::decode(value)?, - action: Slicable::decode(value)?, + parent: Decode::decode(value)?, + action: Decode::decode(value)?, }) } } @@ -150,22 +150,20 @@ pub struct Justification { pub signatures: Vec<(AuthorityId, Signature)> } -impl Slicable for Justification { - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - self.round_number.using_encoded(|s| v.extend(s)); - self.hash.using_encoded(|s| v.extend(s)); - self.signatures.using_encoded(|s| v.extend(s)); - - v +impl Encode for Justification { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.round_number); + dest.push(&self.hash); + dest.push(&self.signatures); } +} +impl Decode for Justification { fn decode(value: &mut I) -> Option { Some(Justification { - round_number: Slicable::decode(value)?, - hash: Slicable::decode(value)?, - signatures: Slicable::decode(value)?, + round_number: Decode::decode(value)?, + hash: Decode::decode(value)?, + signatures: Decode::decode(value)?, }) } } @@ -213,35 +211,34 @@ pub struct MisbehaviorReport { pub misbehavior: MisbehaviorKind, } -impl Slicable for MisbehaviorReport { - fn encode(&self) -> Vec { - let mut v = Vec::new(); - self.parent_hash.using_encoded(|s| v.extend(s)); - self.parent_number.using_encoded(|s| v.extend(s)); - self.target.using_encoded(|s| v.extend(s)); +impl Encode for MisbehaviorReport { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.parent_hash); + dest.push(&self.parent_number); + dest.push(&self.target); match self.misbehavior { MisbehaviorKind::BftDoublePrepare(ref round, (ref h_a, ref s_a), (ref h_b, ref s_b)) => { - (MisbehaviorCode::BftDoublePrepare as i8).using_encoded(|s| v.extend(s)); - round.using_encoded(|s| v.extend(s)); - h_a.using_encoded(|s| v.extend(s)); - s_a.using_encoded(|s| v.extend(s)); - h_b.using_encoded(|s| v.extend(s)); - s_b.using_encoded(|s| v.extend(s)); + dest.push(&(MisbehaviorCode::BftDoublePrepare as i8)); + dest.push(round); + dest.push(h_a); + dest.push(s_a); + dest.push(h_b); + dest.push(s_b); } MisbehaviorKind::BftDoubleCommit(ref round, (ref h_a, ref s_a), (ref h_b, ref s_b)) => { - (MisbehaviorCode::BftDoubleCommit as i8).using_encoded(|s| v.extend(s)); - round.using_encoded(|s| v.extend(s)); - h_a.using_encoded(|s| v.extend(s)); - s_a.using_encoded(|s| v.extend(s)); - h_b.using_encoded(|s| v.extend(s)); - s_b.using_encoded(|s| v.extend(s)); + dest.push(&(MisbehaviorCode::BftDoubleCommit as i8)); + dest.push(round); + dest.push(h_a); + dest.push(s_a); + dest.push(h_b); + dest.push(s_b); } } - - v } +} +impl Decode for MisbehaviorReport { fn decode(input: &mut I) -> Option { let parent_hash = Hash::decode(input)?; let parent_number = Number::decode(input)?; diff --git a/substrate/runtime/primitives/src/generic.rs b/substrate/runtime/primitives/src/generic.rs index ba11ab310a360..1f466e2e9c82d 100644 --- a/substrate/runtime/primitives/src/generic.rs +++ b/substrate/runtime/primitives/src/generic.rs @@ -23,11 +23,12 @@ use std::fmt; use serde::{Deserialize, Deserializer}; use rstd::prelude::*; -use codec::{Slicable, Input}; +use codec::{Decode, Encode, Codec, Input, Output}; use runtime_support::AuxDispatchable; use traits::{self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay, Block as BlockT, - Header as HeaderT, Hashing as HashingT}; + Header as HeaderT, Hash as HashT}; use rstd::ops; +use bft::Justification; /// Definition of something that the external world might want to say. #[derive(PartialEq, Eq, Clone)] @@ -41,27 +42,29 @@ pub struct Extrinsic { pub function: Call, } -impl Slicable for Extrinsic where - Address: Member + Slicable + MaybeDisplay, - Index: Member + Slicable + MaybeDisplay + SimpleArithmetic, - Call: Member + Slicable +impl Decode for Extrinsic where + Address: Decode, + Index: Decode, + Call: Decode, { fn decode(input: &mut I) -> Option { Some(Extrinsic { - signed: Slicable::decode(input)?, - index: Slicable::decode(input)?, - function: Slicable::decode(input)?, + signed: Decode::decode(input)?, + index: Decode::decode(input)?, + function: Decode::decode(input)?, }) } +} - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - self.signed.using_encoded(|s| v.extend(s)); - self.index.using_encoded(|s| v.extend(s)); - self.function.using_encoded(|s| v.extend(s)); - - v +impl Encode for Extrinsic where + Address: Encode, + Index: Encode, + Call: Encode, +{ + fn encode_to(&self, dest: &mut T) { + dest.push(&self.signed); + dest.push(&self.index); + dest.push(&self.function); } } @@ -95,7 +98,7 @@ impl UncheckedExtrinsic traits::Checkable +impl traits::Checkable for UncheckedExtrinsic> where Address: Member + Default + MaybeDisplay, @@ -104,19 +107,12 @@ where Signature: traits::Verify + Eq + Default, AccountId: Member + Default + MaybeDisplay, ::MaybeUnsigned: Member, - Extrinsic: Slicable, + Extrinsic: Codec, + ThisLookup: FnOnce(Address) -> Result, { - type Address = Address; - type AccountId = AccountId; type Checked = CheckedExtrinsic; - fn sender(&self) -> &Address { - &self.extrinsic.signed - } - - fn check(self, lookup: ThisLookup) -> Result where - ThisLookup: FnOnce(Address) -> Result + Send + Sync, - { + fn check_with(self, lookup: ThisLookup) -> Result { if !self.is_signed() { Ok(CheckedExtrinsic(Extrinsic { signed: Default::default(), @@ -139,23 +135,32 @@ where } } -impl Slicable for UncheckedExtrinsic where - Signature: Slicable, - Extrinsic: Slicable, +impl Decode + for UncheckedExtrinsic +where + Signature: Decode, + Extrinsic: Decode, { fn decode(input: &mut I) -> Option { // This is a little more complicated than usual since the binary format must be compatible // with substrate's generic `Vec` type. Basically this just means accepting that there // will be a prefix of u32, which has the total number of bytes following (we don't need // to use this). - let _length_do_not_remove_me_see_above: u32 = Slicable::decode(input)?; + let _length_do_not_remove_me_see_above: u32 = Decode::decode(input)?; Some(UncheckedExtrinsic::new( - Slicable::decode(input)?, - Slicable::decode(input)? + Decode::decode(input)?, + Decode::decode(input)? )) } +} +impl Encode + for UncheckedExtrinsic +where + Signature: Encode, + Extrinsic: Encode, +{ fn encode(&self) -> Vec { let mut v = Vec::new(); @@ -163,9 +168,8 @@ impl Slicable for UncheckedExtrinsic. we'll make room for it here, then overwrite once we know the length. v.extend(&[0u8; 4]); - self.extrinsic.using_encoded(|s| v.extend(s)); - - self.signature.using_encoded(|s| v.extend(s)); + self.extrinsic.encode_to(&mut v); + self.signature.encode_to(&mut v); let length = (v.len() - 4) as u32; length.using_encoded(|s| v[0..4].copy_from_slice(s)); @@ -236,18 +240,20 @@ pub struct Digest { pub logs: Vec, } -impl Slicable for Digest where - Item: Member + Default + Slicable -{ +impl Decode for Digest { fn decode(input: &mut I) -> Option { - Some(Digest { logs: Slicable::decode(input)? }) + Some(Digest { logs: Decode::decode(input)? }) } - fn using_encoded R>(&self, f: F) -> R { - self.logs.using_encoded(f) +} + +impl Encode for Digest { + fn encode_to(&self, dest: &mut T) { + self.logs.encode_to(dest) } } + impl traits::Digest for Digest where - Item: Member + Default + Slicable + Item: Member + Default + Codec { type Item = Item; fn push(&mut self, item: Self::Item) { @@ -261,15 +267,15 @@ impl traits::Digest for Digest where #[cfg_attr(feature = "std", derive(Debug, Serialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] -pub struct Header { +pub struct Header { /// The parent hash. - pub parent_hash: ::Output, + pub parent_hash: ::Output, /// The block number. pub number: Number, /// The state trie merkle root - pub state_root: ::Output, + pub state_root: ::Output, /// The merkle root of the extrinsics. - pub extrinsics_root: ::Output, + pub extrinsics_root: ::Output, /// A chain-specific digest of data useful for light clients or referencing auxiliary data. pub digest: Digest, } @@ -290,8 +296,8 @@ struct DeserializeHeader { } #[cfg(feature = "std")] -impl From> for Header { - fn from(other: DeserializeHeader) -> Self { +impl From> for Header { + fn from(other: DeserializeHeader) -> Self { Header { parent_hash: other.parent_hash, number: other.number, @@ -303,52 +309,57 @@ impl From> for } #[cfg(feature = "std")] -impl<'a, Number: 'a, Hashing: 'a + HashingT, DigestItem: 'a> Deserialize<'a> for Header where +impl<'a, Number: 'a, Hash: 'a + HashT, DigestItem: 'a> Deserialize<'a> for Header where Number: Deserialize<'a>, - Hashing::Output: Deserialize<'a>, + Hash::Output: Deserialize<'a>, DigestItem: Deserialize<'a>, { fn deserialize>(de: D) -> Result { - DeserializeHeader::::deserialize(de).map(Into::into) + DeserializeHeader::::deserialize(de).map(Into::into) } } -impl Slicable for Header where - Number: Member + Slicable + MaybeDisplay + SimpleArithmetic + Slicable, - Hashing: HashingT, - DigestItem: Member + Default + Slicable, - Hashing::Output: Default + Member + MaybeDisplay + SimpleBitOps + Slicable, +impl Decode for Header where + Number: Decode, + Hash: HashT, + Hash::Output: Decode, + DigestItem: Decode, { fn decode(input: &mut I) -> Option { Some(Header { - parent_hash: Slicable::decode(input)?, - number: Slicable::decode(input)?, - state_root: Slicable::decode(input)?, - extrinsics_root: Slicable::decode(input)?, - digest: Slicable::decode(input)?, + parent_hash: Decode::decode(input)?, + number: Decode::decode(input)?, + state_root: Decode::decode(input)?, + extrinsics_root: Decode::decode(input)?, + digest: Decode::decode(input)?, }) } +} - fn encode(&self) -> Vec { - let mut v = Vec::new(); - self.parent_hash.using_encoded(|s| v.extend(s)); - self.number.using_encoded(|s| v.extend(s)); - self.state_root.using_encoded(|s| v.extend(s)); - self.extrinsics_root.using_encoded(|s| v.extend(s)); - self.digest.using_encoded(|s| v.extend(s)); - v +impl Encode for Header where + Number: Encode, + Hash: HashT, + Hash::Output: Encode, + DigestItem: Encode, +{ + fn encode_to(&self, dest: &mut T) { + dest.push(&self.parent_hash); + dest.push(&self.number); + dest.push(&self.state_root); + dest.push(&self.extrinsics_root); + dest.push(&self.digest); } } -impl traits::Header for Header where - Number: Member + ::rstd::hash::Hash + Copy + Slicable + MaybeDisplay + SimpleArithmetic + Slicable, - Hashing: HashingT, - DigestItem: Member + Default + Slicable, - Hashing::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Slicable, +impl traits::Header for Header where + Number: Member + ::rstd::hash::Hash + Copy + Codec + MaybeDisplay + SimpleArithmetic + Codec, + Hash: HashT, + DigestItem: Member + Default + Codec, + Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, { type Number = Number; - type Hash = ::Output; - type Hashing = Hashing; + type Hash = ::Output; + type Hashing = Hash; type Digest = Digest; fn number(&self) -> &Self::Number { &self.number } @@ -379,16 +390,16 @@ impl traits::Header for Header Header where - Number: Member + ::rstd::hash::Hash + Copy + Slicable + MaybeDisplay + SimpleArithmetic + Slicable, - Hashing: HashingT, - DigestItem: Member + Default + Slicable, - Hashing::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Slicable, +impl Header where + Number: Member + ::rstd::hash::Hash + Copy + Codec + MaybeDisplay + SimpleArithmetic + Codec, + Hash: HashT, + DigestItem: Member + Default + Codec, + Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, { /// Convenience helper for computing the hash of the header without having /// to import the trait. - pub fn hash(&self) -> Hashing::Output { - Hashing::hash_of(self) + pub fn hash(&self) -> Hash::Output { + Hash::hash_of(self) } } @@ -437,26 +448,26 @@ pub struct Block { pub extrinsics: Vec, } -impl Slicable for Block { +impl Decode for Block { fn decode(input: &mut I) -> Option { Some(Block { - header: Slicable::decode(input)?, - extrinsics: Slicable::decode(input)?, + header: Decode::decode(input)?, + extrinsics: Decode::decode(input)?, }) } +} - fn encode(&self) -> Vec { - let mut v: Vec = Vec::new(); - v.extend(self.header.encode()); - v.extend(self.extrinsics.encode()); - v +impl Encode for Block { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.header); + dest.push(&self.extrinsics); } } impl traits::Block for Block where Header: HeaderT, - Extrinsic: Member + Slicable, + Extrinsic: Member + Codec, { type Extrinsic = Extrinsic; type Header = Header; @@ -476,9 +487,41 @@ where } } +/// Abstraction over a substrate block and justification. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "std", serde(deny_unknown_fields))] +pub struct SignedBlock { + /// Full block. + pub block: Block, + /// Block header justification. + pub justification: Justification, +} + +impl Decode + for SignedBlock +{ + fn decode(input: &mut I) -> Option { + Some(SignedBlock { + block: Decode::decode(input)?, + justification: Decode::decode(input)?, + }) + } +} + +impl Encode + for SignedBlock +{ + fn encode_to(&self, dest: &mut T) { + dest.push(&self.block); + dest.push(&self.justification); + } +} + #[cfg(test)] mod tests { - use codec::Slicable; + use codec::{Decode, Encode}; use substrate_primitives::{H256, H512}; use super::{Digest, Header, UncheckedExtrinsic, Extrinsic}; diff --git a/substrate/runtime/primitives/src/lib.rs b/substrate/runtime/primitives/src/lib.rs index cdb4ab9f05c64..01db862f0da89 100644 --- a/substrate/runtime/primitives/src/lib.rs +++ b/substrate/runtime/primitives/src/lib.rs @@ -26,6 +26,10 @@ extern crate serde; #[macro_use] extern crate serde_derive; +#[cfg(feature = "std")] +#[macro_use] +extern crate log; + extern crate num_traits; extern crate integer_sqrt; extern crate substrate_runtime_std as rstd; @@ -43,6 +47,9 @@ use std::collections::HashMap; use rstd::prelude::*; use substrate_primitives::hash::{H256, H512}; +#[cfg(feature = "std")] +use substrate_primitives::hexdisplay::ascii_format; + #[cfg(feature = "std")] pub mod testing; @@ -56,27 +63,21 @@ use traits::{Verify, Lazy}; #[cfg(feature = "std")] pub type StorageMap = HashMap, Vec>; -/// A simple function allowing StorageMap to be created. -#[cfg(feature = "std")] -pub type MakeStorage = Box StorageMap>; - /// Complex storage builder stuff. #[cfg(feature = "std")] pub trait BuildStorage { - fn build_storage(self) -> StorageMap; -} - -#[cfg(feature = "std")] -impl BuildStorage for MakeStorage { - fn build_storage(mut self) -> StorageMap { - self() + fn hash(data: &[u8]) -> [u8; 16] { + let r = runtime_io::twox_128(data); + trace!(target: "build_storage", "{} <= {}", substrate_primitives::hexdisplay::HexDisplay::from(&r), ascii_format(data)); + r } + fn build_storage(self) -> Result; } #[cfg(feature = "std")] impl BuildStorage for StorageMap { - fn build_storage(self) -> StorageMap { - self + fn build_storage(self) -> Result { + Ok(self) } } @@ -92,9 +93,16 @@ impl Verify for Ed25519Signature { } } -impl codec::Slicable for Ed25519Signature { - fn decode(input: &mut I) -> Option { Some(Ed25519Signature(codec::Slicable::decode(input)?,)) } - fn using_encoded R>(&self, f: F) -> R { self.0.using_encoded(f) } +impl codec::Decode for Ed25519Signature { + fn decode(input: &mut I) -> Option { + Some(Ed25519Signature(codec::Decode::decode(input)?,)) + } +} + +impl codec::Encode for Ed25519Signature { + fn using_encoded R>(&self, f: F) -> R { + self.0.using_encoded(f) + } } impl From for Ed25519Signature { @@ -113,7 +121,7 @@ pub enum ApplyOutcome { /// Failed application (extrinsic was probably a no-op other than fees). Fail = 1, } -impl codec::Slicable for ApplyOutcome { +impl codec::Decode for ApplyOutcome { fn decode(input: &mut I) -> Option { match input.read_byte()? { x if x == ApplyOutcome::Success as u8 => Some(ApplyOutcome::Success), @@ -121,6 +129,8 @@ impl codec::Slicable for ApplyOutcome { _ => None, } } +} +impl codec::Encode for ApplyOutcome { fn using_encoded R>(&self, f: F) -> R { f(&[*self as u8]) } @@ -140,7 +150,8 @@ pub enum ApplyError { /// Sending account had too low a balance. CantPay = 3, } -impl codec::Slicable for ApplyError { + +impl codec::Decode for ApplyError { fn decode(input: &mut I) -> Option { match input.read_byte()? { x if x == ApplyError::BadSignature as u8 => Some(ApplyError::BadSignature), @@ -150,6 +161,9 @@ impl codec::Slicable for ApplyError { _ => None, } } +} + +impl codec::Encode for ApplyError { fn using_encoded R>(&self, f: F) -> R { f(&[*self as u8]) } @@ -190,9 +204,16 @@ impl Verify for MaybeUnsigned where } } -impl codec::Slicable for MaybeUnsigned { - fn decode(input: &mut I) -> Option { Some(MaybeUnsigned(codec::Slicable::decode(input)?)) } - fn using_encoded R>(&self, f: F) -> R { self.0.using_encoded(f) } +impl codec::Decode for MaybeUnsigned { + fn decode(input: &mut I) -> Option { + Some(MaybeUnsigned(codec::Decode::decode(input)?)) + } +} + +impl codec::Encode for MaybeUnsigned { + fn encode_to(&self, dest: &mut W) { + self.0.encode_to(dest) + } } impl From for MaybeUnsigned { @@ -203,7 +224,7 @@ impl From for MaybeUnsigned { /// Verify a signature on an encoded value in a lazy manner. This can be /// an optimization if the signature scheme has an "unsigned" escape hash. -pub fn verify_encoded_lazy(sig: &V, item: &T, signer: &V::Signer) -> bool { +pub fn verify_encoded_lazy(sig: &V, item: &T, signer: &V::Signer) -> bool { // The `Lazy` trait expresses something like `X: FnMut &'a T>`. // unfortunately this is a lifetime relationship that can't // be expressed without generic associated types, better unification of HRTBs in type position, @@ -241,6 +262,9 @@ macro_rules! impl_outer_config { ( pub struct $main:ident for $concrete:ident { $( $config:ident => $snake:ident, )* } ) => { __impl_outer_config_types! { $concrete $( $config $snake )* } #[cfg(any(feature = "std", test))] + #[derive(Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + #[serde(deny_unknown_fields)] pub struct $main { $( pub $snake: Option<$config>, @@ -248,14 +272,14 @@ macro_rules! impl_outer_config { } #[cfg(any(feature = "std", test))] impl $crate::BuildStorage for $main { - fn build_storage(self) -> $crate::StorageMap { + fn build_storage(self) -> ::std::result::Result<$crate::StorageMap, String> { let mut s = $crate::StorageMap::new(); $( if let Some(extra) = self.$snake { - s.extend(extra.build_storage()); + s.extend(extra.build_storage()?); } )* - s + Ok(s) } } } diff --git a/substrate/runtime/primitives/src/testing.rs b/substrate/runtime/primitives/src/testing.rs index a3d58d12e73cb..6ad72eb5fb651 100644 --- a/substrate/runtime/primitives/src/testing.rs +++ b/substrate/runtime/primitives/src/testing.rs @@ -18,7 +18,7 @@ use serde::{Serialize, de::DeserializeOwned}; use std::fmt::Debug; -use codec::{Slicable, Input}; +use codec::{Decode, Encode, Codec, Input, Output}; use runtime_support::AuxDispatchable; use traits::{self, Checkable, Applyable, BlakeTwo256}; @@ -28,14 +28,19 @@ pub use substrate_primitives::H256; pub struct Digest { pub logs: Vec, } -impl Slicable for Digest { + +impl Decode for Digest { fn decode(input: &mut I) -> Option { Vec::::decode(input).map(|logs| Digest { logs }) } +} + +impl Encode for Digest { fn using_encoded R>(&self, f: F) -> R { self.logs.using_encoded(f) } } + impl traits::Digest for Digest { type Item = u64; fn push(&mut self, item: Self::Item) { @@ -53,27 +58,29 @@ pub struct Header { pub extrinsics_root: H256, pub digest: Digest, } -impl Slicable for Header { + +impl Decode for Header { fn decode(input: &mut I) -> Option { Some(Header { - parent_hash: Slicable::decode(input)?, - number: Slicable::decode(input)?, - state_root: Slicable::decode(input)?, - extrinsics_root: Slicable::decode(input)?, - digest: Slicable::decode(input)?, + parent_hash: Decode::decode(input)?, + number: Decode::decode(input)?, + state_root: Decode::decode(input)?, + extrinsics_root: Decode::decode(input)?, + digest: Decode::decode(input)?, }) } +} - fn encode(&self) -> Vec { - let mut v = Vec::new(); - self.parent_hash.using_encoded(|s| v.extend(s)); - self.number.using_encoded(|s| v.extend(s)); - self.state_root.using_encoded(|s| v.extend(s)); - self.extrinsics_root.using_encoded(|s| v.extend(s)); - self.digest.using_encoded(|s| v.extend(s)); - v +impl Encode for Header { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.parent_hash); + dest.push(&self.number); + dest.push(&self.state_root); + dest.push(&self.extrinsics_root); + dest.push(&self.digest); } } + impl traits::Header for Header { type Number = u64; type Hashing = BlakeTwo256; @@ -109,25 +116,25 @@ impl traits::Header for Header { } #[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug)] -pub struct Block { +pub struct Block { pub header: Header, pub extrinsics: Vec, } -impl Slicable for Block { +impl Decode for Block { fn decode(input: &mut I) -> Option { Some(Block { - header: Slicable::decode(input)?, - extrinsics: Slicable::decode(input)?, + header: Decode::decode(input)?, + extrinsics: Decode::decode(input)?, }) } - fn encode(&self) -> Vec { - let mut v: Vec = Vec::new(); - v.extend(self.header.encode()); - v.extend(self.extrinsics.encode()); - v +} +impl Encode for Block { + fn encode_to(&self, dest: &mut T) { + dest.push(&self.header); + dest.push(&self.extrinsics); } } -impl traits::Block for Block { +impl traits::Block for Block { type Extrinsic = Xt; type Header = Header; type Hash =