diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f88509475..f12dd1aff 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,6 +9,7 @@ variables: RUST_BACKTRACE: "1" RUSTFLAGS: "" CARGOFLAGS: "" + CI_SERVER_NAME: "GitLab CI" cache: key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME" untracked: true @@ -92,6 +93,7 @@ linux-snap: paths: - scripts/parity_*_amd64.snap name: "stable-x86_64-unknown-snap-gnu_parity" + allow_failure: true linux-stable-debian: stage: build image: parity/rust-debian:gitlab-ci @@ -433,6 +435,7 @@ darwin: script: | export COMMIT=$(git rev-parse HEAD) export PLATFORM=x86_64-apple-darwin + rustup default stable cargo build -j 8 --features final --release #$CARGOFLAGS cargo build -j 8 --features final --release -p ethstore #$CARGOFLAGS rm -rf parity.md5 @@ -607,19 +610,6 @@ js-test: tags: - rust - rust-stable -js-test-node_8: - stage: test - image: parity/rust-debian-node_8:gitlab-ci - before_script: - - git submodule update --init --recursive - - export JS_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep ^js/ | wc -l) - - if [ $JS_FILES_MODIFIED -eq 0 ]; then echo "Skipping JS deps install since no JS files modified."; else ./js/scripts/install-deps.sh;fi - script: - - if [ $JS_FILES_MODIFIED -eq 0 ]; then echo "Skipping JS lint since no JS files modified."; else ./js/scripts/lint.sh && ./js/scripts/test.sh && ./js/scripts/build.sh; fi - tags: - - rust - - rust-stable - allow_failure: true test-rust-beta: stage: test only: diff --git a/CHANGELOG.md b/CHANGELOG.md index d109cfdb0..29f84462d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,41 @@ +## Parity [v1.6.8](https://github.com/paritytech/parity/releases/tag/v1.6.8) (2017-06-08) + +This release addresses: + +- a rare condition where quickly creating a new account was generating an account not matching the recovery phrase. +- compressed RLP strings caused wrong/empty transaction receipts on Classic network. +- blacklisting the _empty phrase_ account from UI and RPC on non-development chains. See also [this blog post](https://blog.parity.io/restoring-blank-seed-phrase/). +- canceling transactions that didn't have a condition. +- the updated Expanse fork block and chain ID. + +Full changelog: + +- Backporting to beta [#5791](https://github.com/paritytech/parity/pull/5791) + - Bump to v1.6.8 + - Update expanse json with fork at block 600000 [#5351](https://github.com/paritytech/parity/pull/5351) + - Update expanse json with fork at block 600000 + - Update exp chainID to 2 + - Bumped mio [#5763](https://github.com/paritytech/parity/pull/5763) + - Fixed default UI port for mac installer [#5782](https://github.com/paritytech/parity/pull/5782) + - Blacklist empty phrase account. [#5730](https://github.com/paritytech/parity/pull/5730) + - Update Cid/multihash/ring/tinykeccak [#5785](https://github.com/paritytech/parity/pull/5785) + - Updating ring,multihash,tiny-keccak + - Updating CID in ipfs. + - Disable compression for RLP strings [#5786](https://github.com/paritytech/parity/pull/5786) +- Beta Backports [#5789](https://github.com/paritytech/parity/pull/5789) + - Fix local transactions without condition. [#5716](https://github.com/paritytech/parity/pull/5716) + - Block invalid account name creation [#5784](https://github.com/paritytech/parity/pull/5784) + - Additional non-empty phrase check (fromNew) + - Explicit canCreate check in create (not only on UI) + - BN instance check (fixes Geth imports) + - Fixup tests after better checks + - Recover from empty phrase in dev mode [#5698](https://github.com/paritytech/parity/pull/5698) + - Add dev chain to isTest + - Fix signer + - Fix no condition transactions + - Fix case: old parity + - Fix propTypes. + ## Parity [v1.6.7](https://github.com/paritytech/parity/releases/tag/v1.6.7) (2017-05-18) This release addresses: diff --git a/Cargo.lock b/Cargo.lock index ff8b71780..cbb9237a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,6 +120,11 @@ name = "bitflags" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitflags" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "blastfig" version = "0.3.3" @@ -800,6 +805,11 @@ name = "fnv" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "foreign-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "futures" version = "0.1.11" @@ -942,7 +952,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1017,7 +1027,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jsonrpc-core" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#900b528213ffd1aaaefd29e2b99dfab892b15ab4" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d" dependencies = [ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1029,7 +1039,7 @@ dependencies = [ [[package]] name = "jsonrpc-http-server" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#900b528213ffd1aaaefd29e2b99dfab892b15ab4" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d" dependencies = [ "hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -1042,7 +1052,7 @@ dependencies = [ [[package]] name = "jsonrpc-ipc-server" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#900b528213ffd1aaaefd29e2b99dfab892b15ab4" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d" dependencies = [ "bytes 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -1055,7 +1065,7 @@ dependencies = [ [[package]] name = "jsonrpc-macros" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#900b528213ffd1aaaefd29e2b99dfab892b15ab4" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d" dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-pubsub 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -1065,7 +1075,7 @@ dependencies = [ [[package]] name = "jsonrpc-minihttp-server" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#900b528213ffd1aaaefd29e2b99dfab892b15ab4" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d" dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -1079,7 +1089,7 @@ dependencies = [ [[package]] name = "jsonrpc-pubsub" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#900b528213ffd1aaaefd29e2b99dfab892b15ab4" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d" dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1089,7 +1099,7 @@ dependencies = [ [[package]] name = "jsonrpc-server-utils" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#900b528213ffd1aaaefd29e2b99dfab892b15ab4" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d" dependencies = [ "globset 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -1101,7 +1111,7 @@ dependencies = [ [[package]] name = "jsonrpc-tcp-server" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#900b528213ffd1aaaefd29e2b99dfab892b15ab4" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d" dependencies = [ "bytes 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -1115,7 +1125,7 @@ dependencies = [ [[package]] name = "jsonrpc-ws-server" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#900b528213ffd1aaaefd29e2b99dfab892b15ab4" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d" dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -1366,13 +1376,13 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "openssl 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1499,23 +1509,25 @@ dependencies = [ [[package]] name = "openssl" -version = "0.9.3" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl-sys" -version = "0.9.3" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1791,7 +1803,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/paritytech/js-precompiled.git#52ba0075a974e89a723e04c55dd5d5b9941d9a11" +source = "git+https://github.com/paritytech/js-precompiled.git#e0cdec722ff2d32de6308638710fc4eb8a07253e" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1887,7 +1899,7 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2184,7 +2196,7 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.1" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2212,18 +2224,18 @@ dependencies = [ [[package]] name = "security-framework" -version = "0.1.9" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "security-framework-sys" -version = "0.1.9" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2857,6 +2869,7 @@ dependencies = [ "checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d" "checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23" "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 blastfig 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09640e0509d97d5cdff03a9f5daf087a8e04c735c3b113a75139634a19cfc7b2" "checksum bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f421095d2a76fc24cd3fb3f912b90df06be7689912b1bdb423caefae59c258d" "checksum bn 0.4.4 (git+https://github.com/paritytech/bn)" = "" @@ -2888,6 +2901,7 @@ dependencies = [ "checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa" "checksum flate2 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3eeb481e957304178d2e782f2da1257f1434dfecbae883bafb61ada2a9fea3bb" "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" +"checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d" "checksum futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8e51e7f9c150ba7fd4cee9df8bf6ea3dea5b63b68955ddad19ccd35b71dcfb4d" "checksum futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bb982bb25cd8fa5da6a8eb3a460354c984ff1113da82bcb4f0b0862b5795db82" "checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d" @@ -2945,7 +2959,7 @@ dependencies = [ "checksum multihash 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d14363c7695e2e5adbbb8fe139d806a19b8b13f02b9b1fb770fab0c12edaff58" "checksum nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)" = "" "checksum nanomsg-sys 0.5.0 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)" = "" -"checksum native-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aa4e52995154bb6f0b41e4379a279482c9387c1632e3798ba4e511ef8c54ee09" +"checksum native-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1e94a2fc65a44729fe969cc973da87c1052ae3f000b2cb33029f14aeb85550d5" "checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67" "checksum nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52cd74cd09beba596430cc6e3091b74007169a56246e1262f0ba451ea95117b2" "checksum nom 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6caab12c5f97aa316cb249725aa32115118e1522b445e26c257dd77cad5ffd4e" @@ -2960,8 +2974,8 @@ dependencies = [ "checksum number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "084d05f4bf60621a9ac9bde941a410df548f4de9545f06e5ee9d3aef4b97cd77" "checksum odds 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "b28c06e81b0f789122d415d6394b5fe849bde8067469f4c2980d3cdc10c78ec1" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" -"checksum openssl 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "12be61c7eaa23228316ff02c39807e4c1b1af84ba81420f19fd58dade304b25c" -"checksum openssl-sys 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d2845e841700e7b04282ceaa115407ea84e0db918ae689ad9ceb6f06fa6046bd" +"checksum openssl 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b34cd77cf91301fff3123fbd46b065c3b728b17a392835de34c397315dce5586" +"checksum openssl-sys 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e035022a50faa380bd7ccdbd184d946ce539ebdb0a358780de92a995882af97a" "checksum order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "efa535d5117d3661134dbf1719b6f0ffe06f2375843b13935db186cd094105eb" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1d06f6ee0fda786df3784a96ee3f0629f529b91cbfb7d142f6410e6bcd1ce2c" @@ -2974,7 +2988,7 @@ dependencies = [ "checksum phf_codegen 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "8af7ae7c3f75a502292b491e5cc0a1f69e3407744abe6e57e2a3b712bb82f01d" "checksum phf_generator 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "db005608fd99800c8c74106a7c894cf582055b689aa14a79462cefdcb7dc1cc3" "checksum phf_shared 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "fee4d039930e4f45123c9b15976cf93a499847b6483dc09c42ea0ec4940f2aa6" -"checksum pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8cee804ecc7eaf201a4a207241472cc870e825206f6c031e3ee2a72fa425f2fa" +"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" "checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0" "checksum pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2412f3332a07c7a2a50168988dcc184f32180a9758ad470390e5f55e089f6b6e" "checksum primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0e31b86efadeaeb1235452171a66689682783149a6249ff334a2c5d8218d00a4" @@ -3006,11 +3020,11 @@ dependencies = [ "checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" "checksum rustc_version 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e114e275f7c9b5d50bb52b28f9aac1921209f02aa6077c8b255e21eefaf8ffa" -"checksum schannel 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "167852e03fcd0029c3ddebb5afb0715b2996f6e262b2c2aceaa7cd84edd4b158" +"checksum schannel 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4e45ac5e9e4698c1c138d2972bedcd90b81fe1efeba805449d2bdd54512de5f9" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" "checksum secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f412dfa83308d893101dd59c10d6fda8283465976c28c287c5c855bf8d216bc" -"checksum security-framework 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52186fcf3b391c9f0ccdce9a2ac708f7cc81b3f89e149b34bd9279fb1b23f9fa" -"checksum security-framework-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c84067e6297c1f09514a8666d8bbc1268817ec4a6c0f30f12f6201e1f34bd2a1" +"checksum security-framework 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "42ddf098d78d0b64564b23ee6345d07573e7d10e52ad86875d89ddf5f8378a02" +"checksum security-framework-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "5bacdada57ea62022500c457c8571c17dfb5e6240b7c8eac5916ffa8c7138a55" "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d5b7638a1f03815d94e88cb3b3c08e87f0db4d683ef499d1836aaf70a45623f" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" diff --git a/Cargo.toml b/Cargo.toml index 597766a49..497078c62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,13 +72,14 @@ daemonize = "0.2" [features] default = ["ui-precompiled"] ui = [ - "dapps", + "ui-enabled", "parity-dapps/ui", ] ui-precompiled = [ - "dapps", + "ui-enabled", "parity-dapps/ui-precompiled", ] +ui-enabled = ["dapps"] dapps = ["parity-dapps"] ipc = ["ethcore/ipc", "ethsync/ipc"] jit = ["ethcore/jit"] diff --git a/README.md b/README.md index a21e6eeb9..b286055b2 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ below to build from source. ## Build dependencies -**Parity requires Rust version 1.16.0 to build** +**Parity requires Rust version 1.17.0 to build** We recommend installing Rust through [rustup](https://www.rustup.rs/). If you don't already have rustup, you can install it like this: diff --git a/ethcore/src/engines/authority_round.rs b/ethcore/src/engines/authority_round.rs index c6c41c5f8..84c1df8fc 100644 --- a/ethcore/src/engines/authority_round.rs +++ b/ethcore/src/engines/authority_round.rs @@ -168,7 +168,10 @@ fn verify_external(header: &Header, validators: &ValidatorSet, step: &Step) -> R } else { let proposer_signature = header_signature(header)?; let correct_proposer = validators.get(header.parent_hash(), header_step); - if !verify_address(&correct_proposer, &proposer_signature, &header.bare_hash())? { + let is_invalid_proposer = *header.author() != correct_proposer || + !verify_address(&correct_proposer, &proposer_signature, &header.bare_hash())?; + + if is_invalid_proposer { trace!(target: "engine", "verify_block_unordered: bad proposer for step: {}", header_step); Err(EngineError::NotProposer(Mismatch { expected: correct_proposer, found: header.author().clone() }))? } else { diff --git a/ethcore/src/engines/basic_authority.rs b/ethcore/src/engines/basic_authority.rs index 008a63424..75a4806b8 100644 --- a/ethcore/src/engines/basic_authority.rs +++ b/ethcore/src/engines/basic_authority.rs @@ -69,6 +69,10 @@ fn verify_external(header: &Header, validators: &ValidatorSet) -> Result<(), Err let sig = UntrustedRlp::new(&header.seal()[0]).as_val::()?; let signer = public_to_address(&recover(&sig.into(), &header.bare_hash())?); + if *header.author() != signer { + return Err(EngineError::NotAuthorized(*header.author()).into()) + } + match validators.contains(header.parent_hash(), &signer) { false => Err(BlockError::InvalidSeal.into()), true => Ok(()) diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index e0000f4cc..7d3963eac 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -60,7 +60,7 @@ pub const DEFAULT_BLOCKHASH_CONTRACT: &'static str = "73ffffffffffffffffffffffff /// Voting errors. #[derive(Debug)] pub enum EngineError { - /// Signature does not belong to an authority. + /// Signature or author field does not belong to an authority. NotAuthorized(Address), /// The same author issued different votes at the same step. DoubleVote(Address), diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 6e698150b..1013612e8 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -106,7 +106,7 @@ impl From for EthashParams { difficulty_bound_divisor: p.difficulty_bound_divisor.into(), difficulty_increment_divisor: p.difficulty_increment_divisor.map_or(10, Into::into), metropolis_difficulty_increment_divisor: p.metropolis_difficulty_increment_divisor.map_or(9, Into::into), - duration_limit: p.duration_limit.into(), + duration_limit: p.duration_limit.map_or(0, Into::into), block_reward: p.block_reward.into(), registrar: p.registrar.map_or_else(Address::new, Into::into), homestead_transition: p.homestead_transition.map_or(0, Into::into), diff --git a/ethcore/src/evm/evm.rs b/ethcore/src/evm/evm.rs index 46457c35f..a644fd255 100644 --- a/ethcore/src/evm/evm.rs +++ b/ethcore/src/evm/evm.rs @@ -76,7 +76,7 @@ impl From> for Error { impl From for Error { fn from(err: builtin::Error) -> Self { Error::BuiltIn(err.0) - } + } } impl fmt::Display for Error { diff --git a/ethcore/src/evm/ext.rs b/ethcore/src/evm/ext.rs index cc294dbd4..2eb99fe7c 100644 --- a/ethcore/src/evm/ext.rs +++ b/ethcore/src/evm/ext.rs @@ -131,7 +131,7 @@ pub trait Ext { fn inc_sstore_clears(&mut self); /// Prepare to trace an operation. Passthrough for the VM trace. - fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _stack_pop: usize, _gas_cost: &U256) -> bool { false } + fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: &U256) -> bool { false } /// Trace the finalised execution of a single instruction. fn trace_executed(&mut self, _gas_used: U256, _stack_push: &[U256], _mem_diff: Option<(usize, &[u8])>, _store_diff: Option<(U256, U256)>) {} diff --git a/ethcore/src/evm/instructions.rs b/ethcore/src/evm/instructions.rs index f726c9166..351517386 100644 --- a/ethcore/src/evm/instructions.rs +++ b/ethcore/src/evm/instructions.rs @@ -37,6 +37,15 @@ pub fn get_push_bytes(i: Instruction) -> usize { (i - PUSH1 + 1) as usize } +/// Returns number of bytes to read for `PUSHN` instruction or 0. +pub fn push_bytes(i: Instruction) -> usize { + if is_push(i) { + get_push_bytes(i) + } else { + 0 + } +} + #[test] fn test_get_push_bytes() { assert_eq!(get_push_bytes(PUSH1), 1); @@ -129,166 +138,169 @@ pub fn get_tier_idx (tier: GasPriceTier) -> usize { } } +/// EVM instruction information. #[derive(Copy, Clone, Default)] pub struct InstructionInfo { + /// Mnemonic name. pub name: &'static str, - pub additional: usize, + /// Number of stack arguments. pub args: usize, + /// Number of returned stack items. pub ret: usize, - pub side_effects: bool, + /// Gas price tier. pub tier: GasPriceTier } impl InstructionInfo { - pub fn new(name: &'static str, additional: usize, args: usize, ret: usize, side_effects: bool, tier: GasPriceTier) -> Self { + /// Create new instruction info. + pub fn new(name: &'static str, args: usize, ret: usize, tier: GasPriceTier) -> Self { InstructionInfo { name: name, - additional: additional, args: args, ret: ret, - side_effects: side_effects, tier: tier } } } lazy_static! { + /// Static instruction table. pub static ref INSTRUCTIONS: [InstructionInfo; 0x100] = { let mut arr = [InstructionInfo::default(); 0x100]; - arr[STOP as usize] = InstructionInfo::new("STOP", 0, 0, 0, true, GasPriceTier::Zero); - arr[ADD as usize] = InstructionInfo::new("ADD", 0, 2, 1, false, GasPriceTier::VeryLow); - arr[SUB as usize] = InstructionInfo::new("SUB", 0, 2, 1, false, GasPriceTier::VeryLow); - arr[MUL as usize] = InstructionInfo::new("MUL", 0, 2, 1, false, GasPriceTier::Low); - arr[DIV as usize] = InstructionInfo::new("DIV", 0, 2, 1, false, GasPriceTier::Low); - arr[SDIV as usize] = InstructionInfo::new("SDIV", 0, 2, 1, false, GasPriceTier::Low); - arr[MOD as usize] = InstructionInfo::new("MOD", 0, 2, 1, false, GasPriceTier::Low); - arr[SMOD as usize] = InstructionInfo::new("SMOD", 0, 2, 1, false, GasPriceTier::Low); - arr[EXP as usize] = InstructionInfo::new("EXP", 0, 2, 1, false, GasPriceTier::Special); - arr[NOT as usize] = InstructionInfo::new("NOT", 0, 1, 1, false, GasPriceTier::VeryLow); - arr[LT as usize] = InstructionInfo::new("LT", 0, 2, 1, false, GasPriceTier::VeryLow); - arr[GT as usize] = InstructionInfo::new("GT", 0, 2, 1, false, GasPriceTier::VeryLow); - arr[SLT as usize] = InstructionInfo::new("SLT", 0, 2, 1, false, GasPriceTier::VeryLow); - arr[SGT as usize] = InstructionInfo::new("SGT", 0, 2, 1, false, GasPriceTier::VeryLow); - arr[EQ as usize] = InstructionInfo::new("EQ", 0, 2, 1, false, GasPriceTier::VeryLow); - arr[ISZERO as usize] = InstructionInfo::new("ISZERO", 0, 1, 1, false, GasPriceTier::VeryLow); - arr[AND as usize] = InstructionInfo::new("AND", 0, 2, 1, false, GasPriceTier::VeryLow); - arr[OR as usize] = InstructionInfo::new("OR", 0, 2, 1, false, GasPriceTier::VeryLow); - arr[XOR as usize] = InstructionInfo::new("XOR", 0, 2, 1, false, GasPriceTier::VeryLow); - arr[BYTE as usize] = InstructionInfo::new("BYTE", 0, 2, 1, false, GasPriceTier::VeryLow); - arr[ADDMOD as usize] = InstructionInfo::new("ADDMOD", 0, 3, 1, false, GasPriceTier::Mid); - arr[MULMOD as usize] = InstructionInfo::new("MULMOD", 0, 3, 1, false, GasPriceTier::Mid); - arr[SIGNEXTEND as usize] = InstructionInfo::new("SIGNEXTEND", 0, 2, 1, false, GasPriceTier::Low); - arr[RETURNDATASIZE as usize] = InstructionInfo::new("RETURNDATASIZE", 0, 0, 1, false, GasPriceTier::Base); - arr[RETURNDATACOPY as usize] = InstructionInfo::new("RETURNDATACOPY", 0, 3, 0, true, GasPriceTier::VeryLow); - arr[SHA3 as usize] = InstructionInfo::new("SHA3", 0, 2, 1, false, GasPriceTier::Special); - arr[ADDRESS as usize] = InstructionInfo::new("ADDRESS", 0, 0, 1, false, GasPriceTier::Base); - arr[BALANCE as usize] = InstructionInfo::new("BALANCE", 0, 1, 1, false, GasPriceTier::Special); - arr[ORIGIN as usize] = InstructionInfo::new("ORIGIN", 0, 0, 1, false, GasPriceTier::Base); - arr[CALLER as usize] = InstructionInfo::new("CALLER", 0, 0, 1, false, GasPriceTier::Base); - arr[CALLVALUE as usize] = InstructionInfo::new("CALLVALUE", 0, 0, 1, false, GasPriceTier::Base); - arr[CALLDATALOAD as usize] = InstructionInfo::new("CALLDATALOAD", 0, 1, 1, false, GasPriceTier::VeryLow); - arr[CALLDATASIZE as usize] = InstructionInfo::new("CALLDATASIZE", 0, 0, 1, false, GasPriceTier::Base); - arr[CALLDATACOPY as usize] = InstructionInfo::new("CALLDATACOPY", 0, 3, 0, true, GasPriceTier::VeryLow); - arr[CODESIZE as usize] = InstructionInfo::new("CODESIZE", 0, 0, 1, false, GasPriceTier::Base); - arr[CODECOPY as usize] = InstructionInfo::new("CODECOPY", 0, 3, 0, true, GasPriceTier::VeryLow); - arr[GASPRICE as usize] = InstructionInfo::new("GASPRICE", 0, 0, 1, false, GasPriceTier::Base); - arr[EXTCODESIZE as usize] = InstructionInfo::new("EXTCODESIZE", 0, 1, 1, false, GasPriceTier::Special); - arr[EXTCODECOPY as usize] = InstructionInfo::new("EXTCODECOPY", 0, 4, 0, true, GasPriceTier::Special); - arr[BLOCKHASH as usize] = InstructionInfo::new("BLOCKHASH", 0, 1, 1, false, GasPriceTier::Ext); - arr[COINBASE as usize] = InstructionInfo::new("COINBASE", 0, 0, 1, false, GasPriceTier::Base); - arr[TIMESTAMP as usize] = InstructionInfo::new("TIMESTAMP", 0, 0, 1, false, GasPriceTier::Base); - arr[NUMBER as usize] = InstructionInfo::new("NUMBER", 0, 0, 1, false, GasPriceTier::Base); - arr[DIFFICULTY as usize] = InstructionInfo::new("DIFFICULTY", 0, 0, 1, false, GasPriceTier::Base); - arr[GASLIMIT as usize] = InstructionInfo::new("GASLIMIT", 0, 0, 1, false, GasPriceTier::Base); - arr[POP as usize] = InstructionInfo::new("POP", 0, 1, 0, false, GasPriceTier::Base); - arr[MLOAD as usize] = InstructionInfo::new("MLOAD", 0, 1, 1, false, GasPriceTier::VeryLow); - arr[MSTORE as usize] = InstructionInfo::new("MSTORE", 0, 2, 0, true, GasPriceTier::VeryLow); - arr[MSTORE8 as usize] = InstructionInfo::new("MSTORE8", 0, 2, 0, true, GasPriceTier::VeryLow); - arr[SLOAD as usize] = InstructionInfo::new("SLOAD", 0, 1, 1, false, GasPriceTier::Special); - arr[SSTORE as usize] = InstructionInfo::new("SSTORE", 0, 2, 0, true, GasPriceTier::Special); - arr[JUMP as usize] = InstructionInfo::new("JUMP", 0, 1, 0, true, GasPriceTier::Mid); - arr[JUMPI as usize] = InstructionInfo::new("JUMPI", 0, 2, 0, true, GasPriceTier::High); - arr[PC as usize] = InstructionInfo::new("PC", 0, 0, 1, false, GasPriceTier::Base); - arr[MSIZE as usize] = InstructionInfo::new("MSIZE", 0, 0, 1, false, GasPriceTier::Base); - arr[GAS as usize] = InstructionInfo::new("GAS", 0, 0, 1, false, GasPriceTier::Base); - arr[JUMPDEST as usize] = InstructionInfo::new("JUMPDEST", 0, 0, 0, true, GasPriceTier::Special); - arr[PUSH1 as usize] = InstructionInfo::new("PUSH1", 1, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH2 as usize] = InstructionInfo::new("PUSH2", 2, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH3 as usize] = InstructionInfo::new("PUSH3", 3, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH4 as usize] = InstructionInfo::new("PUSH4", 4, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH5 as usize] = InstructionInfo::new("PUSH5", 5, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH6 as usize] = InstructionInfo::new("PUSH6", 6, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH7 as usize] = InstructionInfo::new("PUSH7", 7, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH8 as usize] = InstructionInfo::new("PUSH8", 8, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH9 as usize] = InstructionInfo::new("PUSH9", 9, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH10 as usize] = InstructionInfo::new("PUSH10", 10, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH11 as usize] = InstructionInfo::new("PUSH11", 11, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH12 as usize] = InstructionInfo::new("PUSH12", 12, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH13 as usize] = InstructionInfo::new("PUSH13", 13, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH14 as usize] = InstructionInfo::new("PUSH14", 14, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH15 as usize] = InstructionInfo::new("PUSH15", 15, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH16 as usize] = InstructionInfo::new("PUSH16", 16, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH17 as usize] = InstructionInfo::new("PUSH17", 17, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH18 as usize] = InstructionInfo::new("PUSH18", 18, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH19 as usize] = InstructionInfo::new("PUSH19", 19, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH20 as usize] = InstructionInfo::new("PUSH20", 20, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH21 as usize] = InstructionInfo::new("PUSH21", 21, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH22 as usize] = InstructionInfo::new("PUSH22", 22, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH23 as usize] = InstructionInfo::new("PUSH23", 23, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH24 as usize] = InstructionInfo::new("PUSH24", 24, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH25 as usize] = InstructionInfo::new("PUSH25", 25, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH26 as usize] = InstructionInfo::new("PUSH26", 26, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH27 as usize] = InstructionInfo::new("PUSH27", 27, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH28 as usize] = InstructionInfo::new("PUSH28", 28, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH29 as usize] = InstructionInfo::new("PUSH29", 29, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH30 as usize] = InstructionInfo::new("PUSH30", 30, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH31 as usize] = InstructionInfo::new("PUSH31", 31, 0, 1, false, GasPriceTier::VeryLow); - arr[PUSH32 as usize] = InstructionInfo::new("PUSH32", 32, 0, 1, false, GasPriceTier::VeryLow); - arr[DUP1 as usize] = InstructionInfo::new("DUP1", 0, 1, 2, false, GasPriceTier::VeryLow); - arr[DUP2 as usize] = InstructionInfo::new("DUP2", 0, 2, 3, false, GasPriceTier::VeryLow); - arr[DUP3 as usize] = InstructionInfo::new("DUP3", 0, 3, 4, false, GasPriceTier::VeryLow); - arr[DUP4 as usize] = InstructionInfo::new("DUP4", 0, 4, 5, false, GasPriceTier::VeryLow); - arr[DUP5 as usize] = InstructionInfo::new("DUP5", 0, 5, 6, false, GasPriceTier::VeryLow); - arr[DUP6 as usize] = InstructionInfo::new("DUP6", 0, 6, 7, false, GasPriceTier::VeryLow); - arr[DUP7 as usize] = InstructionInfo::new("DUP7", 0, 7, 8, false, GasPriceTier::VeryLow); - arr[DUP8 as usize] = InstructionInfo::new("DUP8", 0, 8, 9, false, GasPriceTier::VeryLow); - arr[DUP9 as usize] = InstructionInfo::new("DUP9", 0, 9, 10, false, GasPriceTier::VeryLow); - arr[DUP10 as usize] = InstructionInfo::new("DUP10", 0, 10, 11, false, GasPriceTier::VeryLow); - arr[DUP11 as usize] = InstructionInfo::new("DUP11", 0, 11, 12, false, GasPriceTier::VeryLow); - arr[DUP12 as usize] = InstructionInfo::new("DUP12", 0, 12, 13, false, GasPriceTier::VeryLow); - arr[DUP13 as usize] = InstructionInfo::new("DUP13", 0, 13, 14, false, GasPriceTier::VeryLow); - arr[DUP14 as usize] = InstructionInfo::new("DUP14", 0, 14, 15, false, GasPriceTier::VeryLow); - arr[DUP15 as usize] = InstructionInfo::new("DUP15", 0, 15, 16, false, GasPriceTier::VeryLow); - arr[DUP16 as usize] = InstructionInfo::new("DUP16", 0, 16, 17, false, GasPriceTier::VeryLow); - arr[SWAP1 as usize] = InstructionInfo::new("SWAP1", 0, 2, 2, false, GasPriceTier::VeryLow); - arr[SWAP2 as usize] = InstructionInfo::new("SWAP2", 0, 3, 3, false, GasPriceTier::VeryLow); - arr[SWAP3 as usize] = InstructionInfo::new("SWAP3", 0, 4, 4, false, GasPriceTier::VeryLow); - arr[SWAP4 as usize] = InstructionInfo::new("SWAP4", 0, 5, 5, false, GasPriceTier::VeryLow); - arr[SWAP5 as usize] = InstructionInfo::new("SWAP5", 0, 6, 6, false, GasPriceTier::VeryLow); - arr[SWAP6 as usize] = InstructionInfo::new("SWAP6", 0, 7, 7, false, GasPriceTier::VeryLow); - arr[SWAP7 as usize] = InstructionInfo::new("SWAP7", 0, 8, 8, false, GasPriceTier::VeryLow); - arr[SWAP8 as usize] = InstructionInfo::new("SWAP8", 0, 9, 9, false, GasPriceTier::VeryLow); - arr[SWAP9 as usize] = InstructionInfo::new("SWAP9", 0, 10, 10, false, GasPriceTier::VeryLow); - arr[SWAP10 as usize] = InstructionInfo::new("SWAP10", 0, 11, 11, false, GasPriceTier::VeryLow); - arr[SWAP11 as usize] = InstructionInfo::new("SWAP11", 0, 12, 12, false, GasPriceTier::VeryLow); - arr[SWAP12 as usize] = InstructionInfo::new("SWAP12", 0, 13, 13, false, GasPriceTier::VeryLow); - arr[SWAP13 as usize] = InstructionInfo::new("SWAP13", 0, 14, 14, false, GasPriceTier::VeryLow); - arr[SWAP14 as usize] = InstructionInfo::new("SWAP14", 0, 15, 15, false, GasPriceTier::VeryLow); - arr[SWAP15 as usize] = InstructionInfo::new("SWAP15", 0, 16, 16, false, GasPriceTier::VeryLow); - arr[SWAP16 as usize] = InstructionInfo::new("SWAP16", 0, 17, 17, false, GasPriceTier::VeryLow); - arr[LOG0 as usize] = InstructionInfo::new("LOG0", 0, 2, 0, true, GasPriceTier::Special); - arr[LOG1 as usize] = InstructionInfo::new("LOG1", 0, 3, 0, true, GasPriceTier::Special); - arr[LOG2 as usize] = InstructionInfo::new("LOG2", 0, 4, 0, true, GasPriceTier::Special); - arr[LOG3 as usize] = InstructionInfo::new("LOG3", 0, 5, 0, true, GasPriceTier::Special); - arr[LOG4 as usize] = InstructionInfo::new("LOG4", 0, 6, 0, true, GasPriceTier::Special); - arr[CREATE as usize] = InstructionInfo::new("CREATE", 0, 3, 1, true, GasPriceTier::Special); - arr[CALL as usize] = InstructionInfo::new("CALL", 0, 7, 1, true, GasPriceTier::Special); - arr[CALLCODE as usize] = InstructionInfo::new("CALLCODE", 0, 7, 1, true, GasPriceTier::Special); - arr[RETURN as usize] = InstructionInfo::new("RETURN", 0, 2, 0, true, GasPriceTier::Zero); - arr[DELEGATECALL as usize] = InstructionInfo::new("DELEGATECALL", 0, 6, 1, true, GasPriceTier::Special); - arr[SUICIDE as usize] = InstructionInfo::new("SUICIDE", 0, 1, 0, true, GasPriceTier::Special); - arr[CREATE2 as usize] = InstructionInfo::new("CREATE2", 0, 3, 1, true, GasPriceTier::Special); - arr[REVERT as usize] = InstructionInfo::new("REVERT", 0, 2, 0, true, GasPriceTier::Zero); + arr[STOP as usize] = InstructionInfo::new("STOP", 0, 0, GasPriceTier::Zero); + arr[ADD as usize] = InstructionInfo::new("ADD", 2, 1, GasPriceTier::VeryLow); + arr[SUB as usize] = InstructionInfo::new("SUB", 2, 1, GasPriceTier::VeryLow); + arr[MUL as usize] = InstructionInfo::new("MUL", 2, 1, GasPriceTier::Low); + arr[DIV as usize] = InstructionInfo::new("DIV", 2, 1, GasPriceTier::Low); + arr[SDIV as usize] = InstructionInfo::new("SDIV", 2, 1, GasPriceTier::Low); + arr[MOD as usize] = InstructionInfo::new("MOD", 2, 1, GasPriceTier::Low); + arr[SMOD as usize] = InstructionInfo::new("SMOD", 2, 1, GasPriceTier::Low); + arr[EXP as usize] = InstructionInfo::new("EXP", 2, 1, GasPriceTier::Special); + arr[NOT as usize] = InstructionInfo::new("NOT", 1, 1, GasPriceTier::VeryLow); + arr[LT as usize] = InstructionInfo::new("LT", 2, 1, GasPriceTier::VeryLow); + arr[GT as usize] = InstructionInfo::new("GT", 2, 1, GasPriceTier::VeryLow); + arr[SLT as usize] = InstructionInfo::new("SLT", 2, 1, GasPriceTier::VeryLow); + arr[SGT as usize] = InstructionInfo::new("SGT", 2, 1, GasPriceTier::VeryLow); + arr[EQ as usize] = InstructionInfo::new("EQ", 2, 1, GasPriceTier::VeryLow); + arr[ISZERO as usize] = InstructionInfo::new("ISZERO", 1, 1, GasPriceTier::VeryLow); + arr[AND as usize] = InstructionInfo::new("AND", 2, 1, GasPriceTier::VeryLow); + arr[OR as usize] = InstructionInfo::new("OR", 2, 1, GasPriceTier::VeryLow); + arr[XOR as usize] = InstructionInfo::new("XOR", 2, 1, GasPriceTier::VeryLow); + arr[BYTE as usize] = InstructionInfo::new("BYTE", 2, 1, GasPriceTier::VeryLow); + arr[ADDMOD as usize] = InstructionInfo::new("ADDMOD", 3, 1, GasPriceTier::Mid); + arr[MULMOD as usize] = InstructionInfo::new("MULMOD", 3, 1, GasPriceTier::Mid); + arr[SIGNEXTEND as usize] = InstructionInfo::new("SIGNEXTEND", 2, 1, GasPriceTier::Low); + arr[RETURNDATASIZE as usize] = InstructionInfo::new("RETURNDATASIZE", 0, 1, GasPriceTier::Base); + arr[RETURNDATACOPY as usize] = InstructionInfo::new("RETURNDATACOPY", 3, 0, GasPriceTier::VeryLow); + arr[SHA3 as usize] = InstructionInfo::new("SHA3", 2, 1, GasPriceTier::Special); + arr[ADDRESS as usize] = InstructionInfo::new("ADDRESS", 0, 1, GasPriceTier::Base); + arr[BALANCE as usize] = InstructionInfo::new("BALANCE", 1, 1, GasPriceTier::Special); + arr[ORIGIN as usize] = InstructionInfo::new("ORIGIN", 0, 1, GasPriceTier::Base); + arr[CALLER as usize] = InstructionInfo::new("CALLER", 0, 1, GasPriceTier::Base); + arr[CALLVALUE as usize] = InstructionInfo::new("CALLVALUE", 0, 1, GasPriceTier::Base); + arr[CALLDATALOAD as usize] = InstructionInfo::new("CALLDATALOAD", 1, 1, GasPriceTier::VeryLow); + arr[CALLDATASIZE as usize] = InstructionInfo::new("CALLDATASIZE", 0, 1, GasPriceTier::Base); + arr[CALLDATACOPY as usize] = InstructionInfo::new("CALLDATACOPY", 3, 0, GasPriceTier::VeryLow); + arr[CODESIZE as usize] = InstructionInfo::new("CODESIZE", 0, 1, GasPriceTier::Base); + arr[CODECOPY as usize] = InstructionInfo::new("CODECOPY", 3, 0, GasPriceTier::VeryLow); + arr[GASPRICE as usize] = InstructionInfo::new("GASPRICE", 0, 1, GasPriceTier::Base); + arr[EXTCODESIZE as usize] = InstructionInfo::new("EXTCODESIZE", 1, 1, GasPriceTier::Special); + arr[EXTCODECOPY as usize] = InstructionInfo::new("EXTCODECOPY", 4, 0, GasPriceTier::Special); + arr[BLOCKHASH as usize] = InstructionInfo::new("BLOCKHASH", 1, 1, GasPriceTier::Ext); + arr[COINBASE as usize] = InstructionInfo::new("COINBASE", 0, 1, GasPriceTier::Base); + arr[TIMESTAMP as usize] = InstructionInfo::new("TIMESTAMP", 0, 1, GasPriceTier::Base); + arr[NUMBER as usize] = InstructionInfo::new("NUMBER", 0, 1, GasPriceTier::Base); + arr[DIFFICULTY as usize] = InstructionInfo::new("DIFFICULTY", 0, 1, GasPriceTier::Base); + arr[GASLIMIT as usize] = InstructionInfo::new("GASLIMIT", 0, 1, GasPriceTier::Base); + arr[POP as usize] = InstructionInfo::new("POP", 1, 0, GasPriceTier::Base); + arr[MLOAD as usize] = InstructionInfo::new("MLOAD", 1, 1, GasPriceTier::VeryLow); + arr[MSTORE as usize] = InstructionInfo::new("MSTORE", 2, 0, GasPriceTier::VeryLow); + arr[MSTORE8 as usize] = InstructionInfo::new("MSTORE8", 2, 0, GasPriceTier::VeryLow); + arr[SLOAD as usize] = InstructionInfo::new("SLOAD", 1, 1, GasPriceTier::Special); + arr[SSTORE as usize] = InstructionInfo::new("SSTORE", 2, 0, GasPriceTier::Special); + arr[JUMP as usize] = InstructionInfo::new("JUMP", 1, 0, GasPriceTier::Mid); + arr[JUMPI as usize] = InstructionInfo::new("JUMPI", 2, 0, GasPriceTier::High); + arr[PC as usize] = InstructionInfo::new("PC", 0, 1, GasPriceTier::Base); + arr[MSIZE as usize] = InstructionInfo::new("MSIZE", 0, 1, GasPriceTier::Base); + arr[GAS as usize] = InstructionInfo::new("GAS", 0, 1, GasPriceTier::Base); + arr[JUMPDEST as usize] = InstructionInfo::new("JUMPDEST", 0, 0, GasPriceTier::Special); + arr[PUSH1 as usize] = InstructionInfo::new("PUSH1", 0, 1, GasPriceTier::VeryLow); + arr[PUSH2 as usize] = InstructionInfo::new("PUSH2", 0, 1, GasPriceTier::VeryLow); + arr[PUSH3 as usize] = InstructionInfo::new("PUSH3", 0, 1, GasPriceTier::VeryLow); + arr[PUSH4 as usize] = InstructionInfo::new("PUSH4", 0, 1, GasPriceTier::VeryLow); + arr[PUSH5 as usize] = InstructionInfo::new("PUSH5", 0, 1, GasPriceTier::VeryLow); + arr[PUSH6 as usize] = InstructionInfo::new("PUSH6", 0, 1, GasPriceTier::VeryLow); + arr[PUSH7 as usize] = InstructionInfo::new("PUSH7", 0, 1, GasPriceTier::VeryLow); + arr[PUSH8 as usize] = InstructionInfo::new("PUSH8", 0, 1, GasPriceTier::VeryLow); + arr[PUSH9 as usize] = InstructionInfo::new("PUSH9", 0, 1, GasPriceTier::VeryLow); + arr[PUSH10 as usize] = InstructionInfo::new("PUSH10", 0, 1, GasPriceTier::VeryLow); + arr[PUSH11 as usize] = InstructionInfo::new("PUSH11", 0, 1, GasPriceTier::VeryLow); + arr[PUSH12 as usize] = InstructionInfo::new("PUSH12", 0, 1, GasPriceTier::VeryLow); + arr[PUSH13 as usize] = InstructionInfo::new("PUSH13", 0, 1, GasPriceTier::VeryLow); + arr[PUSH14 as usize] = InstructionInfo::new("PUSH14", 0, 1, GasPriceTier::VeryLow); + arr[PUSH15 as usize] = InstructionInfo::new("PUSH15", 0, 1, GasPriceTier::VeryLow); + arr[PUSH16 as usize] = InstructionInfo::new("PUSH16", 0, 1, GasPriceTier::VeryLow); + arr[PUSH17 as usize] = InstructionInfo::new("PUSH17", 0, 1, GasPriceTier::VeryLow); + arr[PUSH18 as usize] = InstructionInfo::new("PUSH18", 0, 1, GasPriceTier::VeryLow); + arr[PUSH19 as usize] = InstructionInfo::new("PUSH19", 0, 1, GasPriceTier::VeryLow); + arr[PUSH20 as usize] = InstructionInfo::new("PUSH20", 0, 1, GasPriceTier::VeryLow); + arr[PUSH21 as usize] = InstructionInfo::new("PUSH21", 0, 1, GasPriceTier::VeryLow); + arr[PUSH22 as usize] = InstructionInfo::new("PUSH22", 0, 1, GasPriceTier::VeryLow); + arr[PUSH23 as usize] = InstructionInfo::new("PUSH23", 0, 1, GasPriceTier::VeryLow); + arr[PUSH24 as usize] = InstructionInfo::new("PUSH24", 0, 1, GasPriceTier::VeryLow); + arr[PUSH25 as usize] = InstructionInfo::new("PUSH25", 0, 1, GasPriceTier::VeryLow); + arr[PUSH26 as usize] = InstructionInfo::new("PUSH26", 0, 1, GasPriceTier::VeryLow); + arr[PUSH27 as usize] = InstructionInfo::new("PUSH27", 0, 1, GasPriceTier::VeryLow); + arr[PUSH28 as usize] = InstructionInfo::new("PUSH28", 0, 1, GasPriceTier::VeryLow); + arr[PUSH29 as usize] = InstructionInfo::new("PUSH29", 0, 1, GasPriceTier::VeryLow); + arr[PUSH30 as usize] = InstructionInfo::new("PUSH30", 0, 1, GasPriceTier::VeryLow); + arr[PUSH31 as usize] = InstructionInfo::new("PUSH31", 0, 1, GasPriceTier::VeryLow); + arr[PUSH32 as usize] = InstructionInfo::new("PUSH32", 0, 1, GasPriceTier::VeryLow); + arr[DUP1 as usize] = InstructionInfo::new("DUP1", 1, 2, GasPriceTier::VeryLow); + arr[DUP2 as usize] = InstructionInfo::new("DUP2", 2, 3, GasPriceTier::VeryLow); + arr[DUP3 as usize] = InstructionInfo::new("DUP3", 3, 4, GasPriceTier::VeryLow); + arr[DUP4 as usize] = InstructionInfo::new("DUP4", 4, 5, GasPriceTier::VeryLow); + arr[DUP5 as usize] = InstructionInfo::new("DUP5", 5, 6, GasPriceTier::VeryLow); + arr[DUP6 as usize] = InstructionInfo::new("DUP6", 6, 7, GasPriceTier::VeryLow); + arr[DUP7 as usize] = InstructionInfo::new("DUP7", 7, 8, GasPriceTier::VeryLow); + arr[DUP8 as usize] = InstructionInfo::new("DUP8", 8, 9, GasPriceTier::VeryLow); + arr[DUP9 as usize] = InstructionInfo::new("DUP9", 9, 10, GasPriceTier::VeryLow); + arr[DUP10 as usize] = InstructionInfo::new("DUP10", 10, 11, GasPriceTier::VeryLow); + arr[DUP11 as usize] = InstructionInfo::new("DUP11", 11, 12, GasPriceTier::VeryLow); + arr[DUP12 as usize] = InstructionInfo::new("DUP12", 12, 13, GasPriceTier::VeryLow); + arr[DUP13 as usize] = InstructionInfo::new("DUP13", 13, 14, GasPriceTier::VeryLow); + arr[DUP14 as usize] = InstructionInfo::new("DUP14", 14, 15, GasPriceTier::VeryLow); + arr[DUP15 as usize] = InstructionInfo::new("DUP15", 15, 16, GasPriceTier::VeryLow); + arr[DUP16 as usize] = InstructionInfo::new("DUP16", 16, 17, GasPriceTier::VeryLow); + arr[SWAP1 as usize] = InstructionInfo::new("SWAP1", 2, 2, GasPriceTier::VeryLow); + arr[SWAP2 as usize] = InstructionInfo::new("SWAP2", 3, 3, GasPriceTier::VeryLow); + arr[SWAP3 as usize] = InstructionInfo::new("SWAP3", 4, 4, GasPriceTier::VeryLow); + arr[SWAP4 as usize] = InstructionInfo::new("SWAP4", 5, 5, GasPriceTier::VeryLow); + arr[SWAP5 as usize] = InstructionInfo::new("SWAP5", 6, 6, GasPriceTier::VeryLow); + arr[SWAP6 as usize] = InstructionInfo::new("SWAP6", 7, 7, GasPriceTier::VeryLow); + arr[SWAP7 as usize] = InstructionInfo::new("SWAP7", 8, 8, GasPriceTier::VeryLow); + arr[SWAP8 as usize] = InstructionInfo::new("SWAP8", 9, 9, GasPriceTier::VeryLow); + arr[SWAP9 as usize] = InstructionInfo::new("SWAP9", 10, 10, GasPriceTier::VeryLow); + arr[SWAP10 as usize] = InstructionInfo::new("SWAP10", 11, 11, GasPriceTier::VeryLow); + arr[SWAP11 as usize] = InstructionInfo::new("SWAP11", 12, 12, GasPriceTier::VeryLow); + arr[SWAP12 as usize] = InstructionInfo::new("SWAP12", 13, 13, GasPriceTier::VeryLow); + arr[SWAP13 as usize] = InstructionInfo::new("SWAP13", 14, 14, GasPriceTier::VeryLow); + arr[SWAP14 as usize] = InstructionInfo::new("SWAP14", 15, 15, GasPriceTier::VeryLow); + arr[SWAP15 as usize] = InstructionInfo::new("SWAP15", 16, 16, GasPriceTier::VeryLow); + arr[SWAP16 as usize] = InstructionInfo::new("SWAP16", 17, 17, GasPriceTier::VeryLow); + arr[LOG0 as usize] = InstructionInfo::new("LOG0", 2, 0, GasPriceTier::Special); + arr[LOG1 as usize] = InstructionInfo::new("LOG1", 3, 0, GasPriceTier::Special); + arr[LOG2 as usize] = InstructionInfo::new("LOG2", 4, 0, GasPriceTier::Special); + arr[LOG3 as usize] = InstructionInfo::new("LOG3", 5, 0, GasPriceTier::Special); + arr[LOG4 as usize] = InstructionInfo::new("LOG4", 6, 0, GasPriceTier::Special); + arr[CREATE as usize] = InstructionInfo::new("CREATE", 3, 1, GasPriceTier::Special); + arr[CALL as usize] = InstructionInfo::new("CALL", 7, 1, GasPriceTier::Special); + arr[CALLCODE as usize] = InstructionInfo::new("CALLCODE", 7, 1, GasPriceTier::Special); + arr[RETURN as usize] = InstructionInfo::new("RETURN", 2, 0, GasPriceTier::Zero); + arr[DELEGATECALL as usize] = InstructionInfo::new("DELEGATECALL", 6, 1, GasPriceTier::Special); + arr[SUICIDE as usize] = InstructionInfo::new("SUICIDE", 1, 0, GasPriceTier::Special); + arr[CREATE2 as usize] = InstructionInfo::new("CREATE2", 3, 1, GasPriceTier::Special); + arr[REVERT as usize] = InstructionInfo::new("REVERT", 2, 0, GasPriceTier::Zero); arr }; } diff --git a/ethcore/src/evm/interpreter/memory.rs b/ethcore/src/evm/interpreter/memory.rs index 555e4bc30..00f7a7d79 100644 --- a/ethcore/src/evm/interpreter/memory.rs +++ b/ethcore/src/evm/interpreter/memory.rs @@ -89,9 +89,10 @@ impl Memory for Vec { } fn write_slice(&mut self, offset: U256, slice: &[u8]) { - let off = offset.low_u64() as usize; - - self[off..off+slice.len()].copy_from_slice(slice); + if !slice.is_empty() { + let off = offset.low_u64() as usize; + self[off..off+slice.len()].copy_from_slice(slice); + } } fn write(&mut self, offset: U256, value: U256) { @@ -183,5 +184,12 @@ mod tests { assert_eq!(mem.read_slice(U256::from(0), U256::from(7)), "a67890g".as_bytes()); } + + // write empty slice out of bounds + { + let slice = []; + mem.write_slice(U256::from(0x1000), &slice); + assert_eq!(mem.size(), 32); + } } } diff --git a/ethcore/src/evm/interpreter/mod.rs b/ethcore/src/evm/interpreter/mod.rs index 8b8b739e0..32d010daf 100644 --- a/ethcore/src/evm/interpreter/mod.rs +++ b/ethcore/src/evm/interpreter/mod.rs @@ -130,7 +130,7 @@ impl evm::Evm for Interpreter { // Calculate gas cost let requirements = gasometer.requirements(ext, instruction, info, &stack, self.mem.size())?; // TODO: make compile-time removable if too much of a performance hit. - let trace_executed = ext.trace_prepare_execute(reader.position - 1, instruction, info.args, &requirements.gas_cost.as_u256()); + let trace_executed = ext.trace_prepare_execute(reader.position - 1, instruction, &requirements.gas_cost.as_u256()); gasometer.verify_gas(&requirements.gas_cost)?; self.mem.expand(requirements.memory_required_size); diff --git a/ethcore/src/evm/mod.rs b/ethcore/src/evm/mod.rs index 1ac05ce61..91b44a543 100644 --- a/ethcore/src/evm/mod.rs +++ b/ethcore/src/evm/mod.rs @@ -35,6 +35,7 @@ mod benches; pub use self::evm::{Evm, Error, Finalize, FinalizationResult, GasLeft, Result, CostType, ReturnData}; pub use self::ext::{Ext, ContractCreateResult, MessageCallResult, CreateContractAddress}; +pub use self::instructions::{InstructionInfo, INSTRUCTIONS, push_bytes}; pub use self::vmtype::VMType; pub use self::factory::Factory; pub use self::schedule::Schedule; diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index b5b5fb959..4dbee6bde 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -357,7 +357,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return(output, trace_output.as_mut()), &mut subtracer, &mut subvmtracer) }; - vm_tracer.done_subtrace(subvmtracer); + vm_tracer.done_subtrace(subvmtracer, res.is_ok()); trace!(target: "executive", "res={:?}", res); @@ -432,7 +432,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::InitContract(trace_output.as_mut()), &mut subtracer, &mut subvmtracer) }; - vm_tracer.done_subtrace(subvmtracer); + vm_tracer.done_subtrace(subvmtracer, res.is_ok()); match res { Ok(ref res) => tracer.trace_create( diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index 22a80a3ba..d0895306e 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -361,8 +361,8 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> self.substate.sstore_clears_count = self.substate.sstore_clears_count + U256::one(); } - fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, stack_pop: usize, gas_cost: &U256) -> bool { - self.vm_tracer.trace_prepare_execute(pc, instruction, stack_pop, gas_cost) + fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, gas_cost: &U256) -> bool { + self.vm_tracer.trace_prepare_execute(pc, instruction, gas_cost) } fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem_diff: Option<(usize, &[u8])>, store_diff: Option<(U256, U256)>) { diff --git a/ethcore/src/trace/executive_tracer.rs b/ethcore/src/trace/executive_tracer.rs index 6cca0020c..fb2f91a2f 100644 --- a/ethcore/src/trace/executive_tracer.rs +++ b/ethcore/src/trace/executive_tracer.rs @@ -192,7 +192,7 @@ impl ExecutiveVMTracer { } impl VMTracer for ExecutiveVMTracer { - fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, _stack_pop: usize, gas_cost: &U256) -> bool { + fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, gas_cost: &U256) -> bool { self.data.operations.push(VMOperation { pc: pc, instruction: instruction, @@ -221,7 +221,7 @@ impl VMTracer for ExecutiveVMTracer { }} } - fn done_subtrace(&mut self, sub: Self) { + fn done_subtrace(&mut self, sub: Self, _is_successful: bool) { self.data.subs.push(sub.data); } diff --git a/ethcore/src/trace/mod.rs b/ethcore/src/trace/mod.rs index 6cb9e47e9..a7eea218b 100644 --- a/ethcore/src/trace/mod.rs +++ b/ethcore/src/trace/mod.rs @@ -89,7 +89,7 @@ pub trait Tracer: Send { pub trait VMTracer: Send { /// Trace the preparation to execute a single instruction. /// @returns true if `trace_executed` should be called. - fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _stack_pop: usize, _gas_cost: &U256) -> bool { false } + fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: &U256) -> bool { false } /// Trace the finalised execution of a single instruction. fn trace_executed(&mut self, _gas_used: U256, _stack_push: &[U256], _mem_diff: Option<(usize, &[u8])>, _store_diff: Option<(U256, U256)>) {} @@ -98,7 +98,7 @@ pub trait VMTracer: Send { fn prepare_subtrace(&self, code: &[u8]) -> Self where Self: Sized; /// Finalize subtracer. - fn done_subtrace(&mut self, sub: Self) where Self: Sized; + fn done_subtrace(&mut self, sub: Self, is_successful: bool) where Self: Sized; /// Consumes self and returns the VM trace. fn drain(self) -> Option; diff --git a/ethcore/src/trace/noop_tracer.rs b/ethcore/src/trace/noop_tracer.rs index d69ed9a16..d8502a4a8 100644 --- a/ethcore/src/trace/noop_tracer.rs +++ b/ethcore/src/trace/noop_tracer.rs @@ -72,7 +72,7 @@ pub struct NoopVMTracer; impl VMTracer for NoopVMTracer { /// Trace the preparation to execute a single instruction. - fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _stack_pop: usize, _gas_cost: &U256) -> bool { false } + fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: &U256) -> bool { false } /// Trace the finalised execution of a single instruction. fn trace_executed(&mut self, _gas_used: U256, _stack_push: &[U256], _mem_diff: Option<(usize, &[u8])>, _store_diff: Option<(U256, U256)>) {} @@ -81,7 +81,7 @@ impl VMTracer for NoopVMTracer { fn prepare_subtrace(&self, _code: &[u8]) -> Self { NoopVMTracer } /// Spawn subtracer which will be used to trace deeper levels of execution. - fn done_subtrace(&mut self, _sub: Self) {} + fn done_subtrace(&mut self, _sub: Self, _is_successful: bool) {} /// Consumes self and returns all VM traces. fn drain(self) -> Option { None } diff --git a/evmbin/src/display/json.rs b/evmbin/src/display/json.rs index 604d3d3c3..1791640d6 100644 --- a/evmbin/src/display/json.rs +++ b/evmbin/src/display/json.rs @@ -16,7 +16,7 @@ //! JSON VM output. -use ethcore::trace; +use ethcore::{evm, trace}; use std::collections::HashMap; use util::{U256, H256, ToPretty}; @@ -26,11 +26,14 @@ use vm; /// JSON formatting informant. #[derive(Default)] pub struct Informant { + code: Vec, depth: usize, pc: usize, instruction: u8, + name: &'static str, gas_cost: U256, gas_used: U256, + stack_pop: usize, stack: Vec, memory: Vec, storage: HashMap, @@ -55,38 +58,44 @@ impl Informant { } impl vm::Informant for Informant { + fn set_gas(&mut self, gas: U256) { + self.gas_used = gas; + } + fn finish(&mut self, result: Result) { match result { Ok(success) => println!( - "{{\"output\":\"0x{output}\",\"gasUsed\":\"{gas:x}\",\"time\":\"{time}\"}}", + "{{\"output\":\"0x{output}\",\"gasUsed\":\"{gas:x}\",\"time\":{time}}}", output = success.output.to_hex(), gas = success.gas_used, - time = display::format_time(&success.time), + time = display::as_micros(&success.time), ), Err(failure) => println!( - "{{\"error\":\"{error}\",\"time\":\"{time}\"}}", + "{{\"error\":\"{error}\",\"gasUsed\":\"{gas:x}\",\"time\":{time}}}", error = failure.error, - time = display::format_time(&failure.time), + gas = failure.gas_used, + time = display::as_micros(&failure.time), ), } } } impl trace::VMTracer for Informant { - fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, stack_pop: usize, gas_cost: &U256) -> bool { + fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, gas_cost: &U256) -> bool { self.pc = pc; self.instruction = instruction; self.gas_cost = *gas_cost; - let len = self.stack.len(); - self.stack.truncate(len - stack_pop); true } fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem_diff: Option<(usize, &[u8])>, store_diff: Option<(U256, U256)>) { + let info = evm::INSTRUCTIONS[self.instruction as usize]; + println!( - "{{\"pc\":{pc},\"op\":{op},\"gas\":{gas},\"gasCost\":{gas_cost},\"memory\":{memory},\"stack\":{stack},\"storage\":{storage},\"depth\":{depth}}}", + "{{\"pc\":{pc},\"op\":{op},\"opName\":\"{name}\",\"gas\":{gas},\"gasCost\":{gas_cost},\"memory\":{memory},\"stack\":{stack},\"storage\":{storage},\"depth\":{depth}}}", pc = self.pc, op = self.instruction, + name = info.name, gas = display::u256_as_str(&(gas_used + self.gas_cost)), gas_cost = display::u256_as_str(&self.gas_cost), memory = self.memory(), @@ -96,6 +105,9 @@ impl trace::VMTracer for Informant { ); self.gas_used = gas_used; + + let len = self.stack.len(); + self.stack.truncate(len - info.args); self.stack.extend_from_slice(stack_push); if let Some((pos, data)) = mem_diff { @@ -107,17 +119,25 @@ impl trace::VMTracer for Informant { } } - fn prepare_subtrace(&self, _code: &[u8]) -> Self where Self: Sized { + fn prepare_subtrace(&self, code: &[u8]) -> Self where Self: Sized { let mut vm = Informant::default(); vm.depth = self.depth + 1; + vm.code = code.to_vec(); + vm.gas_used = self.gas_used; vm } - fn done_subtrace(&mut self, mut sub: Self) where Self: Sized { + fn done_subtrace(&mut self, mut sub: Self, is_successful: bool) where Self: Sized { if sub.depth == 1 { // print last line with final state: - sub.pc += 1; - sub.instruction = 0; + if is_successful { + sub.pc += 1; + sub.instruction = 0; + } else { + let push_bytes = evm::push_bytes(sub.instruction); + sub.pc += if push_bytes > 0 { push_bytes + 1 } else { 0 }; + sub.instruction = if sub.pc < sub.code.len() { sub.code[sub.pc] } else { 0 }; + } sub.gas_cost = 0.into(); let gas_used = sub.gas_used; trace::VMTracer::trace_executed(&mut sub, gas_used, &[], None, None); diff --git a/evmbin/src/display/mod.rs b/evmbin/src/display/mod.rs index 2d6179859..2c25fe721 100644 --- a/evmbin/src/display/mod.rs +++ b/evmbin/src/display/mod.rs @@ -27,6 +27,11 @@ pub fn format_time(time: &Duration) -> String { format!("{}.{:.9}s", time.as_secs(), time.subsec_nanos()) } +/// Formats the time as microseconds. +pub fn as_micros(time: &Duration) -> u64 { + time.as_secs() * 1_000_000 + time.subsec_nanos() as u64 / 1_000 +} + /// Converts U256 into string. /// TODO Overcomes: https://github.com/paritytech/bigint/issues/13 pub fn u256_as_str(v: &U256) -> String { diff --git a/evmbin/src/display/simple.rs b/evmbin/src/display/simple.rs index 5dcefd92c..46a57bab0 100644 --- a/evmbin/src/display/simple.rs +++ b/evmbin/src/display/simple.rs @@ -44,6 +44,6 @@ impl vm::Informant for Informant { impl trace::VMTracer for Informant { fn prepare_subtrace(&self, _code: &[u8]) -> Self where Self: Sized { Default::default() } - fn done_subtrace(&mut self, _sub: Self) where Self: Sized {} + fn done_subtrace(&mut self, _sub: Self, _is_successful: bool) where Self: Sized {} fn drain(self) -> Option { None } } diff --git a/evmbin/src/main.rs b/evmbin/src/main.rs index 6f50249e0..a7d90b90b 100644 --- a/evmbin/src/main.rs +++ b/evmbin/src/main.rs @@ -81,6 +81,7 @@ fn run(args: Args, mut informant: T) { params.code = Some(Arc::new(code)); params.data = data; + informant.set_gas(gas); let result = vm::run(&mut informant, spec, params); informant.finish(result); } diff --git a/evmbin/src/vm.rs b/evmbin/src/vm.rs index 6e45c5dc8..51a8425a1 100644 --- a/evmbin/src/vm.rs +++ b/evmbin/src/vm.rs @@ -24,6 +24,8 @@ use ethcore::action_params::ActionParams; /// VM execution informant pub trait Informant: trace::VMTracer { + /// Set initial gas. + fn set_gas(&mut self, _gas: U256) {} /// Display final result. fn finish(&mut self, result: Result); } @@ -40,6 +42,8 @@ pub struct Success { /// Execution failed pub struct Failure { + /// Used gas + pub gas_used: U256, /// Internal error pub error: EvmTestError, /// Duration @@ -49,6 +53,7 @@ pub struct Failure { /// Execute VM with given `ActionParams` pub fn run(vm_tracer: &mut T, spec: spec::Spec, params: ActionParams) -> Result { let mut test_client = EvmTestClient::new(spec).map_err(|error| Failure { + gas_used: 0.into(), error, time: Duration::from_secs(0) })?; @@ -65,6 +70,7 @@ pub fn run(vm_tracer: &mut T, spec: spec::Spec, params: Acti time: duration, }), Err(e) => Err(Failure { + gas_used: initial_gas, error: e, time: duration, }), diff --git a/js/package.json b/js/package.json index cd6059033..d45df6d3f 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.87", + "version": "1.7.90", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", @@ -159,6 +159,7 @@ }, "dependencies": { "@parity/wordlist": "1.0.1", + "arraybuffer-loader": "0.2.2", "babel-runtime": "6.23.0", "base32.js": "0.1.0", "bignumber.js": "3.0.1", @@ -218,7 +219,6 @@ "redux-thunk": "2.1.0", "rlp": "2.0.0", "scryptsy": "2.0.0", - "secp256k1": "3.2.5", "solc": "ngotchac/solc-js", "store": "1.3.20", "sw-toolbox": "^3.6.0", diff --git a/js/src/api/api.js b/js/src/api/api.js index 0b6e444c8..526ecbf1b 100644 --- a/js/src/api/api.js +++ b/js/src/api/api.js @@ -23,7 +23,7 @@ import { Db, Eth, Parity, Net, Personal, Shh, Signer, Trace, Web3 } from './rpc' import Subscriptions from './subscriptions'; import util from './util'; import { isFunction } from './util/types'; -// import { LocalAccountsMiddleware } from './local'; +import { LocalAccountsMiddleware } from './local'; export default class Api extends EventEmitter { constructor (transport, allowSubscriptions = true) { @@ -54,9 +54,9 @@ export default class Api extends EventEmitter { const middleware = this.parity .nodeKind() .then((nodeKind) => { - // if (nodeKind.availability === 'public') { - // return LocalAccountsMiddleware; - // } + if (nodeKind.availability === 'public') { + return LocalAccountsMiddleware; + } return null; }) diff --git a/js/src/api/contract/contract.js b/js/src/api/contract/contract.js index 0aff05684..dee4d6d77 100644 --- a/js/src/api/contract/contract.js +++ b/js/src/api/contract/contract.js @@ -177,19 +177,26 @@ export default class Contract { return null; } - const decoded = event.decodeLog(log.topics, log.data); + try { + const decoded = event.decodeLog(log.topics, log.data); - log.params = {}; - log.event = event.name; + log.params = {}; + log.event = event.name; - decoded.params.forEach((param, index) => { - const { type, value } = param.token; - const key = param.name || index; + decoded.params.forEach((param, index) => { + const { type, value } = param.token; + const key = param.name || index; - log.params[key] = { type, value }; - }); + log.params[key] = { type, value }; + }); - return log; + return log; + } catch (error) { + console.warn('Error decoding log', log); + console.warn(error); + + return null; + } }) .filter((log) => log); } diff --git a/js/src/api/local/accounts/account.js b/js/src/api/local/accounts/account.js index 94e923f45..0bb069c8b 100644 --- a/js/src/api/local/accounts/account.js +++ b/js/src/api/local/accounts/account.js @@ -17,9 +17,9 @@ import { createKeyObject, decryptPrivateKey } from '../ethkey'; export default class Account { - constructor (persist, data) { + constructor (persist, data = {}) { const { - keyObject, + keyObject = null, meta = {}, name = '' } = data; @@ -41,6 +41,15 @@ export default class Account { }); } + export () { + const exported = Object.assign({}, this._keyObject); + + exported.meta = JSON.stringify(this._meta); + exported.name = this._name; + + return exported; + } + get address () { return `0x${this._keyObject.address.toLowerCase()}`; } @@ -66,6 +75,10 @@ export default class Account { } get uuid () { + if (!this._keyObject) { + return null; + } + return this._keyObject.id; } diff --git a/js/src/api/local/accounts/accounts.js b/js/src/api/local/accounts/accounts.js index e7e5cc397..d0d100862 100644 --- a/js/src/api/local/accounts/accounts.js +++ b/js/src/api/local/accounts/accounts.js @@ -17,23 +17,74 @@ import Account from './account'; import localStore from 'store'; import { debounce } from 'lodash'; +import { decryptPrivateKey } from '../ethkey'; const NULL_ADDRESS = '0x0000000000000000000000000000000000000000'; const LS_STORE_KEY = '_parity::localAccounts'; export default class Accounts { + persist = debounce(() => { + this._lastState = JSON.stringify(this); + + localStore.set(LS_STORE_KEY, this); + }, 100); + constructor (data = localStore.get(LS_STORE_KEY) || {}) { + this._lastState = JSON.stringify(data); + + window.addEventListener('storage', ({ key, newValue }) => { + if (key !== LS_STORE_KEY) { + return; + } + + if (newValue !== this._lastState) { + console.log('Data changed in a second tab, syncing state'); + + this.restore(JSON.parse(newValue)); + } + }); + + this.restore(data); + } + + restore (data) { const { last = NULL_ADDRESS, - store = [] + dappsDefault = NULL_ADDRESS, + store = {} } = data; - this.persist = debounce(() => { - localStore.set(LS_STORE_KEY, this); - }, 100); - this._last = last; - this._store = store.map((data) => new Account(this.persist, data)); + this._dappsDefaultAddress = dappsDefault; + this._store = {}; + + if (Array.isArray(store)) { + // Recover older version that stored accounts as an array + store.forEach((data) => { + const account = new Account(this.persist, data); + + this._store[account.address] = account; + }); + } else { + Object.keys(store).forEach((key) => { + this._store[key] = new Account(this.persist, store[key]); + }); + } + } + + _addAccount = (account) => { + const { address } = account; + + if (address in this._store && this._store[address].uuid) { + throw new Error(`Account ${address} already exists!`); + } + + this._store[address] = account; + this.lastAddress = address; + + this.persist(); + + return account.address; } create (secret, password) { @@ -41,20 +92,19 @@ export default class Accounts { return Account .fromPrivateKey(this.persist, privateKey, password) - .then((account) => { - const { address } = account; + .then(this._addAccount); + } - if (this._store.find((account) => account.address === address)) { - throw new Error(`Account ${address} already exists!`); + restoreFromWallet (wallet, password) { + return decryptPrivateKey(wallet, password) + .then((privateKey) => { + if (!privateKey) { + throw new Error('Invalid password'); } - this._store.push(account); - this.lastAddress = address; - - this.persist(); - - return account.address; - }); + return Account.fromPrivateKey(this.persist, privateKey, password); + }) + .then(this._addAccount); } set lastAddress (value) { @@ -65,20 +115,48 @@ export default class Accounts { return this._last; } + get dappsDefaultAddress () { + if (this._dappsDefaultAddress === NULL_ADDRESS) { + return this._last; + } + + if (this._dappsDefaultAddress in this._store) { + return this._dappsDefaultAddress; + } + + return NULL_ADDRESS; + } + + set dappsDefaultAddress (value) { + this._dappsDefaultAddress = value.toLowerCase(); + } + get (address) { address = address.toLowerCase(); - this.lastAddress = address; - - const account = this._store.find((account) => account.address === address); + const account = this._store[address]; if (!account) { throw new Error(`Account not found: ${address}`); } + this.lastAddress = address; + return account; } + getLazyCreate (address) { + address = address.toLowerCase(); + + this.lastAddress = address; + + if (!(address in this._store)) { + this._store[address] = new Account(this.persist); + } + + return this._store[address]; + } + remove (address, password) { address = address.toLowerCase(); @@ -108,26 +186,20 @@ export default class Accounts { removeUnsafe (address) { address = address.toLowerCase(); - const index = this._store.findIndex((account) => account.address === address); - - if (index === -1) { - return; - } - - this._store.splice(index, 1); + delete this._store[address]; this.persist(); } - mapArray (mapper) { - return this._store.map(mapper); + addresses () { + return Object.keys(this._store); } - mapObject (mapper) { + map (mapper) { const result = {}; - this._store.forEach((account) => { - result[account.address] = mapper(account); + Object.keys(this._store).forEach((key) => { + result[key] = mapper(this._store[key]); }); return result; @@ -136,6 +208,7 @@ export default class Accounts { toJSON () { return { last: this._last, + dappsDefault: this._dappsDefaultAddress, store: this._store }; } diff --git a/js/src/api/local/ethkey/ethkey.js b/js/src/api/local/ethkey/ethkey.js new file mode 100644 index 000000000..f8395b007 --- /dev/null +++ b/js/src/api/local/ethkey/ethkey.js @@ -0,0 +1,147 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +/* global WebAssembly */ + +import wasmBuffer from './ethkey.wasm.js'; + +const NOOP = () => {}; + +// WASM memory setup +const WASM_PAGE_SIZE = 65536; +const STATIC_BASE = 1024; +const STATICTOP = STATIC_BASE + WASM_PAGE_SIZE * 2; +const STACK_BASE = align(STATICTOP + 16); +const STACKTOP = STACK_BASE; +const TOTAL_STACK = 5 * 1024 * 1024; +const TOTAL_MEMORY = 16777216; +const STACK_MAX = STACK_BASE + TOTAL_STACK; +const DYNAMIC_BASE = STACK_MAX + 64; +const DYNAMICTOP_PTR = STACK_MAX; + +function mockWebAssembly () { + function throwWasmError () { + throw new Error('Missing WebAssembly support'); + } + + // Simple mock replacement + return { + Memory: class { buffer = new ArrayBuffer(2048) }, + Table: class {}, + Module: class {}, + Instance: class { + exports = { + '_input_ptr': () => 0, + '_secret_ptr': () => 0, + '_public_ptr': () => 0, + '_address_ptr': () => 0, + '_ecpointg': NOOP, + '_brain': throwWasmError, + '_verify_secret': throwWasmError + } + } + }; +} + +const { Memory, Table, Module, Instance } = typeof WebAssembly !== 'undefined' ? WebAssembly : mockWebAssembly(); + +const wasmMemory = new Memory({ + initial: TOTAL_MEMORY / WASM_PAGE_SIZE, + maximum: TOTAL_MEMORY / WASM_PAGE_SIZE +}); + +const wasmTable = new Table({ + initial: 8, + maximum: 8, + element: 'anyfunc' +}); + +// TypedArray views into the memory +const wasmMemoryU8 = new Uint8Array(wasmMemory.buffer); +const wasmMemoryU32 = new Uint32Array(wasmMemory.buffer); + +// Keep DYNAMIC_BASE in memory +wasmMemoryU32[DYNAMICTOP_PTR >> 2] = align(DYNAMIC_BASE); + +function align (mem) { + const ALIGN_SIZE = 16; + + return (Math.ceil(mem / ALIGN_SIZE) * ALIGN_SIZE) | 0; +} + +export function slice (ptr, len) { + return wasmMemoryU8.subarray(ptr, ptr + len); +} + +// Required by emscripten +function abort (what) { + throw new Error(what || 'WASM abort'); +} + +// Required by emscripten +function abortOnCannotGrowMemory () { + abort(`Cannot enlarge memory arrays.`); +} + +// Required by emscripten +function enlargeMemory () { + abortOnCannotGrowMemory(); +} + +// Required by emscripten +function getTotalMemory () { + return TOTAL_MEMORY; +} + +// Required by emscripten - used to perform memcpy on large data +function memcpy (dest, src, len) { + wasmMemoryU8.set(wasmMemoryU8.subarray(src, src + len), dest); + + return dest; +} + +// Synchronously compile WASM from the buffer +const module = new Module(wasmBuffer); + +// Instantiated WASM module +const instance = new Instance(module, { + global: {}, + env: { + DYNAMICTOP_PTR, + STACKTOP, + STACK_MAX, + abort, + enlargeMemory, + getTotalMemory, + abortOnCannotGrowMemory, + ___lock: NOOP, + ___syscall6: () => 0, + ___setErrNo: (no) => no, + _abort: abort, + ___syscall140: () => 0, + _emscripten_memcpy_big: memcpy, + ___syscall54: () => 0, + ___unlock: NOOP, + _llvm_trap: abort, + ___syscall146: () => 0, + 'memory': wasmMemory, + 'table': wasmTable, + tableBase: 0, + memoryBase: STATIC_BASE + } +}); + +export const extern = instance.exports; diff --git a/js/src/api/local/ethkey/ethkey.wasm.js b/js/src/api/local/ethkey/ethkey.wasm.js new file mode 100644 index 000000000..d426f0e0c --- /dev/null +++ b/js/src/api/local/ethkey/ethkey.wasm.js @@ -0,0 +1 @@ +module.exports = new Buffer('AGFzbQEAAAABOgpgA39/fwF/YAF/AX9gAn9/AX9gAX8AYAABf2AAAGACf38AYAR/f39/AGADf39/AGAGf39/f39/AX8CyQELA2VudghTVEFDS1RPUAN/AANlbnYFYWJvcnQAAwNlbnYLX19fc3lzY2FsbDYAAgNlbnYNX19fc3lzY2FsbDE0MAACA2VudhZfZW1zY3JpcHRlbl9tZW1jcHlfYmlnAAADZW52DF9fX3N5c2NhbGw1NAACA2VudgpfbGx2bV90cmFwAAUDZW52DV9fX3N5c2NhbGwxNDYAAgNlbnYGbWVtb3J5AgGAAoACA2VudgV0YWJsZQFwAQgIA2Vudgl0YWJsZUJhc2UDfwADOjkEBAQEBAQDBwMICAgIAwYGBgIIAwMDBgMDCAYGBgMCBwYIAgICBgkDBgEAAAEEBAQAAQAAAQABAAIGBgF/ASMACwdfBw5fdmVyaWZ5X3NlY3JldAAMC19wdWJsaWNfcHRyAAoLX3NlY3JldF9wdHIACQpfaW5wdXRfcHRyAAgJX2VjcG9pbnRnAAcGX2JyYWluAA0MX2FkZHJlc3NfcHRyAAsJDgEAIwELCD0wPjEyNz8rCpClAzlJAQJ/An8jAiEAIwJB0JgBaiQCQagZKAIAQQFGBEAgACQCQawZDwsgACIBEB9BqBlBATYCAEGsGSABQdCYARA8GiAAJAJBrBkLCwYAQbi2AQsGAEG4vgELBgBB2L4BCwYAQZi/AQsKAEG4vgFBIBAlC74HAQt/AkAjAiEIIwJBoJwBaiQCIABBgAhLBEAgAEGACBAnCyAIQaACaiEFQagZKAIAQQFHBEAgBRAfQagZQQE2AgBBrBkgBUHQmAEQPBoLIAghCSAIQcgAaiIEEBQgCEH4mwFqIgFCADcAACABQgA3AAggAUIANwAQIAFCADcAGCAEQbi2ASAAEBAgBSAEQdgBEDwaIAUgAUEgEBIgCEHwmgFqIgMgASkAADcAACADIAEpAAg3AAggAyABKQAQNwAQIAMgASkAGDcAGCAIQZCbAWoiBkEBaiEHIAhB2JsBaiICQQxqIQpBACEAA0AgBBAUIAFCADcAACABQgA3AAggAUIANwAQIAFCADcAGCAEIANBIBAQIAUgBEHYARA8GiAFIAFBIBASIAIgASkAADcAACACIAEpAAg3AAggAiABKQAQNwAQIAIgASkAGDcAGCADIAIpAAA3AAAgAyACKQAINwAIIAMgAikAEDcAECADIAIpABg3ABggAEEBaiELIABBgYABRwRAIAshAAwBCwsgCUEBaiEAA0ACQCAJQawZIANBIBAmIAksAABBAUYEQCAGIAApAAA3AAAgBiAAKQAINwAIIAYgACkAEDcAECAGIAApABg3ABggBiAAKQAgNwAgIAYgACkAKDcAKCAGIAApADA3ADAgBiAAKQA4NwA4IAYgACwAQDoAQCAEEBQgAUIANwAAIAFCADcACCABQgA3ABAgAUIANwAYIAQgB0HAABAQIAUgBEHYARA8GiAFIAFBIBASIAIgASkAADcAACACIAEpAAg3AAggAiABKQAQNwAQIAIgASkAGDcAGEGYvwEgCikAADcAAEGgvwEgCikACDcAAEGovwEgCigAEDYAAEGYvwEsAABFDQELIAQQFCABQgA3AAAgAUIANwAIIAFCADcAECABQgA3ABggBCADQSAQECAFIARB2AEQPBogBSABQSAQEiACIAEpAAA3AAAgAiABKQAINwAIIAIgASkAEDcAECACIAEpABg3ABggAyACKQAANwAAIAMgAikACDcACCADIAIpABA3ABAgAyACKQAYNwAYDAELC0HYvgEgBykAADcAAEHgvgEgBykACDcAAEHovgEgBykAEDcAAEHwvgEgBykAGDcAAEH4vgEgBykAIDcAAEGAvwEgBykAKDcAAEGIvwEgBykAMDcAAEGQvwEgBykAODcAAEG4vgEgAykAADcAAEHAvgEgAykACDcAAEHIvgEgAykAEDcAAEHQvgEgAykAGDcAACAIJAILCwQAEAUL1wsCGX8tfgJAIAApAwAhJCAAQShqIgIpAwAhJSAAQdAAaiIDKQMAITAgAEH4AGoiBCkDACE+IABBoAFqIgUpAwAhJiAAQQhqIgYpAwAhMSAAQTBqIgcpAwAhMiAAQdgAaiIIKQMAIScgAEGAAWoiCSkDACEgIABBqAFqIgopAwAhPyAAQRBqIgspAwAhMyAAQThqIgwpAwAhHSAAQeAAaiINKQMAISEgAEGIAWoiDikDACE0IABBsAFqIg8pAwAhHiAAQRhqIhApAwAhNSAAQcAAaiIRKQMAISggAEHoAGoiEikDACE2IABBkAFqIhMpAwAhGyAAQbgBaiIUKQMAISIgAEEgaiIV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0AkpAwA3AxAgAUHYCSkDADcDGCABQeAJKQMANwMgIAFB6AkpAwA3AyggAUHwCSkDADcDMCABQfgJKQMANwM4IAFBgAopAwA3A0AgASADEBYgACABKQIANwIAIAAgASkCCDcCCCAAIAEpAhA3AhAgACABKQIYNwIYIAAgASkCIDcCICAAIAEpAig3AiggACABKQIwNwIwIAAgASkCODcCOCAAIAEpAkA3AkAgByQCDwsACwsgAxAbIAAgAykCADcCACAAIAMpAgg3AgggACADKQIQNwIQIAAgAykCGDcCGCAAIAMpAiA3AiAgACADKQIoNwIoIAAgAykCMDcCMCAAIAMpAjg3AjggACADKQJANwJAIAckAgsLzx8BD38CQCMCIQwjAkGABWokAiAAQZABaiIELAAABEAgDCQCDwsgDCELIAxBuARqIgIgAEHIAGoiCikCADcCACACIAopAgg3AgggAiAKKQIQNwIQIAIgCikCGDcCGCACIAopAiA3AiAgAiAKKQIoNwIoIAIgCikCMDcCMCACIAopAjg3AjggAiAKKQJANwJAIAIgChAVIAxB8ANqIgEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAAkACQCABKAIAIgNBCEYEQEEIIQcCQAJAAkADQCAHQX9qIQMgB0UNBSADQRBPDQEgAUEEaiADQQJ0aigCACIHIANBAnRBxAlqKAIAIgVHDQIgAyEHDAALAAtBvAsgA0EQECgMAQsgByAFTw0CQQghDQsFIANBCE8NASADIQ0LDAELIAFBwAkQFiABKAIAIQ0LIAEoAgQhDiALIAFBCGoiAykCADcCACALIAMpAgg3AgggCyADKQIQNwIQIAsgAykCGDcCGCALIAMpAiA3AiAgCyADKQIoNwIoIAsgAykCMDcCMCALIAMpAjg3AjggDUEBRiAORXEEQCAEQQE6AAAgDCQCDwsgDEGoA2ohCCAMQeACaiEEIAxBmAJqIQUgDEGIAWohBiACIAApAgA3AgAgAiAAKQIINwIIIAIgACkCEDcCECACIAApAhg3AhggAiAAKQIgNwIgIAIgACkCKDcCKCACIAApAjA3AjAgAiAAKQI4NwI4IAIgACkCQDcCQCACIAAQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgDEHAAGoiCSABKQMANwMAIAkgASkDCDcDCCAJIAEpAxA3AxAgCSABKQMYNwMYIAkgASkDIDcDICAJIAEpAyg3AyggCSABKQMwNwMwIAkgASkDODcDOCAJIAEpA0A3A0AgAiAJKQMANwMAIAIgCSkDCDcDCCACIAkpAxA3AxAgAiAJKQMYNwMYIAIgCSkDIDcDICACIAkpAyg3AyggAiAJKQMwNwMwIAIgCSkDODcDOCACIAkpA0A3A0AgAiAJEBUgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0ACQAJAIAEoAgAiA0EIRgRAQQghBwJAAkACQANAIAdBf2ohAyAHRQ0FIANBEE8NASABQQRqIANBAnRqKAIAIgcgA0ECdEHECWooAgAiD0cNAiADIQcMAAsAC0G8CyADQRAQKAwBCyAHIA9PDQILBSADQQhPDQELDAELIAFBwAkQFgsgBCABKQMANwMAIAQgASkDCDcDCCAEIAEpAxA3AxAgBCABKQMYNwMYIAQgASkDIDcDICAEIAEpAyg3AyggBCABKQMwNwMwIAQgASkDODcDOCAEIAEpA0A3A0AgAiAEKQMANwMAIAIgBCkDCDcDCCACIAQpAxA3AxAgAiAEKQMYNwMYIAIgBCkDIDcDICACIAQpAyg3AyggAiAEKQMwNwMwIAIgBCkDODcDOCACIAQpA0A3A0AgAiAJEBUgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0ACQAJAIAEoAgAiA0EIRgRAQQghBwJAAkACQANAIAdBf2ohAyAHRQ0FIANBEE8NASABQQRqIANBAnRqKAIAIgcgA0ECdEHECWooAgAiCUcNAiADIQcMAAsAC0G8CyADQRAQKAwBCyAHIAlPDQILBSADQQhPDQELDAELIAFBwAkQFgsgBSABKQMANwMAIAUgASkDCDcDCCAFIAEpAxA3AxAgBSABKQMYNwMYIAUgASkDIDcDICAFIAEpAyg3AyggBSABKQMwNwMwIAUgASkDODcDOCAFIAEpA0A3A0AgAiANNgIAIAIgDjYCBCACQQhqIgMgCykDADcDACADIAspAwg3AwggAyALKQMQNwMQIAMgCykDGDcDGCADIAspAyA3AyAgAyALKQMoNwMoIAMgCykDMDcDMCADIAspAzg3AzggCCACEB0gAiAFKQMANwMAIAIgBSkDCDcDCCACIAUpAxA3AxAgAiAFKQMYNwMYIAIgBSkDIDcDICACIAUpAyg3AyggAiAFKQMwNwMwIAIgBSkDODcDOCACIAUpA0A3A0AgAiAIEBcgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgARAbIAYgASkDADcDACAGIAEpAwg3AwggBiABKQMQNwMQIAYgASkDGDcDGCAGIAEpAyA3AyAgBiABKQMoNwMoIAYgASkDMDcDMCAGIAEpAzg3AzggBiABKQNANwNAIAIgBikDADcDACACIAYpAwg3AwggAiAGKQMQNwMQIAIgBikDGDcDGCACIAYpAyA3AyAgAiAGKQMoNwMoIAIgBikDMDcDMCACIAYpAzg3AzggAiAGKQNANwNAIAIgBhAXIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAIAEQGyAEIAEpAwA3AwAgBCABKQMINwMIIAQgASkDEDcDECAEIAEpAxg3AxggBCABKQMgNwMgIAQgASkDKDcDKCAEIAEpAzA3AzAgBCABKQM4NwM4IAQgASkDQDcDQCACIAApAgA3AgAgAiAAKQIINwIIIAIgACkCEDcCECACIAApAhg3AhggAiAAKQIgNwIgIAIgACkCKDcCKCACIAApAjA3AjAgAiAAKQI4NwI4IAIgACkCQDcCQCACIAAQFSABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQAJAAkAgASgCACIDQQhGBEBBCCEHAkACQAJAA0AgB0F/aiEDIAdFDQUgA0EQTw0BIAFBBGogA0ECdGooAgAiByADQQJ0QcQJaigCACILRw0CIAMhBwwACwALQbwLIANBEBAoDAELIAcgC08NAgsFIANBCE8NAQsMAQsgAUHACRAWCyAIIAEpAwA3AwAgCCABKQMINwMIIAggASkDEDcDECAIIAEpAxg3AxggCCABKQMgNwMgIAggASkDKDcDKCAIIAEpAzA3AzAgCCABKQM4NwM4IAggASkDQDcDQCACIAQpAwA3AwAgAiAEKQMINwMIIAIgBCkDEDcDECACIAQpAxg3AxggAiAEKQMgNwMgIAIgBCkDKDcDKCACIAQpAzA3AzAgAiAEKQM4NwM4IAIgBCkDQDcDQCACIAgQFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyAMQdABaiIDIAEpAwA3AwAgAyABKQMINwMIIAMgASkDEDcDECADIAEpAxg3AxggAyABKQMgNwMgIAMgASkDKDcDKCADIAEpAzA3AzAgAyABKQM4NwM4IAMgASkDQDcDQCACIAApAgA3AgAgAiAAKQIINwIIIAIgACkCEDcCECACIAApAhg3AhggAiAAKQIgNwIgIAIgACkCKDcCKCACIAApAjA3AjAgAiAAKQI4NwI4IAIgACkCQDcCQCACIAMQFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyAIIAEpAwA3AwAgCCABKQMINwMIIAggASkDEDcDECAIIAEpAxg3AxggCCABKQMgNwMgIAggASkDKDcDKCAIIAEpAzA3AzAgCCABKQM4NwM4IAggASkDQDcDQCACIAYpAwA3AwAgAiAGKQMINwMIIAIgBikDEDcDECACIAYpAxg3AxggAiAGKQMgNwMgIAIgBikDKDcDKCACIAYpAzA3AzAgAiAGKQM4NwM4IAIgBikDQDcDQCACIAgQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgBCABKQMANwMAIAQgASkDCDcDCCAEIAEpAxA3AxAgBCABKQMYNwMYIAQgASkDIDcDICAEIAEpAyg3AyggBCABKQMwNwMwIAQgASkDODcDOCAEIAEpA0A3A0AgAiAEKQMANwMAIAIgBCkDCDcDCCACIAQpAxA3AxAgAiAEKQMYNwMYIAIgBCkDIDcDICACIAQpAyg3AyggAiAEKQMwNwMwIAIgBCkDODcDOCACIAQpA0A3A0AgAiAKEBYgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgASwARARAIAFBwAkQFQsgBSABKQMANwMAIAUgASkDCDcDCCAFIAEpAxA3AxAgBSABKQMYNwMYIAUgASkDIDcDICAFIAEpAyg3AyggBSABKQMwNwMwIAUgASkDODcDOCAFIAEpA0A3A0AgCiAFKQIANwIAIAogBSkCCDcCCCAKIAUpAhA3AhAgCiAFKQIYNwIYIAogBSkCIDcCICAKIAUpAig3AiggCiAFKQIwNwIwIAogBSkCODcCOCAKIAUpAkA3AkAgACADKQIANwIAIAAgAykCCDcCCCAAIAMpAhA3AhAgACADKQIYNwIYIAAgAykCIDcCICAAIAMpAig3AiggACADKQIwNwIwIAAgAykCODcCOCAAIAMpAkA3AkAgDCQCCwvCFgETfwJAIwIhCSMCQfC1AmokAiAJQZC0AmohAyAJQcizAmohBSAJQbiyAmohByAJQey1AmohCyAJIgRBCDYCACAEQZiv4LcBNgIEIARB24LKzwU2AgggBEHZ0bjuAjYCDCAEQdv57xQ2AhAgBEGHlpz0fDYCFCAEQZXFga0FNgIYIARBrPfyTjYCHCAEQf7M+c0HNgIgIARBJGoiBkIANwIAIAZCADcCCCAGQgA3AhAgBkIANwIYIAZBADoAICAEQQg2AkggBEHMAGoiD0G4qcNYNgIAIARBj6Gf4nk2AlAgBEGZqJW0ejYCVCAEQcjo3mg2AlggBEGokcTwADYCXCAEQfz3k+0FNgJgIARB5YiPtQI2AmQgBEH3tOvBBDYCaCAEQewAaiIGQgA3AgAgBkIANwIIIAZCADcCECAGQgA3AhggBkEAOgAgIARBkAFqIhBBADoAACAJQdi0AmoiASAEQZQBEDwaIAlB6JkBaiICIARBlAEQPBogAkGUAWogAUGUARA8GiACQagCaiABQZQBEDwaIAJBvANqIAFBlAEQPBogAkHQBGogAUGUARA8GiACQeQFaiABQZQBEDwaIAJB+AZqIAFBlAEQPBogAkGMCGogAUGUARA8GiACQaAJaiABQZQBEDwaIAJBtApqIAFBlAEQPBogAkHIC2ogAUGUARA8GiACQdwMaiABQZQBEDwaIAJB8A1qIAFBlAEQPBogAkGED2ogAUGUARA8GiACQZgQaiABQZQBEDwaIAJBrBFqIAFBlAEQPBogAkHAEmogAUGUARA8GiACQdQTaiABQZQBEDwaIAJB6BRqIAFBlAEQPBogAkH8FWogAUGUARA8GiACQZAXaiABQZQBEDwaIAJBpBhqIAFBlAEQPBogAkG4GWogAUGUARA8GiACQcwaaiABQZQBEDwaIAJB4BtqIAFBlAEQPBogAkH0HGogAUGUARA8GiACQYgeaiABQZQBEDwaIAJBnB9qIAFBlAEQPBogAkGwIGogAUGUARA8GiACQcQhaiABQZQBEDwaIAJB2CJqIAFBlAEQPBogAkHsI2ogAUGUARA8GiACQYAlaiABQZQBEDwaIAJBlCZqIAFBlAEQPBogAkGoJ2ogAUGUARA8GiACQbwoaiABQZQBEDwaIAJB0ClqIAFBlAEQPBogAkHkKmogAUGUARA8GiACQfgraiABQZQBEDwaIAJBjC1qIAFBlAEQPBogAkGgLmogAUGUARA8GiACQbQvaiABQZQBEDwaIAJByDBqIAFBlAEQPBogAkHcMWogAUGUARA8GiACQfAyaiABQZQBEDwaIAJBhDRqIAFBlAEQPBogAkGYNWogAUGUARA8GiACQaw2aiABQZQBEDwaIAJBwDdqIAFBlAEQPBogAkHUOGogAUGUARA8GiACQeg5aiABQZQBEDwaIAJB/DpqIAFBlAEQPBogAkGQPGogAUGUARA8GiACQaQ9aiABQZQBEDwaIAJBuD5qIAFBlAEQPBogAkHMP2ogAUGUARA8GiACQeDAAGogAUGUARA8GiACQfTBAGogAUGUARA8GiACQYjDAGogAUGUARA8GiACQZzEAGogAUGUARA8GiACQbDFAGogAUGUARA8GiACQcTGAGogAUGUARA8GiACQdjHAGogAUGUARA8GiACQezIAGogAUGUARA8GiACQYDKAGogAUGUARA8GiACQZTLAGogAUGUARA8GiAQLAAABH8gByAEQZABEDwaIAsgBEGRAWoiBi4AADsAACALIAYsAAI6AAJBAQUgBSAEKQMANwMAIAUgBCkDCDcDCCAFIAQpAxA3AxAgBSAEKQMYNwMYIAUgBCkDIDcDICAFIAQpAyg3AyggBSAEKQMwNwMwIAUgBCkDODcDOCAFIAQpA0A3A0AgBEHIAGoiBigCAEEBRiAPKAIARXEEQCADQdgMKQIANwIAIANB4AwpAgA3AgggA0HoDCkCADcCECADQfAMKQIANwIYIANB+AwpAgA3AiAgA0GADSkCADcCKCADQYgNKQIANwIwIANBkA0pAgA3AjggA0GYDSkCADcCQAUgAUHACSkDADcDACABQcgJKQMANwMIIAFB0AkpAwA3AxAgAUHYCSkDADcDGCABQeAJKQMANwMgIAFB6AkpAwA3AyggAUHwCSkDADcDMCABQfgJKQMANwM4IAFBgAopAwA3A0AgASAGEBYgAyABKQMANwMAIAMgASkDCDcDCCADIAEpAxA3AxAgAyABKQMYNwMYIAMgASkDIDcDICADIAEpAyg3AyggAyABKQMwNwMwIAMgASkDODcDOCADIAEpA0A3A0ALIAcgBSkDADcDACAHIAUpAwg3AwggByAFKQMQNwMQIAcgBSkDGDcDGCAHIAUpAyA3AyAgByAFKQMoNwMoIAcgBSkDMDcDMCAHIAUpAzg3AzggByAFKQNANwNAIAdByABqIgYgAykDADcDACAGIAMpAwg3AwggBiADKQMQNwMQIAYgAykDGDcDGCAGIAMpAyA3AyAgBiADKQMoNwMoIAYgAykDMDcDMCAGIAMpAzg3AzggBiADKQNANwNAQQALIQwgCUGYAWohDSAJQZDmAWoiCkGozABqIQggCiEG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QCACIA4QFyAMQbgIaiIDIAIpAwA3AwAgAyACKQMINwMIIAMgAikDEDcDECADIAIpAxg3AxggAyACKQMgNwMgIAMgAikDKDcDKCADIAIpAzA3AzAgAyACKQM4NwM4IAMgAikDQDcDQCADEBsgDCIGIAMpAwA3AwAgBiADKQMINwMIIAYgAykDEDcDECAGIAMpAxg3AxggBiADKQMgNwMgIAYgAykDKDcDKCAGIAMpAzA3AzAgBiADKQM4NwM4IAYgAykDQDcDQCACIABBkAFqIgkpAgA3AgAgAiAJKQIINwIIIAIgCSkCEDcCECACIAkpAhg3AhggAiAJKQIgNwIgIAIgCSkCKDcCKCACIAkpAjA3AjAgAiAJKQI4NwI4IAIgCSkCQDcCQCACIAkQFyADIAIpAwA3AwAgAyACKQMINwMIIAMgAikDEDcDECADIAIpAxg3AxggAyACKQMgNwMgIAMgAikDKDcDKCADIAIpAzA3AzAgAyACKQM4NwM4IAMgAikDQDcDQCADEBsgDEHIAGoiBSADKQMANwMAIAUgAykDCDcDCCAFIAMpAxA3AxAgBSADKQMYNwMYIAUgAykDIDcDICAFIAMpAyg3AyggBSADKQMwNwMwIAUgAykDODcDOCAFIAMpA0A3A0AgAiAAKQIANwIAIAIgACkCCDcCCCACIAApAhA3AhAgAiAAKQIYNwIYIAIgACkCIDcCICACIAApAig3AiggAiAAKQIwNwIwIAIgACkCODcCOCACIAApAkA3AkAgAiAGEBcgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAxAbIAxBkAFqIgcgAykDADcDACAHIAMpAwg3AwggByADKQMQNwMQIAcgAykDGDcDGCAHIAMpAyA3AyAgByADKQMoNwMoIAcgAykDMDcDMCAHIAMpAzg3AzggByADKQNANwNAIAIgASkCADcCACACIAEpAgg3AgggAiABKQIQNwIQIAIgASkCGDcCGCACIAEpAiA3AiAgAiABKQIoNwIoIAIgASkCMDcCMCACIAEpAjg3AjggAiABKQJANwJAIAIgBRAXIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMQGyAMQdgBaiIIIAMpAwA3AwAgCCADKQMINwMIIAggAykDEDcDECAIIAMpAxg3AxggCCADKQMgNwMgIAggAykDKDcDKCAIIAMpAzA3AzAgCCADKQM4NwM4IAggAykDQDcDQCACIABByABqIg0pAgA3AgAgAiANKQIINwIIIAIgDSkCEDcCECACIA0pAhg3AhggAiANKQIgNwIgIAIgDSkCKDcCKCACIA0pAjA3AjAgAiANKQI4NwI4IAIgDSkCQDcCQCACIAYQFyADIAIpAwA3AwAgAyACKQMINwMIIAMgAikDEDcDECADIAIpAxg3AxggAyACKQMgNwMgIAMgAikDKDcDKCADIAIpAzA3AzAgAyACKQM4NwM4IAMgAikDQDcDQCADEBsgDEHwB2oiBCADKQMANwMAIAQgAykDCDcDCCAEIAMpAxA3AxAgBCADKQMYNwMYIAQgAykDIDcDICAEIAMpAyg3AyggBCADKQMwNwMwIAQgAykDODcDOCAEIAMpA0A3A0AgAiAEKQMANwMAIAIgBCkDCDcDCCACIAQpAxA3AxAgAiAEKQMYNwMYIAIgBCkDIDcDICACIAQpAyg3AyggAiAEKQMwNwMwIAIgBCkDODcDOCACIAQpA0A3A0AgAiAOEBcgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAxAbIAxBoAJqIgogAykDADcDACAKIAMpAwg3AwggCiADKQMQNwMQIAogAykDGDcDGCAKIAMpAyA3AyAgCiADKQMoNwMoIAogAykDMDcDMCAKIAMpAzg3AzggCiADKQNANwNAIAIgAUHIAGoiASkCADcCACACIAEpAgg3AgggAiABKQIQNwIQIAIgASkCGDcCGCACIAEpAiA3AiAgAiABKQIoNwIoIAIgASkCMDcCMCACIAEpAjg3AjggAiABKQJANwJAIAIgBRAXIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMQGyAEIAMpAwA3AwAgBCADKQMINwMIIAQgAykDEDcDECAEIAMpAxg3AxggBCADKQMgNwMgIAQgAykDKDcDKCAEIAMpAzA3AzAgBCADKQM4NwM4IAQgAykDQDcDQCACIAQpAwA3AwAgAiAEKQMINwMIIAIgBCkDEDcDECACIAQpAxg3AxggAiAEKQMgNwMgIAIgBCkDKDcDKCACIAQpAzA3AzAgAiAEKQM4NwM4IAIgBCkDQDcDQCACIAkQFyADIAIpAwA3AwAgAyACKQMINwMIIAMgAikDEDcDECADIAIpAxg3AxggAyACKQMgNwMgIAMgAikDKDcDKCADIAIpAzA3AzAgAyACKQM4NwM4IAMgAikDQDcDQCADEBsgDEHoAmoiASADKQMANwMAIAEgAykDCDcDCCABIAMpAxA3AxAgASADKQMYNwMYIAEgAykDIDcDICABIAMpAyg3AyggASADKQMwNwMwIAEgAykDODcDOCABIAMpA0A3A0AgAiAHKQMANwMAIAIgBykDCDcDCCACIAcpAxA3AxAgAiAHKQMYNwMYIAIgBykDIDcDICACIAcpAyg3AyggAiAHKQMwNwMwIAIgBykDODcDOCACIAcpA0A3A0AgAiAIEBYgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAywARARAIANBwAkQFQsgDEGwA2oiCyADKQMANwMAIAsgAykDCDcDCCALIAMpAxA3AxAgCyADKQMYNwMYIAsgAykDIDcDICALIAMpAyg3AyggCyADKQMwNwMwIAsgAykDODcDOCALIAMpA0A3A0AgAiAKKQMANwMAIAIgCikDCDcDCCACIAopAxA3AxAgAiAKKQMYNwMYIAIgCikDIDcDICACIAopAyg3AyggAiAKKQMwNwMwIAIgCikDODcDOCACIAopA0A3A0AgAiABEBYgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAywARARAIANBwAkQFQsgDEH4A2oiCCADKQMANwMAIAggAykDCDcDCCAIIAMpAxA3AxAgCCADKQMYNwMYIAggAykDIDcDICAIIAMpAyg3AyggCCADKQMwNwMwIAggAykDODcDOCAIIAMpA0A3A0AgCygCAEEBRgRAIAsoAgRFBEACQAJAIAgoAgBBAUcNACAIKAIEDQAgABAkDAELIAJBiAopAwA3AwAgAkGQCikDADcDCCACQZgKKQMANwMQIAJBoAopAwA3AxggAkGoCikDADcDICACQbAKKQMANwMoIAJBuAopAwA3AzAgAkHACikDADcDOCACQcgKKQMANwNAIAJByABqIgFBiAopAwA3AwAgAUGQCikDADcDCCABQZgKKQMANwMQIAFBoAopAwA3AxggAUGoCikDADcDICABQbAKKQMANwMoIAFBuAopAwA3AzAgAUHACikDADcDOCABQcgKKQMANwNAIAJBkAFqIgFB2AwpAgA3AgAgAUHgDCkCADcCCCABQegMKQIANwIQIAFB8AwpAgA3AhggAUH4DCkCADcCICABQYANKQIANwIoIAFBiA0pAgA3AjAgAUGQDSkCADcCOCABQZgNKQIANwJAIAAgAkHYARA8GgsgDCQCDwsLIAxBqAdqIQUgAiALKQMANwMAIAIgCykDCDcDCCACIAspAxA3AxAgAiALKQMYNwMYIAIgCykDIDcDICACIAspAyg3AyggAiALKQMwNwMwIAIgCykDODcDOCACIAspA0A3A0AgAiALEBcgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAxAbIAxBwARqIgEgAykDADcDACABIAMpAwg3AwggASADKQMQNwMQIAEgAykDGDcDGCABIAMpAyA3AyAgASADKQMoNwMoIAEgAykDMDcDMCABIAMpAzg3AzggASADKQNANwNAIAIgBykDADcDACACIAcpAwg3AwggAiAHKQMQNwMQIAIgBykDGDcDGCACIAcpAyA3AyAgAiAHKQMoNwMoIAIgBykDMDcDMCACIAcpAzg3AzggAiAHKQNANwNAIAIgARAXIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMQGyAMQYgFaiIHIAMpAwA3AwAgByADKQMINwMIIAcgAykDEDcDECAHIAMpAxg3AxggByADKQMgNwMgIAcgAykDKDcDKCAHIAMpAzA3AzAgByADKQM4NwM4IAcgAykDQDcDQCACIAEpAwA3AwAgAiABKQMINwMIIAIgASkDEDcDECACIAEpAxg3AxggAiABKQMgNwMgIAIgASkDKDcDKCACIAEpAzA3AzAgAiABKQM4NwM4IAIgASkDQDcDQCACIAsQFyADIAIpAwA3AwAgAyACKQMINwMIIAMgAikDEDcDECADIAIpAxg3AxggAyACKQMgNwMgIAMgAikDKDcDKCADIAIpAzA3AzAgAyACKQM4NwM4IAMgAikDQDcDQCADEBsgDEHQBWoiDyADKQMANwMAIA8gAykDCDcDCCAPIAMpAxA3AxAgDyADKQMYNwMYIA8gAykDIDcDICAPIAMpAyg3AyggDyADKQMwNwMwIA8gAykDODcDOCAPIAMpA0A3A0AgAiAIKQMANwMAIAIgCCkDCDcDCCACIAgpAxA3AxAgAiAIKQMYNwMYIAIgCCkDIDcDICACIAgpAyg3AyggAiAIKQMwNwMwIAIgCCkDODcDOCACIAgpA0A3A0AgAiAIEBcgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAxAbIAQgAykDADcDACAEIAMpAwg3AwggBCADKQMQNwMQIAQgAykDGDcDGCAEIAMpAyA3AyAgBCADKQMoNwMoIAQgAykDMDcDMCAEIAMpAzg3AzggBCADKQNANwNAIAIgBCkDADcDACACIAQpAwg3AwggAiAEKQMQNwMQIAIgBCkDGDcDGCACIAQpAyA3AyAgAiAEKQMoNwMoIAIgBCkDMDcDMCACIAQpAzg3AzggAiAEKQNANwNAIAIgDxAVIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAAkACQCADKAIAIgFBCEYEQEEIIQYCQAJAAkADQCAGQX9qIQEgBkUNBSABQRBPDQEgA0EEaiABQQJ0aigCACIGIAFBAnRBxAlqKAIAIhBHDQIgASEGDAALAAtBvAsgAUEQECgMAQsgBiAQTw0CCwUgAUEITw0BCwwBCyADQcAJEBYLIAUgAykDADcDACAFIAMpAwg3AwggBSADKQMQNwMQIAUgAykDGDcDGCAFIAMpAyA3AyAgBSADKQMoNwMoIAUgAykDMDcDMCAFIAMpAzg3AzggBSADKQNANwNAIAIgBSkDADcDACACIAUpAwg3AwggAiAFKQMQNwMQIAIgBSkDGDcDGCACIAUpAyA3AyAgAiAFKQMoNwMoIAIgBSkDMDcDMCACIAUpAzg3AzggAiAFKQNANwNAIAIgBxAWIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMsAEQEQCADQcAJEBULIAxB4AZqIgEgAykDADcDACABIAMpAwg3AwggASADKQMQNwMQIAEgAykDGDcDGCABIAMpAyA3AyAgASADKQMoNwMoIAEgAykDMDcDMCABIAMpAzg3AzggASADKQNANwNAIAIgASkDADcDACACIAEpAwg3AwggAiABKQMQNwMQIAIgASkDGDcDGCACIAEpAyA3AyAgAiABKQMoNwMoIAIgASkDMDcDMCACIAEpAzg3AzggAiABKQNANwNAIAIgBxAWIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMsAEQEQCADQcAJEBULIAxBmAZqIgYgAykDADcDACAGIAMpAwg3AwggBiADKQMQNwMQIAYgAykDGDcDGCAGIAMpAyA3AyAgBiADKQMoNwMoIAYgAykDMDcDMCAGIAMpAzg3AzggBiADKQNANwNAIAAgBikCADcCACAAIAYpAgg3AgggACAGKQIQNwIQIAAgBikCGDcCGCAAIAYpAiA3AiAgACAGKQIoNwIoIAAgBikCMDcCMCAAIAYpAjg3AjggACAGKQJANwJAIAIgBykDADcDACACIAcpAwg3AwggAiAHKQMQNwMQIAIgBykDGDcDGCACIAcpAyA3AyAgAiAHKQMoNwMoIAIgBykDMDcDMCACIAcpAzg3AzggAiAHKQNANwNAIAIgABAWIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMsAEQEQCADQcAJEBULIAUgAykDADcDACAFIAMpAwg3AwggBSADKQMQNwMQIAUgAykDGDcDGCAFIAMpAyA3AyAgBSADKQMoNwMoIAUgAykDMDcDMCAFIAMpAzg3AzggBSADKQNANwNAIAIgCCkDADcDACACIAgpAwg3AwggAiAIKQMQNwMQIAIgCCkDGDcDGCACIAgpAyA3AyAgAiAIKQMoNwMoIAIgCCkDMDcDMCACIAgpAzg3AzggAiAIKQNANwNAIAIgBRAXIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMQGyABIAMpAwA3AwAgASADKQMINwMIIAEgAykDEDcDECABIAMpAxg3AxggASADKQMgNwMgIAEgAykDKDcDKCABIAMpAzA3AzAgASADKQM4NwM4IAEgAykDQDcDQCACIAopAwA3AwAgAiAKKQMINwMIIAIgCikDEDcDECACIAopAxg3AxggAiAKKQMgNwMgIAIgCikDKDcDKCACIAopAzA3AzAgAiAKKQM4NwM4IAIgCikDQDcDQCACIA8QFyADIAIpAwA3AwAgAyACKQMINwMIIAMgAikDEDcDECADIAIpAxg3AxggAyACKQMgNwMgIAMgAikDKDcDKCADIAIpAzA3AzAgAyACKQM4NwM4IAMgAikDQDcDQCADEBsgBCADKQMANwMAIAQgAykDCDcDCCAEIAMpAxA3AxAgBCADKQMYNwMYIAQgAykDIDcDICAEIAMpAyg3AyggBCADKQMwNwMwIAQgAykDODcDOCAEIAMpA0A3A0AgAiABKQMANwMAIAIgASkDCDcDCCACIAEpAxA3AxAgAiABKQMYNwMYIAIgASkDIDcDICACIAEpAyg3AyggAiABKQMwNwMwIAIgASkDODcDOCACIAEpA0A3A0AgAiAEEBYgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAywARARAIANBwAkQFQsgBiADKQMANwMAIAYgAykDCDcDCCAGIAMpAxA3AxAgBiADKQMYNwMYIAYgAykDIDcDICAGIAMpAyg3AyggBiADKQMwNwMwIAYgAykDODcDOCAGIAMpA0A3A0AgDSAGKQIANwIAIA0gBikCCDcCCCANIAYpAhA3AhAgDSAGKQIYNwIYIA0gBikCIDcCICANIAYpAig3AiggDSAGKQIwNwIwIA0gBikCODcCOCANIAYpAkA3AkAgAiAJKQIANwIAIAIgCSkCCDcCCCACIAkpAhA3AhAgAiAJKQIYNwIYIAIgCSkCIDcCICACIAkpAig3AiggAiAJKQIwNwIwIAIgCSkCODcCOCACIAkpAkA3AkAgAiAOEBcgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAxAbIAQgAykDADcDACAEIAMpAwg3AwggBCADKQMQNwMQIAQgAykDGDcDGCAEIAMpAyA3AyAgBCADKQMoNwMoIAQgAykDMDcDMCAEIAMpAzg3AzggBCADKQNANwNAIAIgBCkDADcDACACIAQpAwg3AwggAiAEKQMQNwMQIAIgBCkDGDcDGCACIAQpAyA3AyAgAiAEKQMoNwMoIAIgBCkDMDcDMCACIAQpAzg3AzggAiAEKQNANwNAIAIgCxAXIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMQGyAFIAMpAwA3AwAgBSADKQMINwMIIAUgAykDEDcDECAFIAMpAxg3AxggBSADKQMgNwMgIAUgAykDKDcDKCAFIAMpAzA3AzAgBSADKQM4NwM4IAUgAykDQDcDQCAJIAUpAgA3AgAgCSAFKQIINwIIIAkgBSkCEDcCECAJIAUpAhg3AhggCSAFKQIgNwIgIAkgBSkCKDcCKCAJIAUpAjA3AjAgCSAFKQI4NwI4IAkgBSkCQDcCQCAMJAILC94KAQt/AkAjAiEJIwJBgAVqJAIgCUG4BGohAiAJQfADaiEDIAlBqANqIQQgCUHgAmohBSAJQZgCaiEIIAlB0AFqIQcgCUHAAGoiCiABQZABEDwaIAEoApABIQsgASgClAEhDCAJIgYgAUGYAWoiASkCADcCACAGIAEpAgg3AgggBiABKQIQNwIQIAYgASkCGDcCGCAGIAEpAiA3AiAgBiABKQIoNwIoIAYgASkCMDcCMCAGIAEpAjg3AjggC0EBRiAMRXEEQCAAQYgOQZQBEDwaIAkkAgUgAiALNgIAIAIgDDYCBCACQQhqIgEgBikDADcDACABIAYpAwg3AwggASAGKQMQNwMQIAEgBikDGDcDGCABIAYpAyA3AyAgASAGKQMoNwMoIAEgBikDMDcDMCABIAYpAzg3AzggByACEB0gAiAHKQMANwMAIAIgBykDCDcDCCACIAcpAxA3AxAgAiAHKQMYNwMYIAIgBykDIDcDICACIAcpAyg3AyggAiAHKQMwNwMwIAIgBykDODcDOCACIAcpA0A3A0AgAiAHEBcgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAxAbIAggAykDADcDACAIIAMpAwg3AwggCCADKQMQNwMQIAggAykDGDcDGCAIIAMpAyA3AyAgCCADKQMoNwMoIAggAykDMDcDMCAIIAMpAzg3AzggCCADKQNANwNAIAIgCikDADcDACACIAopAwg3AwggAiAKKQMQNwMQIAIgCikDGDcDGCACIAopAyA3AyAgAiAKKQMoNwMoIAIgCikDMDcDMCACIAopAzg3AzggAiAKKQNANwNAIAIgCBAXIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMQGyAFIAMpAwA3AwAgBSADKQMINwMIIAUgAykDEDcDECAFIAMpAxg3AxggBSADKQMgNwMgIAUgAykDKDcDKCAFIAMpAzA3AzAgBSADKQM4NwM4IAUgAykDQDcDQCACIApByABqIgEpAwA3AwAgAiABKQMINwMIIAIgASkDEDcDECACIAEpAxg3AxggAiABKQMgNwMgIAIgASkDKDcDKCACIAEpAzA3AzAgAiABKQM4NwM4IAIgASkDQDcDQCACIAgQFyADIAIpAwA3AwAgAyACKQMINwMIIAMgAikDEDcDECADIAIpAxg3AxggAyACKQMgNwMgIAMgAikDKDcDKCADIAIpAzA3AzAgAyACKQM4NwM4IAMgAikDQDcDQCADEBsgBCADKQMANwMAIAQgAykDCDcDCCAEIAMpAxA3AxAgBCADKQMYNwMYIAQgAykDIDcDICAEIAMpAyg3AyggBCADKQMwNwMwIAQgAykDODcDOCAEIAMpA0A3A0AgBCAHEBcgBBAbIAAgBSkCADcCACAAIAUpAgg3AgggACAFKQIQNwIQIAAgBSkCGDcCGCAAIAUpAiA3AiAgACAFKQIoNwIoIAAgBSkCMDcCMCAAIAUpAjg3AjggACAFKQJANwJAIABByABqIgEgBCkCADcCACABIAQpAgg3AgggASAEKQIQNwIQIAEgBCkCGDcCGCABIAQpAiA3AiAgASAEKQIoNwIoIAEgBCkCMDcCMCABIAQpAjg3AjggASAEKQJANwJAIABBADoAkAEgCSQCCwsLhC0BDX8CQCMCIQwjAkHQCWokAiAMQbgIaiEDIAxB4AZqIQIgACgCkAFBAUYEQCAAKAKUAUUEQCABLACQASEHIAMgAUGQARA8GiAHQQFxBEAgAkGICikDADcDACACQZAKKQMANwMIIAJBmAopAwA3AxAgAkGgCikDADcDGCACQagKKQMANwMgIAJBsAopAwA3AyggAkG4CikDADcDMCACQcAKKQMANwM4IAJByAopAwA3A0AgAkHIAGoiAUGICikDADcDACABQZAKKQMANwMIIAFBmAopAwA3AxAgAUGgCikDADcDGCABQagKKQMANwMgIAFBsAopAwA3AyggAUG4CikDADcDMCABQcAKKQMANwM4IAFByAopAwA3A0AgAkGQAWoiAUHYDCkCADcCACABQeAMKQIANwIIIAFB6AwpAgA3AhAgAUHwDCkCADcCGCABQfgMKQIANwIgIAFBgA0pAgA3AiggAUGIDSkCADcCMCABQZANKQIANwI4IAFBmA0pAgA3AkAFIAIgAykDADcDACACIAMpAwg3AwggAiADKQMQNwMQIAIgAykDGDcDGCACIAMpAyA3AyAgAiADKQMoNwMoIAIgAykDMDcDMCACIAMpAzg3AzggAiADKQNANwNAIAJByABqIgEgA0HIAGoiBykDADcDACABIAcpAwg3AwggASAHKQMQNwMQIAEgBykDGDcDGCABIAcpAyA3AyAgASAHKQMoNwMoIAEgBykDMDcDMCABIAcpAzg3AzggASAHKQNANwNAIAJBkAFqIgFBiAopAwA3AwAgAUGQCikDADcDCCABQZgKKQMANwMQIAFBoAopAwA3AxggAUGoCikDADcDICABQbAKKQMANwMoIAFBuAopAwA3AzAgAUHACikDADcDOCABQcgKKQMANwNACyAAIAJB2AEQPBogDCQCDwsLIAEsAJABBEAgDCQCDwsgAyAAQZABaiIKKQIANwIAIAMgCikCCDcCCCADIAopAhA3AhAgAyAKKQIYNwIYIAMgCikCIDcCICADIAopAig3AiggAyAKKQIwNwIwIAMgCikCODcCOCADIAopAkA3AkAgAyAKEBcgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0AgAhAbIAwiByACKQMANwMAIAcgAikDCDcDCCAHIAIpAxA3AxAgByACKQMYNwMYIAcgAikDIDcDICAHIAIpAyg3AyggByACKQMwNwMwIAcgAikDODcDOCAHIAIpA0A3A0AgAyABKQIANwIAIAMgASkCCDcCCCADIAEpAhA3AhAgAyABKQIYNwIYIAMgASkCIDcCICADIAEpAig3AiggAyABKQIwNwIwIAMgASkCODcCOCADIAEpAkA3AkAgAyAHEBcgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0AgAhAbIAxByABqIgQgAikDADcDACAEIAIpAwg3AwggBCACKQMQNwMQIAQgAikDGDcDGCAEIAIpAyA3AyAgBCACKQMoNwMoIAQgAikDMDcDMCAEIAIpAzg3AzggBCACKQNANwNAIAMgAUHIAGoiASkCADcCACADIAEpAgg3AgggAyABKQIQNwIQIAMgASkCGDcCGCADIAEpAiA3AiAgAyABKQIoNwIoIAMgASkCMDcCMCADIAEpAjg3AjggAyABKQJANwJAIAMgBxAXIAIgAykDADcDACACIAMpAwg3AwggAiADKQMQNwMQIAIgAykDGDcDGCACIAMpAyA3AyAgAiADKQMoNwMoIAIgAykDMDcDMCACIAMpAzg3AzggAiADKQNANwNAIAIQGyAMQZABaiIBIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABIAoQFyABEBsgAyAAKQIANwIAIAMgACkCCDcCCCADIAApAhA3AhAgAyAAKQIYNwIYIAMgACkCIDcCICADIAApAig3AiggAyAAKQIwNwIwIAMgACkCODcCOCADIAApAkA3AkAgAyAEEBYgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0AgAiwARARAIAJBwAkQFQsgDEHYAWoiCSACKQMANwMAIAkgAikDCDcDCCAJIAIpAxA3AxAgCSACKQMYNwMYIAkgAikDIDcDICAJIAIpAyg3AyggCSACKQMwNwMwIAkgAikDODcDOCAJIAIpA0A3A0AgAyAAQcgAaiIEKQIANwIAIAMgBCkCCDcCCCADIAQpAhA3AhAgAyAEKQIYNwIYIAMgBCkCIDcCICADIAQpAig3AiggAyAEKQIwNwIwIAMgBCkCODcCOCADIAQpAkA3AkAgAyABEBYgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0AgAiwARARAIAJBwAkQFQsgDEGgAmoiBSACKQMANwMAIAUgAikDCDcDCCAFIAIpAxA3AxAgBSACKQMYNwMYIAUgAikDIDcDICAFIAIpAyg3AyggBSACKQMwNwMwIAUgAikDODcDOCAFIAIpA0A3A0AgCSgCAEEBRgRAIAkoAgRFBEACQAJAIAUoAgBBAUcNACAFKAIEDQAgABAkDAELIABBiAopAgA3AgAgAEGQCikCADcCCCAAQZgKKQIANwIQIABBoAopAgA3AhggAEGoCikCADcCICAAQbAKKQIANwIoIABBuAopAgA3AjAgAEHACikCADcCOCAAQcgKKQIANwJAIARBiAopAgA3AgAgBEGQCikCADcCCCAEQZgKKQIANwIQIARBoAopAgA3AhggBEGoCikCADcCICAEQbAKKQIANwIoIARBuAopAgA3AjAgBEHACikCADcCOCAEQcgKKQIANwJAIApB2AwpAgA3AgAgCkHgDCkCADcCCCAKQegMKQIANwIQIApB8AwpAgA3AhggCkH4DCkCADcCICAKQYANKQIANwIoIApBiA0pAgA3AjAgCkGQDSkCADcCOCAKQZgNKQIANwJACyAMJAIPCwsgDEHQBWohBiADIAkpAwA3AwAgAyAJKQMINwMIIAMgCSkDEDcDECADIAkpAxg3AxggAyAJKQMgNwMgIAMgCSkDKDcDKCADIAkpAzA3AzAgAyAJKQM4NwM4IAMgCSkDQDcDQCADIAkQFyACIAMpAwA3AwAgAiADKQMINwMIIAIgAykDEDcDECACIAMpAxg3AxggAiADKQMgNwMgIAIgAykDKDcDKCACIAMpAzA3AzAgAiADKQM4NwM4IAIgAykDQDcDQCACEBsgDEHoAmoiASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgAyAAKQIANwIAIAMgACkCCDcCCCADIAApAhA3AhAgAyAAKQIYNwIYIAMgACkCIDcCICADIAApAig3AiggAyAAKQIwNwIwIAMgACkCODcCOCADIAApAkA3AkAgAyABEBcgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0AgAhAbIAxBsANqIgsgAikDADcDACALIAIpAwg3AwggCyACKQMQNwMQIAsgAikDGDcDGCALIAIpAyA3AyAgCyACKQMoNwMoIAsgAikDMDcDMCALIAIpAzg3AzggCyACKQNANwNAIAMgASkDADcDACADIAEpAwg3AwggAyABKQMQNwMQIAMgASkDGDcDGCADIAEpAyA3AyAgAyABKQMoNwMoIAMgASkDMDcDMCADIAEpAzg3AzggAyABKQNANwNAIAMgCRAXIAIgAykDADcDACACIAMpAwg3AwggAiADKQMQNwMQIAIgAykDGDcDGCACIAMpAyA3AyAgAiADKQMoNwMoIAIgAykDMDcDMCACIAMpAzg3AzggAiADKQNANwNAIAIQGyAMQfgDaiINIAIpAwA3AwAgDSACKQMINwMIIA0gAikDEDcDECANIAIpAxg3AxggDSACKQMgNwMgIA0gAikDKDcDKCANIAIpAzA3AzAgDSACKQM4NwM4IA0gAikDQDcDQCADIAUpAwA3AwAgAyAFKQMINwMIIAMgBSkDEDcDECADIAUpAxg3AxggAyAFKQMgNwMgIAMgBSkDKDcDKCADIAUpAzA3AzAgAyAFKQM4NwM4IAMgBSkDQDcDQCADIAUQFyACIAMpAwA3AwAgAiADKQMINwMIIAIgAykDEDcDECACIAMpAxg3AxggAiADKQMgNwMgIAIgAykDKDcDKCACIAMpAzA3AzAgAiADKQM4NwM4IAIgAykDQDcDQCACEBsgDEGYBmoiCCACKQMANwMAIAggAikDCDcDCCAIIAIpAxA3AxAgCCACKQMYNwMYIAggAikDIDcDICAIIAIpAyg3AyggCCACKQMwNwMwIAggAikDODcDOCAIIAIpA0A3A0AgAyAIKQMANwMAIAMgCCkDCDcDCCADIAgpAxA3AxAgAyAIKQMYNwMYIAMgCCkDIDcDICADIAgpAyg3AyggAyAIKQMwNwMwIAMgCCkDODcDOCADIAgpA0A3A0AgAyANEBUgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0ACQAJAIAIoAgAiAUEIRgRAQQghBwJAAkACQANAIAdBf2ohASAHRQ0FIAFBEE8NASACQQRqIAFBAnRqKAIAIgcgAUECdEHECWooAgAiDkcNAiABIQcMAAsAC0G8CyABQRAQKAwBCyAHIA5PDQILBSABQQhPDQELDAELIAJBwAkQFgsgBiACKQMANwMAIAYgAikDCDcDCCAGIAIpAxA3AxAgBiACKQMYNwMYIAYgAikDIDcDICAGIAIpAyg3AyggBiACKQMwNwMwIAYgAikDODcDOCAGIAIpA0A3A0AgAyAGKQMANwMAIAMgBikDCDcDCCADIAYpAxA3AxAgAyAGKQMYNwMYIAMgBikDIDcDICADIAYpAyg3AyggAyAGKQMwNwMwIAMgBikDODcDOCADIAYpA0A3A0AgAyALEBYgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0AgAiALEBYgAkHEAGoiASwAAARAA0AgAkHACRAVIAEsAAANAAsLIAxBiAVqIgEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAIAAgASkCADcCACAAIAEpAgg3AgggACABKQIQNwIQIAAgASkCGDcCGCAAIAEpAiA3AiAgACABKQIoNwIoIAAgASkCMDcCMCAAIAEpAjg3AjggACABKQJANwJAIAMgCykDADcDACADIAspAwg3AwggAyALKQMQNwMQIAMgCykDGDcDGCADIAspAyA3AyAgAyALKQMoNwMoIAMgCykDMDcDMCADIAspAzg3AzggAyALKQNANwNAIAMgABAWIAIgAykDADcDACACIAMpAwg3AwggAiADKQMQNwMQIAIgAykDGDcDGCACIAMpAyA3AyAgAiADKQMoNwMoIAIgAykDMDcDMCACIAMpAzg3AzggAiADKQNANwNAIAIsAEQEQCACQcAJEBULIAYgAikDADcDACAGIAIpAwg3AwggBiACKQMQNwMQIAYgAikDGDcDGCAGIAIpAyA3AyAgBiACKQMoNwMoIAYgAikDMDcDMCAGIAIpAzg3AzggBiACKQNANwNAIAMgBSkDADcDACADIAUpAwg3AwggAyAFKQMQNwMQIAMgBSkDGDcDGCADIAUpAyA3AyAgAyAFKQMoNwMoIAMgBSkDMDcDMCADIAUpAzg3AzggAyAFKQNANwNAIAMgBhAXIAIgAykDADcDACACIAMpAwg3AwggAiADKQMQNwMQIAIgAykDGDcDGCACIAMpAyA3AyAgAiADKQMoNwMoIAIgAykDMDcDMCACIAMpAzg3AzggAiADKQNANwNAIAIQGyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCADIAQpAgA3AgAgAyAEKQIINwIIIAMgBCkCEDcCECADIAQpAhg3AhggAyAEKQIgNwIgIAMgBCkCKDcCKCADIAQpAjA3AjAgAyAEKQI4NwI4IAMgBCkCQDcCQCADIA0QFyACIAMpAwA3AwAgAiADKQMINwMIIAIgAykDEDcDECACIAMpAxg3AxggAiADKQMgNwMgIAIgAykDKDcDKCACIAMpAzA3AzAgAiADKQM4NwM4IAIgAykDQDcDQCACEBsgCCACKQMANwMAIAggAikDCDcDCCAIIAIpAxA3AxAgCCACKQMYNwMYIAggAikDIDcDICAIIAIpAyg3AyggCCACKQMwNwMwIAggAikDODcDOCAIIAIpA0A3A0AgAyABKQMANwMAIAMgASkDCDcDCCADIAEpAxA3AxAgAyABKQMYNwMYIAMgASkDIDcDICADIAEpAyg3AyggAyABKQMwNwMwIAMgASkDODcDOCADIAEpA0A3A0AgAyAIEBYgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0AgAiwARARAIAJBwAkQFQsgDEHABGoiACACKQMANwMAIAAgAikDCDcDCCAAIAIpAxA3AxAgACACKQMYNwMYIAAgAikDIDcDICAAIAIpAyg3AyggACACKQMwNwMwIAAgAikDODcDOCAAIAIpA0A3A0AgBCAAKQIANwIAIAQgACkCCDcCCCAEIAApAhA3AhAgBCAAKQIYNwIYIAQgACkCIDcCICAEIAApAig3AiggBCAAKQIwNwIwIAQgACkCODcCOCAEIAApAkA3AkAgCiAJEBcgChAbIAwkAgsLklcBE38CQCMCIREjAkHwB2okAiAAKAKQAUEBRiIIBEAgACgClAFFBEAgESQCDwsLIBFBqAdqIQIgEUHgBmohASARQZgGaiEDIBFB0AVqIQUgEUGIBWohBiARQcAEaiEOIBFB+ANqIQcgEUGwA2ohCyARQegCaiENIBFBoAJqIQQgEUHYAWohCSARQZABaiEKIBFByABqIRAgESEPIABBkAFqIRICfwJAIAhFDQAgACgClAFBAUcNACACIAApAgA3AgAgAiAAKQIINwIIIAIgACkCEDcCECACIAApAhg3AhggAiAAKQIgNwIgIAIgACkCKDcCKCACIAApAjA3AjAgAiAAKQI4NwI4IAIgACkCQDcCQCACIAAQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgCSABKQMANwMAIAkgASkDCDcDCCAJIAEpAxA3AxAgCSABKQMYNwMYIAkgASkDIDcDICAJIAEpAyg3AyggCSABKQMwNwMwIAkgASkDODcDOCAJIAEpA0A3A0AgAiAAQcgAaiIMKQIANwIAIAIgDCkCCDcCCCACIAwpAhA3AhAgAiAMKQIYNwIYIAIgDCkCIDcCICACIAwpAig3AiggAiAMKQIwNwIwIAIgDCkCODcCOCACIAwpAkA3AkAgAiAMEBcgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgARAbIAQgASkDADcDACAEIAEpAwg3AwggBCABKQMQNwMQIAQgASkDGDcDGCAEIAEpAyA3AyAgBCABKQMoNwMoIAQgASkDMDcDMCAEIAEpAzg3AzggBCABKQNANwNAIAIgBCkDADcDACACIAQpAwg3AwggAiAEKQMQNwMQIAIgBCkDGDcDGCACIAQpAyA3AyAgAiAEKQMoNwMoIAIgBCkDMDcDMCACIAQpAzg3AzggAiAEKQNANwNAIAIgBBAXIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAIAEQGyANIAEpAwA3AwAgDSABKQMINwMIIA0gASkDEDcDECANIAEpAxg3AxggDSABKQMgNwMgIA0gASkDKDcDKCANIAEpAzA3AzAgDSABKQM4NwM4IA0gASkDQDcDQCACIAApAgA3AgAgAiAAKQIINwIIIAIgACkCEDcCECACIAApAhg3AhggAiAAKQIgNwIgIAIgACkCKDcCKCACIAApAjA3AjAgAiAAKQI4NwI4IAIgACkCQDcCQCACIAQQFSABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQAJAAkAgASgCACIEQQhGBEBBCCEIAkACQAJAA0AgCEF/aiEEIAhFDQUgBEEQTw0BIAFBBGogBEECdGooAgAiCCAEQQJ0QcQJaigCACITRw0CIAQhCAwACwALQbwLIARBEBAoDAELIAggE08NAgsFIARBCE8NAQsMAQsgAUHACRAWCyADIAEpAwA3AwAgAyABKQMINwMIIAMgASkDEDcDECADIAEpAxg3AxggAyABKQMgNwMgIAMgASkDKDcDKCADIAEpAzA3AzAgAyABKQM4NwM4IAMgASkDQDcDQCACIAMpAwA3AwAgAiADKQMINwMIIAIgAykDEDcDECACIAMpAxg3AxggAiADKQMgNwMgIAIgAykDKDcDKCACIAMpAzA3AzAgAiADKQM4NwM4IAIgAykDQDcDQCACIAMQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgBSABKQMANwMAIAUgASkDCDcDCCAFIAEpAxA3AxAgBSABKQMYNwMYIAUgASkDIDcDICAFIAEpAyg3AyggBSABKQMwNwMwIAUgASkDODcDOCAFIAEpA0A3A0AgAiAFKQMANwMAIAIgBSkDCDcDCCACIAUpAxA3AxAgAiAFKQMYNwMYIAIgBSkDIDcDICACIAUpAyg3AyggAiAFKQMwNwMwIAIgBSkDODcDOCACIAUpA0A3A0AgAiAJEBYgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgASwARARAIAFBwAkQFQsgBiABKQMANwMAIAYgASkDCDcDCCAGIAEpAxA3AxAgBiABKQMYNwMYIAYgASkDIDcDICAGIAEpAyg3AyggBiABKQMwNwMwIAYgASkDODcDOCAGIAEpA0A3A0AgAiAGKQMANwMAIAIgBikDCDcDCCACIAYpAxA3AxAgAiAGKQMYNwMYIAIgBikDIDcDICACIAYpAyg3AyggAiAGKQMwNwMwIAIgBikDODcDOCACIAYpA0A3A0AgAiANEBYgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgASwARARAIAFBwAkQFQsgCyABKQMANwMAIAsgASkDCDcDCCALIAEpAxA3AxAgCyABKQMYNwMYIAsgASkDIDcDICALIAEpAyg3AyggCyABKQMwNwMwIAsgASkDODcDOCALIAEpA0A3A0AgCxAaIAIgCSkDADcDACACIAkpAwg3AwggAiAJKQMQNwMQIAIgCSkDGDcDGCACIAkpAyA3AyAgAiAJKQMoNwMoIAIgCSkDMDcDMCACIAkpAzg3AzggAiAJKQNANwNAIAIgCRAVIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAAkACQCABKAIAIgRBCEYEQEEIIQgCQAJAAkADQCAIQX9qIQQgCEUNBSAEQRBPDQEgAUEEaiAEQQJ0aigCACIIIARBAnRBxAlqKAIAIhNHDQIgBCEIDAALAAtBvAsgBEEQECgMAQsgCCATTw0CCwUgBEEITw0BCwwBCyABQcAJEBYLIAMgASkDADcDACADIAEpAwg3AwggAyABKQMQNwMQIAMgASkDGDcDGCADIAEpAyA3AyAgAyABKQMoNwMoIAMgASkDMDcDMCADIAEpAzg3AzggAyABKQNANwNAIAIgAykDADcDACACIAMpAwg3AwggAiADKQMQNwMQIAIgAykDGDcDGCACIAMpAyA3AyAgAiADKQMoNwMoIAIgAykDMDcDMCACIAMpAzg3AzggAiADKQNANwNAIAIgCRAVIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAAkACQCABKAIAIgRBCEYEQEEIIQgCQAJAAkADQCAIQX9qIQQgCEUNBSAEQRBPDQEgAUEEaiAEQQJ0aigCACIIIARBAnRBxAlqKAIAIglHDQIgBCEIDAALAAtBvAsgBEEQECgMAQsgCCAJTw0CCwUgBEEITw0BCwwBCyABQcAJEBYLIAcgASkDADcDACAHIAEpAwg3AwggByABKQMQNwMQIAcgASkDGDcDGCAHIAEpAyA3AyAgByABKQMoNwMoIAcgASkDMDcDMCAHIAEpAzg3AzggByABKQNANwNAIAIgBykDADcDACACIAcpAwg3AwggAiAHKQMQNwMQIAIgBykDGDcDGCACIAcpAyA3AyAgAiAHKQMoNwMoIAIgBykDMDcDMCACIAcpAzg3AzggAiAHKQNANwNAIAIgBxAXIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAIAEQGyADIAEpAwA3AwAgAyABKQMINwMIIAMgASkDEDcDECADIAEpAxg3AxggAyABKQMgNwMgIAMgASkDKDcDKCADIAEpAzA3AzAgAyABKQM4NwM4IAMgASkDQDcDQCACIAMpAwA3AwAgAiADKQMINwMIIAIgAykDEDcDECACIAMpAxg3AxggAiADKQMgNwMgIAIgAykDKDcDKCACIAMpAzA3AzAgAiADKQM4NwM4IAIgAykDQDcDQCACIAsQFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyAFIAEpAwA3AwAgBSABKQMINwMIIAUgASkDEDcDECAFIAEpAxg3AxggBSABKQMgNwMgIAUgASkDKDcDKCAFIAEpAzA3AzAgBSABKQM4NwM4IAUgASkDQDcDQCACIAUpAwA3AwAgAiAFKQMINwMIIAIgBSkDEDcDECACIAUpAxg3AxggAiAFKQMgNwMgIAIgBSkDKDcDKCACIAUpAzA3AzAgAiAFKQM4NwM4IAIgBSkDQDcDQCACIAsQFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyAOIAEpAwA3AwAgDiABKQMINwMIIA4gASkDEDcDECAOIAEpAxg3AxggDiABKQMgNwMgIA4gASkDKDcDKCAOIAEpAzA3AzAgDiABKQM4NwM4IA4gASkDQDcDQCAGIA0pAwA3AwAgBiANKQMINwMIIAYgDSkDEDcDECAGIA0pAxg3AxggBiANKQMgNwMgIAYgDSkDKDcDKCAGIA0pAzA3AzAgBiANKQM4NwM4IAYgDSkDQDcDQCAGEBogBhAaIAYQGiAPIA4pAwA3AwAgDyAOKQMINwMIIA8gDikDEDcDECAPIA4pAxg3AxggDyAOKQMgNwMgIA8gDikDKDcDKCAPIA4pAzA3AzAgDyAOKQM4NwM4IA8gDikDQDcDQCACIAspAwA3AwAgAiALKQMINwMIIAIgCykDEDcDECACIAspAxg3AxggAiALKQMgNwMgIAIgCykDKDcDKCACIAspAzA3AzAgAiALKQM4NwM4IAIgCykDQDcDQCACIA4QFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyADIAEpAwA3AwAgAyABKQMINwMIIAMgASkDEDcDECADIAEpAxg3AxggAyABKQMgNwMgIAMgASkDKDcDKCADIAEpAzA3AzAgAyABKQM4NwM4IAMgASkDQDcDQCACIAcpAwA3AwAgAiAHKQMINwMIIAIgBykDEDcDECACIAcpAxg3AxggAiAHKQMgNwMgIAIgBykDKDcDKCACIAcpAzA3AzAgAiAHKQM4NwM4IAIgBykDQDcDQCACIAMQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgBSABKQMANwMAIAUgASkDCDcDCCAFIAEpAxA3AxAgBSABKQMYNwMYIAUgASkDIDcDICAFIAEpAyg3AyggBSABKQMwNwMwIAUgASkDODcDOCAFIAEpA0A3A0AgAiAFKQMANwMAIAIgBSkDCDcDCCACIAUpAxA3AxAgAiAFKQMYNwMYIAIgBSkDIDcDICACIAUpAyg3AyggAiAFKQMwNwMwIAIgBSkDODcDOCACIAUpA0A3A0AgAiAGEBYgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgASwARARAIAFBwAkQFQsgECABKQMANwMAIBAgASkDCDcDCCAQIAEpAxA3AxAgECABKQMYNwMYIBAgASkDIDcDICAQIAEpAyg3AyggECABKQMwNwMwIBAgASkDODcDOCAQIAEpA0A3A0AgAiAMKQIANwIAIAIgDCkCCDcCCCACIAwpAhA3AhAgAiAMKQIYNwIYIAIgDCkCIDcCICACIAwpAig3AiggAiAMKQIwNwIwIAIgDCkCODcCOCACIAwpAkA3AkAgAiAMEBUgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0ACQAJAIAEoAgAiBEEIRgRAQQghCAJAAkACQANAIAhBf2ohBCAIRQ0FIARBEE8NASABQQRqIARBAnRqKAIAIgggBEECdEHECWooAgAiAkcNAiAEIQgMAAsAC0G8CyAEQRAQKAwBCyAIIAJPDQILBSAEQQhPDQELDAELIAFBwAkQFgsgCiABKQMANwMAIAogASkDCDcDCCAKIAEpAxA3AxAgCiABKQMYNwMYIAogASkDIDcDICAKIAEpAyg3AyggCiABKQMwNwMwIAogASkDODcDOCAKIAEpA0A3A0AgDAwBCyACIAApAgA3AgAgAiAAKQIINwIIIAIgACkCEDcCECACIAApAhg3AhggAiAAKQIgNwIgIAIgACkCKDcCKCACIAApAjA3AjAgAiAAKQI4NwI4IAIgACkCQDcCQCACIAAQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgCSABKQMANwMAIAkgASkDCDcDCCAJIAEpAxA3AxAgCSABKQMYNwMYIAkgASkDIDcDICAJIAEpAyg3AyggCSABKQMwNwMwIAkgASkDODcDOCAJIAEpA0A3A0AgAiAAQcgAaiIMKQIANwIAIAIgDCkCCDcCCCACIAwpAhA3AhAgAiAMKQIYNwIYIAIgDCkCIDcCICACIAwpAig3AiggAiAMKQIwNwIwIAIgDCkCODcCOCACIAwpAkA3AkAgAiAMEBcgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgARAbIAQgASkDADcDACAEIAEpAwg3AwggBCABKQMQNwMQIAQgASkDGDcDGCAEIAEpAyA3AyAgBCABKQMoNwMoIAQgASkDMDcDMCAEIAEpAzg3AzggBCABKQNANwNAIAIgBCkDADcDACACIAQpAwg3AwggAiAEKQMQNwMQIAIgBCkDGDcDGCACIAQpAyA3AyAgAiAEKQMoNwMoIAIgBCkDMDcDMCACIAQpAzg3AzggAiAEKQNANwNAIAIgBBAXIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAIAEQGyANIAEpAwA3AwAgDSABKQMINwMIIA0gASkDEDcDECANIAEpAxg3AxggDSABKQMgNwMgIA0gASkDKDcDKCANIAEpAzA3AzAgDSABKQM4NwM4IA0gASkDQDcDQCACIAApAgA3AgAgAiAAKQIINwIIIAIgACkCEDcCECACIAApAhg3AhggAiAAKQIgNwIgIAIgACkCKDcCKCACIAApAjA3AjAgAiAAKQI4NwI4IAIgACkCQDcCQCACIAQQFSABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQAJAAkAgASgCACIEQQhGBEBBCCEIAkACQAJAA0AgCEF/aiEEIAhFDQUgBEEQTw0BIAFBBGogBEECdGooAgAiCCAEQQJ0QcQJaigCACITRw0CIAQhCAwACwALQbwLIARBEBAoDAELIAggE08NAgsFIARBCE8NAQsMAQsgAUHACRAWCyADIAEpAwA3AwAgAyABKQMINwMIIAMgASkDEDcDECADIAEpAxg3AxggAyABKQMgNwMgIAMgASkDKDcDKCADIAEpAzA3AzAgAyABKQM4NwM4IAMgASkDQDcDQCACIAMpAwA3AwAgAiADKQMINwMIIAIgAykDEDcDECACIAMpAxg3AxggAiADKQMgNwMgIAIgAykDKDcDKCACIAMpAzA3AzAgAiADKQM4NwM4IAIgAykDQDcDQCACIAMQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgBSABKQMANwMAIAUgASkDCDcDCCAFIAEpAxA3AxAgBSABKQMYNwMYIAUgASkDIDcDICAFIAEpAyg3AyggBSABKQMwNwMwIAUgASkDODcDOCAFIAEpA0A3A0AgAiAFKQMANwMAIAIgBSkDCDcDCCACIAUpAxA3AxAgAiAFKQMYNwMYIAIgBSkDIDcDICACIAUpAyg3AyggAiAFKQMwNwMwIAIgBSkDODcDOCACIAUpA0A3A0AgAiAJEBYgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgASwARARAIAFBwAkQFQsgBiABKQMANwMAIAYgASkDCDcDCCAGIAEpAxA3AxAgBiABKQMYNwMYIAYgASkDIDcDICAGIAEpAyg3AyggBiABKQMwNwMwIAYgASkDODcDOCAGIAEpA0A3A0AgAiAGKQMANwMAIAIgBikDCDcDCCACIAYpAxA3AxAgAiAGKQMYNwMYIAIgBikDIDcDICACIAYpAyg3AyggAiAGKQMwNwMwIAIgBikDODcDOCACIAYpA0A3A0AgAiANEBYgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgASwARARAIAFBwAkQFQsgCyABKQMANwMAIAsgASkDCDcDCCALIAEpAxA3AxAgCyABKQMYNwMYIAsgASkDIDcDICALIAEpAyg3AyggCyABKQMwNwMwIAsgASkDODcDOCALIAEpA0A3A0AgCxAaIAIgCSkDADcDACACIAkpAwg3AwggAiAJKQMQNwMQIAIgCSkDGDcDGCACIAkpAyA3AyAgAiAJKQMoNwMoIAIgCSkDMDcDMCACIAkpAzg3AzggAiAJKQNANwNAIAIgCRAVIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAAkACQCABKAIAIgRBCEYEQEEIIQgCQAJAAkADQCAIQX9qIQQgCEUNBSAEQRBPDQEgAUEEaiAEQQJ0aigCACIIIARBAnRBxAlqKAIAIhNHDQIgBCEIDAALAAtBvAsgBEEQECgMAQsgCCATTw0CCwUgBEEITw0BCwwBCyABQcAJEBYLIAMgASkDADcDACADIAEpAwg3AwggAyABKQMQNwMQIAMgASkDGDcDGCADIAEpAyA3AyAgAyABKQMoNwMoIAMgASkDMDcDMCADIAEpAzg3AzggAyABKQNANwNAIAIgAykDADcDACACIAMpAwg3AwggAiADKQMQNwMQIAIgAykDGDcDGCACIAMpAyA3AyAgAiADKQMoNwMoIAIgAykDMDcDMCACIAMpAzg3AzggAiADKQNANwNAIAIgCRAVIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAAkACQCABKAIAIgRBCEYEQEEIIQgCQAJAAkADQCAIQX9qIQQgCEUNBSAEQRBPDQEgAUEEaiAEQQJ0aigCACIIIARBAnRBxAlqKAIAIglHDQIgBCEIDAALAAtBvAsgBEEQECgMAQsgCCAJTw0CCwUgBEEITw0BCwwBCyABQcAJEBYLIAcgASkDADcDACAHIAEpAwg3AwggByABKQMQNwMQIAcgASkDGDcDGCAHIAEpAyA3AyAgByABKQMoNwMoIAcgASkDMDcDMCAHIAEpAzg3AzggByABKQNANwNAIAIgBykDADcDACACIAcpAwg3AwggAiAHKQMQNwMQIAIgBykDGDcDGCACIAcpAyA3AyAgAiAHKQMoNwMoIAIgBykDMDcDMCACIAcpAzg3AzggAiAHKQNANwNAIAIgBxAXIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAIAEQGyAOIAEpAwA3AwAgDiABKQMINwMIIA4gASkDEDcDECAOIAEpAxg3AxggDiABKQMgNwMgIA4gASkDKDcDKCAOIAEpAzA3AzAgDiABKQM4NwM4IA4gASkDQDcDQCAGIA0pAwA3AwAgBiANKQMINwMIIAYgDSkDEDcDECAGIA0pAxg3AxggBiANKQMgNwMgIAYgDSkDKDcDKCAGIA0pAzA3AzAgBiANKQM4NwM4IAYgDSkDQDcDQCAGEBogBhAaIAYQGiACIA4pAwA3AwAgAiAOKQMINwMIIAIgDikDEDcDECACIA4pAxg3AxggAiAOKQMgNwMgIAIgDikDKDcDKCACIA4pAzA3AzAgAiAOKQM4NwM4IAIgDikDQDcDQCACIAsQFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyADIAEpAwA3AwAgAyABKQMINwMIIAMgASkDEDcDECADIAEpAxg3AxggAyABKQMgNwMgIAMgASkDKDcDKCADIAEpAzA3AzAgAyABKQM4NwM4IAMgASkDQDcDQCACIAMpAwA3AwAgAiADKQMINwMIIAIgAykDEDcDECACIAMpAxg3AxggAiADKQMgNwMgIAIgAykDKDcDKCACIAMpAzA3AzAgAiADKQM4NwM4IAIgAykDQDcDQCACIAsQFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyAPIAEpAwA3AwAgDyABKQMINwMIIA8gASkDEDcDECAPIAEpAxg3AxggDyABKQMgNwMgIA8gASkDKDcDKCAPIAEpAzA3AzAgDyABKQM4NwM4IA8gASkDQDcDQCACIAspAwA3AwAgAiALKQMINwMIIAIgCykDEDcDECACIAspAxg3AxggAiALKQMgNwMgIAIgCykDKDcDKCACIAspAzA3AzAgAiALKQM4NwM4IAIgCykDQDcDQCACIA8QFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyADIAEpAwA3AwAgAyABKQMINwMIIAMgASkDEDcDECADIAEpAxg3AxggAyABKQMgNwMgIAMgASkDKDcDKCADIAEpAzA3AzAgAyABKQM4NwM4IAMgASkDQDcDQCACIAcpAwA3AwAgAiAHKQMINwMIIAIgBykDEDcDECACIAcpAxg3AxggAiAHKQMgNwMgIAIgBykDKDcDKCACIAcpAzA3AzAgAiAHKQM4NwM4IAIgBykDQDcDQCACIAMQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgBSABKQMANwMAIAUgASkDCDcDCCAFIAEpAxA3AxAgBSABKQMYNwMYIAUgASkDIDcDICAFIAEpAyg3AyggBSABKQMwNwMwIAUgASkDODcDOCAFIAEpA0A3A0AgAiAFKQMANwMAIAIgBSkDCDcDCCACIAUpAxA3AxAgAiAFKQMYNwMYIAIgBSkDIDcDICACIAUpAyg3AyggAiAFKQMwNwMwIAIgBSkDODcDOCACIAUpA0A3A0AgAiAGEBYgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgASwARARAIAFBwAkQFQsgECABKQMANwMAIBAgASkDCDcDCCAQIAEpAxA3AxAgECABKQMYNwMYIBAgASkDIDcDICAQIAEpAyg3AyggECABKQMwNwMwIBAgASkDODcDOCAQIAEpA0A3A0AgAiAMKQIANwIAIAIgDCkCCDcCCCACIAwpAhA3AhAgAiAMKQIYNwIYIAIgDCkCIDcCICACIAwpAig3AiggAiAMKQIwNwIwIAIgDCkCODcCOCACIAwpAkA3AkAgAiASEBcgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgARAbIAogASkDADcDACAKIAEpAwg3AwggCiABKQMQNwMQIAogASkDGDcDGCAKIAEpAyA3AyAgCiABKQMoNwMoIAogASkDMDcDMCAKIAEpAzg3AzggCiABKQNANwNAIAIgCikDADcDACACIAopAwg3AwggAiAKKQMQNwMQIAIgCikDGDcDGCACIAopAyA3AyAgAiAKKQMoNwMoIAIgCikDMDcDMCACIAopAzg3AzggAiAKKQNANwNAIAIgChAVIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAAkACQCABKAIAIgRBCEYEQEEIIQgCQAJAAkADQCAIQX9qIQQgCEUNBSAEQRBPDQEgAUEEaiAEQQJ0aigCACIIIARBAnRBxAlqKAIAIgJHDQIgBCEIDAALAAtBvAsgBEEQECgMAQsgCCACTw0CCwUgBEEITw0BCwwBCyABQcAJEBYLIAogASkDADcDACAKIAEpAwg3AwggCiABKQMQNwMQIAogASkDGDcDGCAKIAEpAyA3AyAgCiABKQMoNwMoIAogASkDMDcDMCAKIAEpAzg3AzggCiABKQNANwNAIAwLIQQgACAPKQIANwIAIAAgDykCCDcCCCAAIA8pAhA3AhAgACAPKQIYNwIYIAAgDykCIDcCICAAIA8pAig3AiggACAPKQIwNwIwIAAgDykCODcCOCAAIA8pAkA3AkAgBCAQKQIANwIAIAQgECkCCDcCCCAEIBApAhA3AhAgBCAQKQIYNwIYIAQgECkCIDcCICAEIBApAig3AiggBCAQKQIwNwIwIAQgECkCODcCOCAEIBApAkA3AkAgEiAKKQIANwIAIBIgCikCCDcCCCASIAopAhA3AhAgEiAKKQIYNwIYIBIgCikCIDcCICASIAopAig3AiggEiAKKQIwNwIwIBIgCikCODcCOCASIAopAkA3AkAgESQCCwukBAEQfwJ/IwIhAyMCQZABaiQCIAFBIEcEQCADJAJBAA8LIAAoAhwQOyEBIAAoAhgiAhA7IQQgACgCFCIFEDshByAAKAIQIggQOyEJIAAoAgwiChA7IQsgACgCCCIMEDshDSAAKAIEIg4QOyEPIAAoAgAiEBA7IREgA0HIAGoiAEEAOgBEIABBCDYCACAAIAE2AgQgACAENgIIIAAgBzYCDCAAIAk2AhAgACALNgIUIAAgDTYCGCAAIA82AhwgACARNgIgIABBJGoiAUIANwIAIAFCADcCCCABQgA3AhAgAUIANwIYIAAgEAR/QQgFIA4Ef0EHBSAMBH9BBgUgCgR/QQUFIAgEf0EEBSAFBH9BAwUgAgR/QQIFQQELCwsLCwsLIgE2AgAgAyICIAApAwA3AwAgAiAAKQMINwMIIAIgACkDEDcDECACIAApAxg3AxggAiAAKQMgNwMgIAIgACkDKDcDKCACIAApAzA3AzAgAiAAKQM4NwM4IAIgACkDQDcDQAJAAkACQCACKAIAIgRBCEYEQEEIIQECQAJAAkADQCABQX9qIQAgAUUNBiAAQRBPDQEgAkEEaiAAQQJ0aigCACIBIABBAnRB7ApqKAIAIgVHDQIgACEBDAALAAtBvAsgAEEQECgMAQsgASAFSQ0CDAMLBSAEQQhJDQEMAgsMAgsgBEEBRyACKAIEQQBHckUNAEEBIQYMAQtBACEGCyADJAIgBgsLvQYBD38CQCMCIQgjAkHgAWokAiADQSBJBEBBICADECcLIAghBSACKAIcEDshCSACKAIYEDshCiACKAIUEDshCyACKAIQEDshDCACKAIMEDshDSACKAIIEDshDiACKAIEEDshDyACKAIAEDshBiAIQcgAaiIEQQA6AEQgBCADQQJ2IgI2AgAgBCAJNgIEIAQgCjYCCCAEIAs2AgwgBCAMNgIQIAQgDTYCFCAEIA42AhggBCAPNgIcIAQgBjYCICAEQSRqIgNCADcCACADQgA3AgggA0IANwIQIANCADcCGAJAAkADQAJAIAJBf2oiA0EQTw0CIARBBGogA0ECdGooAgAEQCACIQcMAQsgA0EBSwRAIAMhAgwCBSADIQcLCwsMAQtBsAsgA0EQECgLIAQgBzYCACAFIAQpAwA3AwAgBSAEKQMINwMIIAUgBCkDEDcDECAFIAQpAxg3AxggBSAEKQMgNwMgIAUgBCkDKDcDKCAFIAQpAzA3AzAgBSAEKQM4NwM4IAUgBCkDQDcDQAJAAkAgBSgCACIGQQhGBEBBCCECAkACQAJAA0AgAkF/aiEDIAJFDQYgA0EQTw0BIAVBBGogA0ECdGooAgAiByADQQJ0QewKaigCACICRw0CIAMhAgwACwALQbwLIANBEBAoDAELIAcgAkkNAgsFIAZBCEkNAQsMAQsgBkEBRgRAIAUoAgRFDQELIAQgASAFECAgBCgCBBA7IRAgBCgCCBA7IREgBCgCDBA7IRIgBCgCEBA7IQkgBCgCFBA7IQogBCgCGBA7IQsgBCgCHBA7IQwgBCgCIBA7IQ0gBCgCTBA7IQ4gBCgCUBA7IQ8gBCgCVBA7IQYgBCgCWBA7IQUgBCgCXBA7IQcgBCgCYBA7IQMgBCgCZBA7IQIgBCgCaBA7IQEgAEEBOgAAIABBBDoAASAAIA02AAIgACAMNgAGIAAgCzYACiAAIAo2AA4gACAJNgASIAAgEjYAFiAAIBE2ABogACAQNgAeIAAgATYAIiAAIAI2ACYgACADNgAqIAAgBzYALiAAIAU2ADIgACAGNgA2IAAgDzYAOiAAIA42AD4gCCQCDwsgAEEAOgAAIAgkAgsLdgECfwJAIwIhAiMCQTBqJAIgAkEoaiIDIAA2AgAgAkEsaiIAIAE2AgAgAkEYaiIBIAM2AgAgAUEBNgIEIAEgADYCCCABQQE2AgwgAkGsDzYCACACQQI2AgQgAkEANgIIIAIgATYCECACQQI2AhQgAkG8DxAsCwt1AQJ/AkAjAiEDIwJBMGokAiADQShqIgQgATYCACADQSxqIgEgAjYCACADQRhqIgIgATYCACACQQE2AgQgAiAENgIIIAJBATYCDCADQZwPNgIAIANBAjYCBCADQQA2AgggAyACNgIQIANBAjYCFCADIAAQLAsLDwAgAQR/IAAgAXAFQQALCw8AIAEEfyAAIAFuBUEACwvNAgEHfwJ/IwIhBSMCQTBqJAIgBSEEIAAoAgAiAEGPzgBLBEBBJyEGA0AgAEGQzgAQKSECIABBkM4AECohAyACQeQAECpBAXQhByACQeQAEClBAXQhCCAEIAZBfGoiAmogB0GQF2ouAAA7AAAgBCAGQX5qaiAIQZAXai4AADsAACAAQf/B1y9LBEAgAiEGIAMhAAwBBSADIQALCwVBJyECCyAAQeMASgRAIABB5AAQKUEBdCEDIABB5AAQKiEAIAQgAkF+aiICaiADQZAXai4AADsAAAsgAEEKSAR/IAQgAkF/aiIDaiAAQf8BcUEwajoAACABQQFBrL8BQQAgBCADIgBqQScgAGsQLSEAIAUkAiAABSAEIAJBfmoiA2ogAEEBdEGQF2ouAAA7AAAgAUEBQay/AUEAIAQgAyIAakEnIABrEC0hACAFJAIgAAsLC3QBBH8CQCMCIQIjAkEwaiQCIAEoAgAhAyABKAIEIQQgASgCCCEFIAIiASAAKQIANwIAIAEgACkCCDcCCCABIAApAhA3AhAgAkEYaiIAIAEpAgA3AgAgACABKQIINwIIIAAgASkCEDcCECAAIAMgBCAFEA4LC/cRAQ1/An8jAiEMIwJBEGokAiAAKAIAIQgCQAJAIAEEQCAIQQFxBEBBKyEGDAIFQQAhDkEAIQYgBSEHCwVBLSEGDAELDAELQQEhDiAFQQFqIQcLIAhBBHEEfyACIANqIQsgAwRAIAIhAUEAIQkDQCABLAAAQcABcUGAAUYgCWohCSABQQFqIgEgC0cNAAsFQQAhCQsgByADaiAJayEHQQEFQQALIREgDEEEaiEBIAAoAghFBEAgDkEBRgRAIAAoAhghDSAAKAIcIQogAUEANgIAIAZBgAFJBEAgASAGOgAAQQEhBwUgBkGAEEkEf0FAIQhBASELQQIhByABBSAGQYCABEkEfyABQWA6AABBgH8hCEECIQtBAyEHIAFBAWoFIAFBcDoAACABQYB/OgABQYB/IQhBAyELQQQhByABQQJqCwsiCSAIOgAAIAEgC2ogBkE/cUGAf3I6AAALIA0gASAHIAooAgxBA3FBAmoRAABB/wFxBEAgDCQCQQEPCwsgAEEYaiEBIBEEQCABKAIAIAIgAyAAQRxqIgAoAgAoAgxBA3FBAmoRAABB/wFxBEAgDCQCQQEPCwUgAEEcaiEACyABKAIAIAQgBSAAKAIAKAIMQQNxQQJqEQAAIQAgDCQCIAAPCyAAKAIMIgogB00EQCAOQQFGBEAgACgCGCENIAAoAhwhCiABQQA2AgAgBkGAAUkEQCABIAY6AABBASEHBSAGQYAQSQR/QUAhCEEBIQtBAiEHIAEFIAZBgIAESQR/IAFBYDoAAEGAfyEIQQIhC0EDIQcgAUEBagUgAUFwOgAAIAFBgH86AAFBgH8hCEEDIQtBBCEHIAFBAmoLCyIJIAg6AAAgASALaiAGQT9xQYB/cjoAAAsgDSABIAcgCigCDEEDcUECahEAAEH/AXEEQCAMJAJBAQ8LCyAAQRhqIQEgEQRAIAEoAgAgAiADIABBHGoiACgCACgCDEEDcUECahEAAEH/AXEEQCAMJAJBAQ8LBSAAQRxqIQALIAEoAgAgBCAFIAAoAgAoAgxBA3FBAmoRAAAhACAMJAIgAA8LIAwhCSAIQQhxRQRAIAogB2shBwJAAkACQAJAIAAsADAiCEEDRgR/QQEFIAgLQQNxDgMAAgECCyAHIQhBACEHDAILIAdBAWpBAXYhCCAHQQF2IQcMAQtBACEICyAJQQA2AgAgACgCBCIKQYABSQR/IAkgCjoAAEEBBSAKQYAQSQR/IApBBnZBH3FBQHIhD0EBIRBBAiENIAkFIApBgIAESQR/IAkgCkEMdkEPcUFgcjoAACAKQQZ2QT9xQYB/ciEPQQIhEEEDIQ0gCUEBagUgCSAKQRJ2Qf8BcUFwcjoAACAJIApBDHZBP3FBgH9yOgABIApBBnZBP3FBgH9yIQ9BAyEQQQQhDSAJQQJqCwsiCyAPOgAAIAkgEGogCkE/cUGAf3I6AAAgDQshCyAAQRhqIQ0gAEEcaiEKQQAhAAJAAkADQCAAIAdJBEAgAEEBaiEAIA0oAgAgCSALIAooAgAoAgxBA3FBAmoRAABB/wFxDQIMAQsLDAELIAwkAkEBDwsCQAJAIA5BAUcNACANKAIAIRAgCigCACESIAFBADYCACAGQYABSQRAIAEgBjoAAEEBIQcFIAZBgBBJBH9BQCEOQQEhD0ECIQcgAQUgBkGAgARJBH8gAUFgOgAAQYB/IQ5BAiEPQQMhByABQQFqBSABQXA6AAAgAUGAfzoAAUGAfyEOQQMhD0EEIQcgAUECagsLIgAgDjoAACABIA9qIAZBP3FBgH9yOgAACyAQIAEgByASKAIMQQNxQQJqEQAAQf8BcUUNAAwBCyARBEAgDSgCACACIAMgCigCACgCDEEDcUECahEAAEH/AXENAQsgDSgCACAEIAUgCigCACgCDEEDcUECahEAAEH/AXFFBEBBACEAAkACQANAIAAgCE8NASAAQQFqIQAgDSgCACAJIAsgCigCACgCDEEDcUECahEAAEH/AXFFDQAMAgsACyAMJAJBAA8LIAwkAkEBDwsLIAwkAkEBDwsgAEEEaiIPQTA2AgAgAEEwaiIQQQE6AAAgDkEBRgRAIAAoAhghDiAAKAIcIRIgAUEANgIAIAZBgAFJBEAgASAGOgAAQQEhCAUgBkGAEEkEf0FAIQtBASENQQIhCCABBSAGQYCABEkEfyABQWA6AABBgH8hC0ECIQ1BAyEIIAFBAWoFIAFBcDoAACABQYB/OgABQYB/IQtBAyENQQQhCCABQQJqCwsiCSALOgAAIAEgDWogBkE/cUGAf3I6AAALIA4gASAIIBIoAgxBA3FBAmoRAABB/wFxBEAgDCQCQQEPCwsgEQRAIAAoAhggAiADIAAoAhwoAgxBA3FBAmoRAABB/wFxBEAgDCQCQQEPCwsgCiAHayECAkACQAJAAkAgECwAACIDQQNGBH9BAQUgAwtBA3EOAwACAQILIAIhA0EAIQIMAgsgAkEBakEBdiEDIAJBAXYhAgwBC0EAIQMLIAFBADYCACAPKAIAIgZBgAFJBH8gASAGOgAAQQEFIAZBgBBJBH8gBkEGdkEfcUFAciEIQQEhC0ECIQcgAQUgBkGAgARJBH8gASAGQQx2QQ9xQWByOgAAIAZBBnZBP3FBgH9yIQhBAiELQQMhByABQQFqBSABIAZBEnZB/wFxQXByOgAAIAEgBkEMdkE/cUGAf3I6AAEgBkEGdkE/cUGAf3IhCEEDIQtBBCEHIAFBAmoLCyIJIAg6AAAgASALaiAGQT9xQYB/cjoAACAHCyEJIABBGGohByAAQRxqIQZBACEAAkACQANAIAAgAkkEQCAAQQFqIQAgBygCACABIAkgBigCACgCDEEDcUECahEAAEH/AXENAgwBCwsMAQsgDCQCQQEPCyAHKAIAIAQgBSAGKAIAKAIMQQNxQQJqEQAAQf8BcQRAIAwkAkEBDwVBACEACwJAAkADQCAAIANPDQEgAEEBaiEAIAcoAgAgASAJIAYoAgAoAgxBA3FBAmoRAABB/wFxRQ0ADAILAAsgDCQCQQAPCyAMJAJBAQsLiwEBBn8CQCMCIQEjAkEwaiQCIAAoAgQhAyAAKAIIIQQgACgCDCEFIAAoAhAhBiABQRhqIgIgACgCADYCACACIAM2AgQgASIAIAI2AgAgAEEBNgIEIABBADYCCCAAQfyxATYCECAAQQA2AhQgAUEgaiIBIAQ2AgAgASAFNgIEIAEgBjYCCCAAIAEQLAsLdgECfwJAIwIhAiMCQTBqJAIgAkEoaiIDIAA2AgAgAkEsaiIAIAE2AgAgAkEYaiIBIAM2AgAgAUEBNgIEIAEgADYCCCABQQE2AgwgAkHIDzYCACACQQI2AgQgAkEANgIIIAIgATYCECACQQI2AhQgAkHYDxAsCwswAQJ/An8jAiEBIwJBEGokAiABIgIgACgCPBA4NgIAQQYgAhABEDMhACABJAIgAAsLawEDfwJ/IwIhBCMCQSBqJAIgBCEDIARBEGohBSAAQQM2AiQgACgCAEHAAHFFBEAgAyAAKAI8NgIAIANBk6gBNgIEIAMgBTYCCEE2IAMQBARAIABBfzoASwsLIAAgASACEDchACAEJAIgAAsLZQECfwJ/IwIhBCMCQSBqJAIgBCIDIAAoAjw2AgAgA0EANgIEIAMgATYCCCADIARBFGoiADYCDCADIAI2AhBBjAEgAxACEDNBAEgEfyAAQX82AgBBfwUgACgCAAshACAEJAIgAAsLGgAgAEGAYEsEfxA0QQAgAGs2AgBBfwUgAAsLCAAQNUHAAGoLBAAQNgsFAEHgEAv9AgELfwJ/IwIhBSMCQTBqJAIgBUEQaiEGIAVBIGoiAyAAQRxqIgkoAgAiBDYCACADIABBFGoiCigCACAEayIENgIEIAMgATYCCCADIAI2AgwgBSIBIABBPGoiDCgCADYCACABIAM2AgQgAUECNgIIAkACQCAEIAJqIgRBkgEgARAGEDMiAUYNAEECIQcDQCABQQBOBEAgBCABayEEIANBCGohCCABIAMoAgQiDUsiCwRAIAghAwsgC0EfdEEfdSAHaiEHIAMgAygCACABIAsEfyANBUEAC2siAWo2AgAgA0EEaiIIIAgoAgAgAWs2AgAgBiAMKAIANgIAIAYgAzYCBCAGIAc2AgggBEGSASAGEAYQMyIBRg0CDAELCyAAQQA2AhAgCUEANgIAIApBADYCACAAIAAoAgBBIHI2AgAgB0ECRgR/QQAFIAIgAygCBGsLIQIMAQsgACAAKAIsIgEgACgCMGo2AhAgCSABNgIAIAogATYCAAsgBSQCIAILCwQAIAALUAECfwJ/IAIEfwNAIAAsAAAiAyABLAAAIgRGBEAgAEEBaiEAIAFBAWohAUEAIAJBf2oiAkUNAxoMAQsLIANB/wFxIARB/wFxawVBAAsLIgALnQIBBH8CfyAAIAJqIQQgAUH/AXEhASACQcMATgRAA0AgAEEDcQRAIAAgAToAACAAQQFqIQAMAQsLIARBfHEiBUHAAGshBiABIAFBCHRyIAFBEHRyIAFBGHRyIQMDQCAAIAZMBEAgACADNgIAIAAgAzYCBCAAIAM2AgggACADNgIMIAAgAzYCECAAIAM2AhQgACADNgIYIAAgAzYCHCAAIAM2AiAgACADNgIkIAAgAzYCKCAAIAM2AiwgACADNgIwIAAgAzYCNCAAIAM2AjggACADNgI8IABBwABqIQAMAQsLA0AgACAFSARAIAAgAzYCACAAQQRqIQAMAQsLCwNAIAAgBEgEQCAAIAE6AAAgAEEBaiEADAELCyAEIAJrCwsrACAAQf8BcUEYdCAAQQh1Qf8BcUEQdHIgAEEQdUH/AXFBCHRyIABBGHZyC8kDAQN/An8gAkGAwABOBEAgACABIAIQAw8LIAAhBCAAIAJqIQMgAEEDcSABQQNxRgRAA0AgAEEDcQRAIAJFBEAgBA8LIAAgASwAADoAACAAQQFqIQAgAUEBaiEBIAJBAWshAgwBCwsgA0F8cSICQcAAayEFA0AgACAFTARAIAAgASgCADYCACAAIAEoAgQ2AgQgACABKAIINgIIIAAgASgCDDYCDCAAIAEoAhA2AhAgACABKAIUNgIUIAAgASgCGDYCGCAAIAEoAhw2AhwgACABKAIgNgIgIAAgASgCJDYCJCAAIAEoAig2AiggACABKAIsNgIsIAAgASgCMDYCMCAAIAEoAjQ2AjQgACABKAI4NgI4IAAgASgCPDYCPCAAQcAAaiEAIAFBwABqIQEMAQsLA0AgACACSARAIAAgASgCADYCACAAQQRqIQAgAUEEaiEBDAELCwUgA0EEayECA0AgACACSARAIAAgASwAADoAACAAIAEsAAE6AAEgACABLAACOgACIAAgASwAAzoAAyAAQQRqIQAgAUEEaiEBDAELCwsDQCAAIANIBEAgACABLAAAOgAAIABBAWohACABQQFqIQEMAQsLIAQLCwsAAn9BABAAQQALCwsAAn9BARAAQQALCwsAAn9BAhAAQQALCwu9DA0AQYAIC+QBAQAAAAAAAACCgAAAAAAAAIqAAAAAAACAAIAAgAAAAICLgAAAAAAAAAEAAIAAAAAAgYAAgAAAAIAJgAAAAAAAgIoAAAAAAAAAiAAAAAAAAAAJgACAAAAAAAoAAIAAAAAAi4AAgAAAAACLAAAAAAAAgImAAAAAAACAA4AAAAAAAIACgAAAAAAAgIAAAAAAAACACoAAAAAAAAAKAACAAAAAgIGAAIAAAACAgIAAAAAAAIABAACAAAAAAAiAAIAAAACACAAAAC/8///+////////////////////////////////////AEGICgsFAQAAAAEAQdAKCzyxCQAAIgAAAPYCAABYCQAAWQAAADwBAAAIAAAAQUE20Ixe0r87oEiv5tyuuv7///////////////////8AQbALC6kBMwoAACIAAADwAgAA0wkAAGAAAAA9AAAA0wkAAGAAAACBAAAA0wkAAGAAAACLAAAA0wkAAGAAAACTAAAA0wkAAGAAAACbAAAA0wkAAGAAAADvAAAA0wkAAGAAAAD3AAAA0wkAAGAAAAC6AAAA0wkAAGAAAABeAQAA0wkAAGAAAAAxAQAA0wkAAGAAAAAyAQAA0wkAAGAAAAA4AQAA0wkAAGAAAAA9AQAAAQBBoA0LadMJAABgAAAAbgMAAFUKAABcAAAAEAAAADMKAAAiAAAA9gIAANMJAABgAAAAHgQAABQLAAAoAAAAsQoAAGMAAABCAAAAsQoAAGMAAAA9AAAAsQoAAGMAAABQAAAAsQoAAGMAAABSAAAAAQBB0A4LAQEAQZgPC00BAAAAXgsAACAAAAB+CwAAEgAAAFgMAAAGAAAAXgwAACIAAAA8CwAAIgAAAKACAACADAAAFgAAAJYMAAANAAAAPAsAACIAAACmAgAABQBB8A8LAQEAQYgQCw4BAAAAAgAAALRfAAAABABBoBALAQEAQa8QCwUK/////wBBnBILAiRZAEHUEgvPBuQHAAAvaG9tZS9tYWNpZWovLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvdGlueS1rZWNjYWstMS4yLjEvc3JjL2xpYi5ycy9jaGVja291dC9zcmMvbGliY29yZS9zbGljZS9tb2QucnMvaG9tZS9tYWNpZWovLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvdGlueS1zZWNwMjU2azEtMC4xLjAvc3JjL2JpZ19udW0ucnMvY2hlY2tvdXQvc3JjL2xpYmNvcmUvc2xpY2UvbW9kLnJzL2hvbWUvbWFjaWVqLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3Rpbnktc2VjcDI1NmsxLTAuMS4wL3NyYy9uYWYucnMvaG9tZS9tYWNpZWovLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvdGlueS1zZWNwMjU2azEtMC4xLjAvc3JjL2VjX3BvaW50X2cucnNpbnRlcm5hbCBlcnJvcjogZW50ZXJlZCB1bnJlYWNoYWJsZSBjb2RlL2NoZWNrb3V0L3NyYy9saWJjb3JlL3NsaWNlL21vZC5yc2luZGV4IG91dCBvZiBib3VuZHM6IHRoZSBsZW4gaXMgIGJ1dCB0aGUgaW5kZXggaXMgMDAwMTAyMDMwNDA1MDYwNzA4MDkxMDExMTIxMzE0MTUxNjE3MTgxOTIwMjEyMjIzMjQyNTI2MjcyODI5MzAzMTMyMzMzNDM1MzYzNzM4Mzk0MDQxNDI0MzQ0NDU0NjQ3NDg0OTUwNTE1MjUzNTQ1NTU2NTc1ODU5NjA2MTYyNjM2NDY1NjY2NzY4Njk3MDcxNzI3Mzc0NzU3Njc3Nzg3OTgwODE4MjgzODQ4NTg2ODc4ODg5OTA5MTkyOTM5NDk1OTY5Nzk4OTlpbmRleCAgb3V0IG9mIHJhbmdlIGZvciBzbGljZSBvZiBsZW5ndGggc2xpY2UgaW5kZXggc3RhcnRzIGF0ICBidXQgZW5kcyBhdCA=', 'base64'); diff --git a/js/src/api/local/ethkey/index.js b/js/src/api/local/ethkey/index.js index a6967da25..07ca34ba1 100644 --- a/js/src/api/local/ethkey/index.js +++ b/js/src/api/local/ethkey/index.js @@ -17,13 +17,12 @@ import workerPool from './workerPool'; export function createKeyObject (key, password) { - return workerPool.getWorker().action('createKeyObject', { key, password }) + return workerPool.action('createKeyObject', { key, password }) .then((obj) => JSON.parse(obj)); } export function decryptPrivateKey (keyObject, password) { return workerPool - .getWorker() .action('decryptPrivateKey', { keyObject, password }) .then((privateKey) => { if (privateKey) { @@ -40,9 +39,9 @@ export function phraseToAddress (phrase) { } export function phraseToWallet (phrase) { - return workerPool.getWorker().action('phraseToWallet', phrase); + return workerPool.action('phraseToWallet', phrase); } export function verifySecret (secret) { - return workerPool.getWorker().action('verifySecret', secret); + return workerPool.action('verifySecret', secret); } diff --git a/js/src/api/local/ethkey/index.spec.js b/js/src/api/local/ethkey/index.spec.js index 781c49b5c..ce4cc29df 100644 --- a/js/src/api/local/ethkey/index.spec.js +++ b/js/src/api/local/ethkey/index.spec.js @@ -17,7 +17,8 @@ import { randomPhrase } from '@parity/wordlist'; import { phraseToAddress, phraseToWallet } from './'; -describe('api/local/ethkey', () => { +// TODO: Skipping until Node.js 8.0 comes out and we can test WebAssembly +describe.skip('api/local/ethkey', () => { describe('phraseToAddress', function () { this.timeout(30000); diff --git a/js/src/api/local/ethkey/worker.js b/js/src/api/local/ethkey/worker.js index ffb99d0e8..76ccf06b2 100644 --- a/js/src/api/local/ethkey/worker.js +++ b/js/src/api/local/ethkey/worker.js @@ -14,9 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import secp256k1 from 'secp256k1'; -import { keccak_256 as keccak256 } from 'js-sha3'; import { bytesToHex } from '~/api/util/format'; +import { extern, slice } from './ethkey.js'; const isWorker = typeof self !== 'undefined'; @@ -42,43 +41,40 @@ function route ({ action, payload }) { return null; } +const input = slice(extern._input_ptr(), 1024); +const secret = slice(extern._secret_ptr(), 32); +const publicKey = slice(extern._public_ptr(), 64); +const address = slice(extern._address_ptr(), 20); + +extern._ecpointg(); + const actions = { phraseToWallet (phrase) { - let secret = keccak256.array(phrase); + const phraseUtf8 = Buffer.from(phrase, 'utf8'); - for (let i = 0; i < 16384; i++) { - secret = keccak256.array(secret); + if (phraseUtf8.length > input.length) { + throw new Error('Phrase is too long!'); } - while (true) { - secret = keccak256.array(secret); + input.set(phraseUtf8); - const secretBuf = Buffer.from(secret); + extern._brain(phraseUtf8.length); - if (secp256k1.privateKeyVerify(secretBuf)) { - // No compression, slice out last 64 bytes - const publicBuf = secp256k1.publicKeyCreate(secretBuf, false).slice(-64); - const address = keccak256.array(publicBuf).slice(12); + const wallet = { + secret: bytesToHex(secret), + public: bytesToHex(publicKey), + address: bytesToHex(address) + }; - if (address[0] !== 0) { - continue; - } - - const wallet = { - secret: bytesToHex(secretBuf), - public: bytesToHex(publicBuf), - address: bytesToHex(address) - }; - - return wallet; - } - } + return wallet; }, - verifySecret (secret) { - const key = Buffer.from(secret.slice(2), 'hex'); + verifySecret (key) { + const keyBuf = Buffer.from(key.slice(2), 'hex'); - return secp256k1.privateKeyVerify(key); + secret.set(keyBuf); + + return extern._verify_secret(); }, createKeyObject ({ key, password }) { @@ -112,7 +108,8 @@ self.onmessage = function ({ data }) { postMessage([null, result]); } catch (err) { - postMessage([err, null]); + console.error(err); + postMessage([err.toString(), null]); } }; diff --git a/js/src/api/local/ethkey/workerPool.js b/js/src/api/local/ethkey/workerPool.js index e4e4a5134..d7db73b41 100644 --- a/js/src/api/local/ethkey/workerPool.js +++ b/js/src/api/local/ethkey/workerPool.js @@ -38,7 +38,8 @@ class WorkerContainer { this.busy = false; if (err) { - reject(err); + // `err` ought to be a String + reject(new Error(err)); } else { resolve(result); } @@ -48,20 +49,56 @@ class WorkerContainer { } class WorkerPool { - pool = []; + pool = [ + new WorkerContainer(), + new WorkerContainer() + ]; - getWorker () { + queue = []; + + _getContainer () { + return this.pool.find((container) => !container.busy); + } + + action (action, payload) { let container = this.pool.find((container) => !container.busy); + let promise; + + // const start = Date.now(); + if (container) { - return container; + promise = container.action(action, payload); + } else { + promise = new Promise((resolve, reject) => { + this.queue.push([action, payload, resolve]); + }); } - container = new WorkerContainer(); + return promise + .catch((err) => { + this.processQueue(); - this.pool.push(container); + throw err; + }) + .then((result) => { + this.processQueue(); - return container; + // console.log('Work done in ', Date.now() - start); + + return result; + }); + } + + processQueue () { + let container = this._getContainer(); + + while (container && this.queue.length > 0) { + const [action, payload, resolve] = this.queue.shift(); + + resolve(container.action(action, payload)); + container = this._getContainer(); + } } } diff --git a/js/src/api/local/localAccountsMiddleware.js b/js/src/api/local/localAccountsMiddleware.js index 753de8a4c..457574715 100644 --- a/js/src/api/local/localAccountsMiddleware.js +++ b/js/src/api/local/localAccountsMiddleware.js @@ -29,7 +29,7 @@ export default class LocalAccountsMiddleware extends Middleware { const register = this.register.bind(this); register('eth_accounts', () => { - return accounts.mapArray((account) => account.address); + return accounts.addresses(); }); register('eth_coinbase', () => { @@ -37,13 +37,13 @@ export default class LocalAccountsMiddleware extends Middleware { }); register('parity_accountsInfo', () => { - return accounts.mapObject(({ name }) => { + return accounts.map(({ name }) => { return { name }; }); }); register('parity_allAccountsInfo', () => { - return accounts.mapObject(({ name, meta, uuid }) => { + return accounts.map(({ name, meta, uuid }) => { return { name, meta, uuid }; }); }); @@ -68,10 +68,31 @@ export default class LocalAccountsMiddleware extends Middleware { return transactions.hash(id) || Promise.resolve(null); }); + register('parity_dappsList', () => { + return []; + }); + register('parity_defaultAccount', () => { return accounts.lastAddress; }); + register('parity_exportAccount', ([address, password]) => { + const account = accounts.get(address); + + if (!password) { + password = ''; + } + + return account.isValidPassword(password) + .then((isValid) => { + if (!isValid) { + throw new Error('Invalid password'); + } + + return account.export(); + }); + }); + register('parity_generateSecretPhrase', () => { return randomPhrase(12); }); @@ -80,6 +101,10 @@ export default class LocalAccountsMiddleware extends Middleware { return []; }); + register('parity_getNewDappsDefaultAddress', () => { + return accounts.lastAddress; + }); + register('parity_hardwareAccountsInfo', () => { return {}; }); @@ -102,18 +127,30 @@ export default class LocalAccountsMiddleware extends Middleware { }); }); + register('parity_newAccountFromWallet', ([json, password]) => { + if (!password) { + password = ''; + } + + return accounts.restoreFromWallet(JSON.parse(json), password); + }); + register('parity_setAccountMeta', ([address, meta]) => { - accounts.get(address).meta = meta; + accounts.getLazyCreate(address).meta = meta; return true; }); register('parity_setAccountName', ([address, name]) => { - accounts.get(address).name = name; + accounts.getLazyCreate(address).name = name; return true; }); + register('parity_setNewDappsDefaultAddress', ([address]) => { + accounts.dappsDefaultAddress = address; + }); + register('parity_postTransaction', ([tx]) => { if (!tx.from) { tx.from = accounts.lastAddress; @@ -137,10 +174,32 @@ export default class LocalAccountsMiddleware extends Middleware { return []; }); + register('parity_listOpenedVaults', () => { + return []; + }); + register('parity_listRecentDapps', () => { return {}; }); + register('parity_listVaults', () => { + return []; + }); + + register('parity_wsUrl', () => { + // This is a hack, will be replaced by a `hostname` setting on the node itself + return `${window.location.hostname}:8546`; + }); + + register('parity_dappsUrl', () => { + // This is a hack, will be replaced by a `hostname` setting on the node itself + return `${window.location.hostname}:8545`; + }); + + register('parity_hashContent', () => { + throw new Error('Functionality unavailable on a public wallet.'); + }); + register('parity_killAccount', ([address, password]) => { return accounts.remove(address, password); }); @@ -204,6 +263,10 @@ export default class LocalAccountsMiddleware extends Middleware { }); }); + register('signer_generateAuthorizationToken', () => { + return ''; + }); + register('signer_rejectRequest', ([id]) => { return transactions.reject(id); }); diff --git a/js/src/api/local/localAccountsMiddleware.spec.js b/js/src/api/local/localAccountsMiddleware.spec.js index 7408b4b1e..b3de3992d 100644 --- a/js/src/api/local/localAccountsMiddleware.spec.js +++ b/js/src/api/local/localAccountsMiddleware.spec.js @@ -32,7 +32,8 @@ class MockedTransport extends JsonRpcBase { } } -describe('api/local/LocalAccountsMiddleware', function () { +// Skip till all CI runs on Node 8+ +describe.skip('api/local/LocalAccountsMiddleware', function () { this.timeout(30000); let transport; @@ -71,7 +72,9 @@ describe('api/local/LocalAccountsMiddleware', function () { 'parity_phraseToAddress', 'parity_useLocalAccounts', 'parity_listGethAccounts', + 'parity_listOpenedVaults', 'parity_listRecentDapps', + 'parity_listVaults', 'parity_killAccount', 'parity_testPassword', 'signer_confirmRequest', diff --git a/js/src/dapps/dappreg/Application/application.js b/js/src/dapps/dappreg/Application/application.js index 4c3a567c2..b33aa0b96 100644 --- a/js/src/dapps/dappreg/Application/application.js +++ b/js/src/dapps/dappreg/Application/application.js @@ -42,7 +42,7 @@ export default class Application extends Component { return (
- DAPP REGISTRY, a global view of distributed applications available on the network. Putting the puzzle together. + DAPP REGISTRY, a global view of decentralized applications available on the network. Putting the puzzle together.
diff --git a/js/src/dapps/dappreg/ModalDelete/modalDelete.js b/js/src/dapps/dappreg/ModalDelete/modalDelete.js index e64c315fa..20ca64067 100644 --- a/js/src/dapps/dappreg/ModalDelete/modalDelete.js +++ b/js/src/dapps/dappreg/ModalDelete/modalDelete.js @@ -43,7 +43,7 @@ export default class ModalDelete extends Component { secondary >
- You are about to remove a distributed application from the registry, + You are about to remove a decentralized application from the registry, the details of this application is given below. Removal does not return any fees, however the application will not be available to users anymore.
diff --git a/js/src/dapps/dappreg/ModalRegister/modalRegister.js b/js/src/dapps/dappreg/ModalRegister/modalRegister.js index 0c8bd0b9a..ee4d2a374 100644 --- a/js/src/dapps/dappreg/ModalRegister/modalRegister.js +++ b/js/src/dapps/dappreg/ModalRegister/modalRegister.js @@ -50,7 +50,7 @@ export default class ModalRegister extends Component { secondary >
- You are about to register a new distributed application on the network, the details of + You are about to register a new decentralized application on the network, the details of this application is given below. This will require a non-refundable fee of { api.util.fromWei(this.dappsStore.fee).toFormat(3) } ETH
diff --git a/js/src/i18n/_default/extension.js b/js/src/i18n/_default/extension.js index 88ba33674..baa2efd4e 100644 --- a/js/src/i18n/_default/extension.js +++ b/js/src/i18n/_default/extension.js @@ -16,5 +16,5 @@ export default { install: `Install the extension now`, - intro: `Parity now has an extension available for Chrome that allows safe browsing of Ethereum-enabled distributed applications. It is highly recommended that you install this extension to further enhance your Parity experience.` + intro: `Parity now has an extension available for Chrome that allows safe browsing of Ethereum-enabled decentralized applications. It is highly recommended that you install this extension to further enhance your Parity experience.` }; diff --git a/js/src/i18n/_default/settings.js b/js/src/i18n/_default/settings.js index 3e475e087..ea447e4a9 100644 --- a/js/src/i18n/_default/settings.js +++ b/js/src/i18n/_default/settings.js @@ -69,7 +69,7 @@ export default { label: `Addressbook` }, apps: { - description: `Distributed applications that interact with the underlying network. Add applications, manage you application portfolio and interact with application from around the network.`, + description: `Decentralized applications that interact with the underlying network. Add applications, manage you application portfolio and interact with application from around the network.`, label: `Applications` }, contracts: { @@ -85,7 +85,7 @@ export default { label: `Settings` }, signer: { - description: `The secure transaction management area of the application where you can approve any outgoing transactions made from the application as well as those placed into the queue by distributed applications.`, + description: `The secure transaction management area of the application where you can approve any outgoing transactions made from the application as well as those placed into the queue by decentralized applications.`, label: `Signer` }, status: { diff --git a/js/src/i18n/_default/tabBar.js b/js/src/i18n/_default/tabBar.js index 1692a1997..b704879e0 100644 --- a/js/src/i18n/_default/tabBar.js +++ b/js/src/i18n/_default/tabBar.js @@ -16,6 +16,6 @@ export default { tooltip: { - overview: `navigate between the different parts and views of the application, switching between an account view, token view and distributed application view` + overview: `navigate between the different parts and views of the application, switching between an account view, token view and decentralized application view` } }; diff --git a/js/src/i18n/zh-Hant-TW/extension.js b/js/src/i18n/zh-Hant-TW/extension.js index 5c0987038..0f017aa0f 100644 --- a/js/src/i18n/zh-Hant-TW/extension.js +++ b/js/src/i18n/zh-Hant-TW/extension.js @@ -17,6 +17,6 @@ export default { install: `現在就安裝這個擴充套件`, // Install the extension now intro: `Parity現在有一個Chrome的擴充套件,可以安全的瀏覽以太坊所支援的分散式應用。我們強烈推薦你安裝這個擴充套件來進一步提升你的Parity使用體驗。` - // Parity now has an extension available for Chrome that allows safe browsing of Ethereum-enabled distributed applications. + // Parity now has an extension available for Chrome that allows safe browsing of Ethereum-enabled decentralized applications. // It is highly recommended that you install this extension to further enhance your Parity experience. }; diff --git a/js/src/i18n/zh-Hant-TW/settings.js b/js/src/i18n/zh-Hant-TW/settings.js index bf026c384..8841279dc 100644 --- a/js/src/i18n/zh-Hant-TW/settings.js +++ b/js/src/i18n/zh-Hant-TW/settings.js @@ -82,7 +82,7 @@ export default { }, apps: { description: `與整個底層網路交流的分散式應用。新增應用,管理你的應用庫和與網路上的其他應用進行互動。`, - // Distributed applications that interact with the underlying network. Add applications, manage you application portfolio and + // Decentralized applications that interact with the underlying network. Add applications, manage you application portfolio and // interact with application from around the network. label: `應用` // Applications }, @@ -108,7 +108,7 @@ export default { signer: { description: `這個應用安全交易管理區域,你可以通過任何從本應用和其他分散式應用發起的即將傳送的交易`, // The secure transaction management area of the application where you can approve any outgoing transactions made - // from the application as well as those placed into the queue by distributed applications. + // from the application as well as those placed into the queue by decentralized applications. label: `Signer` // Signer }, status: { diff --git a/js/src/i18n/zh-Hant-TW/tabBar.js b/js/src/i18n/zh-Hant-TW/tabBar.js index 73ccabf96..482c230fb 100644 --- a/js/src/i18n/zh-Hant-TW/tabBar.js +++ b/js/src/i18n/zh-Hant-TW/tabBar.js @@ -17,6 +17,6 @@ export default { tooltip: { overview: `在應用的不同部分和不同介面進行導航,在帳戶介面、代幣介面和分散式應用介面之間切換。` - // navigate between the different parts and views of the application, switching between an account view, token view and distributed application view + // navigate between the different parts and views of the application, switching between an account view, token view and decentralized application view } }; diff --git a/js/src/i18n/zh/extension.js b/js/src/i18n/zh/extension.js index e79c03667..609b76bcf 100644 --- a/js/src/i18n/zh/extension.js +++ b/js/src/i18n/zh/extension.js @@ -17,6 +17,6 @@ export default { install: `现在就安装这个扩展`, // Install the extension now intro: `Parity现在有一个Chrome的扩展,可以安全的浏览以太坊所支持的分布式应用。我们强烈推荐你安装这个扩展来进一步提升你的Parity使用体验。` - // Parity now has an extension available for Chrome that allows safe browsing of Ethereum-enabled distributed applications. + // Parity now has an extension available for Chrome that allows safe browsing of Ethereum-enabled decentralized applications. // It is highly recommended that you install this extension to further enhance your Parity experience. }; diff --git a/js/src/i18n/zh/settings.js b/js/src/i18n/zh/settings.js index 3630caa45..4081a06d6 100644 --- a/js/src/i18n/zh/settings.js +++ b/js/src/i18n/zh/settings.js @@ -82,7 +82,7 @@ export default { }, apps: { description: `与整个底层网络交流的分布式应用。添加应用,管理你的应用库和与网络上的其他应用进行交互。`, - // Distributed applications that interact with the underlying network. Add applications, manage you application portfolio and + // Decentralized applications that interact with the underlying network. Add applications, manage you application portfolio and // interact with application from around the network. label: `应用` // Applications }, @@ -108,7 +108,7 @@ export default { signer: { description: `这个应用安全交易管理区域,你可以通过任何从本应用和其他分布式应用发起的即将发送的交易`, // The secure transaction management area of the application where you can approve any outgoing transactions made - // from the application as well as those placed into the queue by distributed applications. + // from the application as well as those placed into the queue by decentralized applications. label: `Signer` // Signer }, status: { diff --git a/js/src/i18n/zh/tabBar.js b/js/src/i18n/zh/tabBar.js index 7521c1b33..08a0a816f 100644 --- a/js/src/i18n/zh/tabBar.js +++ b/js/src/i18n/zh/tabBar.js @@ -17,6 +17,6 @@ export default { tooltip: { overview: `在应用的不同部分和不同界面进行导航,在账户界面、代币界面和分布式应用界面之间切换。` - // navigate between the different parts and views of the application, switching between an account view, token view and distributed application view + // navigate between the different parts and views of the application, switching between an account view, token view and decentralized application view } }; diff --git a/js/src/lib.rs.in b/js/src/lib.rs.in index 2dabd46c5..220811656 100644 --- a/js/src/lib.rs.in +++ b/js/src/lib.rs.in @@ -42,7 +42,7 @@ impl WebApp for App { Info { name: "Parity UI", version: env!("CARGO_PKG_VERSION"), - author: "Ethcore ", + author: "Parity ", description: "New UI for Parity.", icon_url: "icon.png", } diff --git a/js/src/modals/CreateAccount/AccountDetails/accountDetails.js b/js/src/modals/CreateAccount/AccountDetails/accountDetails.js index 75a2ca9c4..137d87d94 100644 --- a/js/src/modals/CreateAccount/AccountDetails/accountDetails.js +++ b/js/src/modals/CreateAccount/AccountDetails/accountDetails.js @@ -25,9 +25,16 @@ import styles from '../createAccount.css'; @observer export default class AccountDetails extends Component { static propTypes = { + isConfirming: PropTypes.bool, + withRequiredBackup: PropTypes.bool, createStore: PropTypes.object.isRequired } + static defaultPropTypes = { + isConfirming: false, + withRequiredBackup: false + } + render () { const { address, description, name } = this.props.createStore; @@ -78,31 +85,103 @@ export default class AccountDetails extends Component { ); } - renderPhrase () { - const { phrase } = this.props.createStore; + renderRequiredBackup () { + const { phraseBackedUp, phraseBackedUpError } = this.props.createStore; - if (!phrase) { + if (!this.props.withRequiredBackup) { return null; } return ( - - } - label={ - - } - readOnly - value={ phrase } - /> +
+ + } + label={ + + } + onChange={ this.onEditPhraseBackedUp } + value={ phraseBackedUp } + /> +
); } + + renderPhrase () { + const { isConfirming } = this.props; + const { isTest, phrase, backupPhraseError } = this.props.createStore; + + const hint = ( + + ); + const label = ( + + ); + + if (!isConfirming) { + if (!phrase) { + return null; + } + + return ( +
+ +
+ +
+ { this.renderRequiredBackup() } +
+ ); + } + + return ( +
+ +
+ +
+
+ ); + } + + onEditPhraseBackedUp = (ev) => { + this.props.createStore.setPhraseBackedUp(ev.target.value); + } + + onEditPhrase = (ev) => { + this.props.createStore.setPhrase(ev.target.value); + } } diff --git a/js/src/modals/CreateAccount/createAccount.css b/js/src/modals/CreateAccount/createAccount.css index 1dd338643..cbab4ee8d 100644 --- a/js/src/modals/CreateAccount/createAccount.css +++ b/js/src/modals/CreateAccount/createAccount.css @@ -131,3 +131,8 @@ padding: 0 4em 1.5em 4em; text-align: center; } + +.backupPhrase { + line-height: 1.618em; + margin-top: 1.5em; +} diff --git a/js/src/modals/CreateAccount/createAccount.js b/js/src/modals/CreateAccount/createAccount.js index 988a5f521..ec8308615 100644 --- a/js/src/modals/CreateAccount/createAccount.js +++ b/js/src/modals/CreateAccount/createAccount.js @@ -37,7 +37,7 @@ import NewImport from './NewImport'; import NewQr from './NewQr'; import RawKey from './RawKey'; import RecoveryPhrase from './RecoveryPhrase'; -import Store, { STAGE_CREATE, STAGE_INFO, STAGE_SELECT_TYPE } from './store'; +import Store, { STAGE_CREATE, STAGE_INFO, STAGE_SELECT_TYPE, STAGE_CONFIRM_BACKUP } from './store'; import TypeIcon from './TypeIcon'; import print from './print'; import recoveryPage from './recoveryPage.ejs'; @@ -61,6 +61,12 @@ const TITLES = { defaultMessage='account information' /> ), + backup: ( + + ), import: ( ) }; -const STAGE_NAMES = [TITLES.type, TITLES.create, TITLES.info]; +const STAGE_NAMES = [TITLES.type, TITLES.create, TITLES.info, TITLES.backup]; const STAGE_IMPORT = [TITLES.type, TITLES.import, TITLES.info]; const STAGE_RESTORE = [TITLES.restore, TITLES.info]; const STAGE_QR = [TITLES.type, TITLES.qr, TITLES.info]; @@ -213,14 +219,25 @@ class CreateAccount extends Component { } return ( - + + ); + + case STAGE_CONFIRM_BACKUP: + return ( + ); } } renderDialogActions () { const { restore } = this.props; - const { createType, canCreate, isBusy, stage } = this.createStore; + const { createType, canCreate, isBusy, stage, phraseBackedUpError } = this.createStore; const cancelBtn = (