From bd066e27a631ce6ae886c413c6a5cc90f0e37593 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 4 Apr 2018 12:06:39 +0200 Subject: [PATCH] Traitify Runtime (#104) * Factor out safe-mix and dispatch * Refactor dispatch into something more modular. * Fix wasm build. * Fix up timestamp * fix warnings. * Borked timestamp example * Fix build * Timestamp as skeleton for traity runtime. * New storage macro. * Dispatch module has traity API. * Move consensus module to new API * Refactoring and outer dispatch * Avoid unnecessary derives. * Abstract the low-level half of system. * nicer outer dispatch syntax. * Make runtime compile again (albeit in a heavily simplified state) * Reworking runtime and the upper levels of system. * Initial reworking of runtime: - Introduced executive module; - Introduced trait primitives module; - Provided an API endpoint. * Expose an additional function in system * Another couple of functions traitified in executive. * another function in executive traitified. * One more function traitified. * Finish traitifying executive! * Traitify session module. * Cleanups and ensure session gets run. * First part of traitification of staking module. * Bit more of staking traitified. * Additional stuff in staking. Fix up session. * Penultimate part of staking module. * Final part of staking (code) * Update demo runtime to include staking. * Final tweaks for staking integration. * Remove old runtime files. * Schedule staking. * Minor fixes * First bits of democracy. * Democracy module integrated. * Fix warning. * Traitify and integrate council module * Council voting. * Runtime binary and tweaks. * Binary update. * Fix `*Type` grumble. * Fix up genesis_map * Remove NonTrivialSlicable * Staking "test externalities" stuff along with refactor. * Add session test externalities constructor * Fixed executor tests. * Make one test in executive module work. * Remove test framework stuff into common module. * Enable other tests in executive * Session tests reinstated, minor refactoring of keyring. * Fix staking tests. * Fix up democracy tests. * First few tests in council. * Council tests reinstated :) * Avoid hardcoding blake2 into Header. * Fix last few tests. * Make all primitives generic. * Fix tests. * Refactor runtime to remove genesismap. * Streamline runtime more with macrofied config. * Clean paths * Fix warning. * Consolidate demo runtime crate. * Remove stale code. * Refactor away dodgy trait. * Add corresponding Aux type. * Fixes * Rename Digesty -> Digest * Rename Headery -> Header * Blocky -> Block * Fix wasm build. * kill warnings * more docs * minor cleanups --- substrate/Cargo.lock | 185 ++- substrate/Cargo.toml | 10 + substrate/build.sh | 2 +- substrate/demo/cli/src/lib.rs | 71 +- substrate/demo/executor/Cargo.toml | 3 + substrate/demo/executor/src/lib.rs | 182 ++- substrate/demo/primitives/Cargo.toml | 2 + substrate/demo/primitives/src/block.rs | 154 -- substrate/demo/primitives/src/lib.rs | 35 +- substrate/demo/runtime/Cargo.toml | 25 +- substrate/demo/runtime/src/api.rs | 27 - substrate/demo/runtime/src/block.rs | 52 - substrate/demo/runtime/src/dispatch.rs | 246 --- substrate/demo/runtime/src/genesismap.rs | 129 -- substrate/demo/runtime/src/lib.rs | 156 +- .../demo/runtime/src/runtime/consensus.rs | 51 - substrate/demo/runtime/src/runtime/council.rs | 1312 --------------- .../demo/runtime/src/runtime/council_vote.rs | 493 ------ .../demo/runtime/src/runtime/democracy.rs | 623 ------- substrate/demo/runtime/src/runtime/mod.rs | 34 - substrate/demo/runtime/src/runtime/session.rs | 259 --- substrate/demo/runtime/src/runtime/staking.rs | 885 ---------- substrate/demo/runtime/src/runtime/system.rs | 352 ---- .../demo/runtime/src/runtime/timestamp.rs | 64 - substrate/demo/runtime/src/transaction.rs | 188 --- substrate/demo/runtime/wasm/Cargo.lock | 189 ++- substrate/demo/runtime/wasm/Cargo.toml | 30 +- .../release/demo_runtime.compact.wasm | Bin 136003 -> 236029 bytes .../release/demo_runtime.wasm | Bin 145910 -> 236080 bytes substrate/polkadot/cli/Cargo.toml | 2 +- substrate/polkadot/consensus/Cargo.toml | 2 +- substrate/polkadot/consensus/src/lib.rs | 4 +- substrate/polkadot/consensus/src/service.rs | 3 +- substrate/polkadot/primitives/src/block.rs | 2 +- .../polkadot/primitives/src/parachain.rs | 12 +- .../polkadot/primitives/src/transaction.rs | 40 +- substrate/polkadot/runtime/wasm/Cargo.lock | 3 +- .../release/polkadot_runtime.compact.wasm | Bin 98641 -> 134951 bytes .../release/polkadot_runtime.wasm | Bin 105889 -> 135000 bytes substrate/publish-wasm.sh | 2 +- substrate/safe-mix/Cargo.toml | 14 + substrate/safe-mix/build.rs | 14 + .../src/safe_mix.rs => safe-mix/src/lib.rs} | 9 +- substrate/substrate/bft/Cargo.toml | 1 + substrate/substrate/bft/src/lib.rs | 12 +- substrate/substrate/client/src/client.rs | 4 +- substrate/substrate/codec/src/lib.rs | 2 +- substrate/substrate/codec/src/slicable.rs | 121 +- .../release/runtime_test.compact.wasm | Bin 14487 -> 14298 bytes .../release/runtime_test.wasm | Bin 15588 -> 14394 bytes substrate/substrate/network/src/test/mod.rs | 2 +- substrate/substrate/primitives/src/bft.rs | 24 +- substrate/substrate/primitives/src/block.rs | 36 +- substrate/substrate/primitives/src/lib.rs | 2 +- substrate/substrate/runtime-io/src/lib.rs | 34 + substrate/substrate/runtime-io/with_std.rs | 10 +- substrate/substrate/runtime-std/build.rs | 12 +- substrate/substrate/runtime-std/src/lib.rs | 9 + substrate/substrate/runtime-std/with_std.rs | 4 + .../substrate/runtime-std/without_std.rs | 12 +- .../substrate/runtime-support/Cargo.toml | 6 +- .../substrate/runtime-support/src/dispatch.rs | 510 ++++++ .../substrate/runtime-support/src/lib.rs | 12 + .../runtime-support/src/storage/generator.rs | 564 ++++++- .../substrate/runtime/consensus/Cargo.toml | 24 + .../substrate/runtime/consensus/src/lib.rs | 111 ++ .../substrate/runtime/council/Cargo.toml | 41 + .../substrate/runtime/council/src/lib.rs | 1453 +++++++++++++++++ .../substrate/runtime/council/src/voting.rs | 457 ++++++ .../substrate/runtime/democracy/Cargo.toml | 36 + .../substrate/runtime/democracy/src/lib.rs | 659 ++++++++ .../runtime/democracy/src/vote_threshold.rs | 75 + .../substrate/runtime/executive/Cargo.toml | 32 + .../substrate/runtime/executive/src/lib.rs | 284 ++++ .../substrate/runtime/primitives/Cargo.toml | 28 + .../runtime/primitives/src/generic.rs | 398 +++++ .../substrate/runtime/primitives/src/lib.rs | 87 + .../runtime/primitives/src/testing.rs | 150 ++ .../runtime/primitives/src/traits.rs | 293 ++++ .../substrate/runtime/session/Cargo.toml | 34 + .../substrate/runtime/session/src/lib.rs | 345 ++++ .../substrate/runtime/staking/Cargo.toml | 35 + .../substrate/runtime/staking/src/lib.rs | 1017 ++++++++++++ substrate/substrate/runtime/system/Cargo.toml | 28 + substrate/substrate/runtime/system/src/lib.rs | 178 ++ .../substrate/runtime/timestamp/Cargo.toml | 25 + .../substrate/runtime/timestamp/src/lib.rs | 93 ++ .../substrate/test-runtime/src/transaction.rs | 2 +- .../test-runtime/src/unchecked_transaction.rs | 2 +- .../substrate/test-runtime/wasm/Cargo.lock | 3 +- .../substrate_test_runtime.compact.wasm | Bin 25981 -> 33039 bytes .../release/substrate_test_runtime.wasm | Bin 27842 -> 33119 bytes 92 files changed, 7890 insertions(+), 5243 deletions(-) delete mode 100644 substrate/demo/primitives/src/block.rs delete mode 100644 substrate/demo/runtime/src/api.rs delete mode 100644 substrate/demo/runtime/src/block.rs delete mode 100644 substrate/demo/runtime/src/dispatch.rs delete mode 100644 substrate/demo/runtime/src/genesismap.rs delete mode 100644 substrate/demo/runtime/src/runtime/consensus.rs delete mode 100644 substrate/demo/runtime/src/runtime/council.rs delete mode 100644 substrate/demo/runtime/src/runtime/council_vote.rs delete mode 100644 substrate/demo/runtime/src/runtime/democracy.rs delete mode 100644 substrate/demo/runtime/src/runtime/mod.rs delete mode 100644 substrate/demo/runtime/src/runtime/session.rs delete mode 100644 substrate/demo/runtime/src/runtime/staking.rs delete mode 100644 substrate/demo/runtime/src/runtime/system.rs delete mode 100644 substrate/demo/runtime/src/runtime/timestamp.rs delete mode 100644 substrate/demo/runtime/src/transaction.rs mode change 100755 => 100644 substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm mode change 100755 => 100644 substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm create mode 100644 substrate/safe-mix/Cargo.toml create mode 100644 substrate/safe-mix/build.rs rename substrate/{demo/runtime/src/safe_mix.rs => safe-mix/src/lib.rs} (95%) mode change 100755 => 100644 substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm create mode 100644 substrate/substrate/runtime-support/src/dispatch.rs create mode 100644 substrate/substrate/runtime/consensus/Cargo.toml create mode 100644 substrate/substrate/runtime/consensus/src/lib.rs create mode 100644 substrate/substrate/runtime/council/Cargo.toml create mode 100644 substrate/substrate/runtime/council/src/lib.rs create mode 100644 substrate/substrate/runtime/council/src/voting.rs create mode 100644 substrate/substrate/runtime/democracy/Cargo.toml create mode 100644 substrate/substrate/runtime/democracy/src/lib.rs create mode 100644 substrate/substrate/runtime/democracy/src/vote_threshold.rs create mode 100644 substrate/substrate/runtime/executive/Cargo.toml create mode 100644 substrate/substrate/runtime/executive/src/lib.rs create mode 100644 substrate/substrate/runtime/primitives/Cargo.toml create mode 100644 substrate/substrate/runtime/primitives/src/generic.rs create mode 100644 substrate/substrate/runtime/primitives/src/lib.rs create mode 100644 substrate/substrate/runtime/primitives/src/testing.rs create mode 100644 substrate/substrate/runtime/primitives/src/traits.rs create mode 100644 substrate/substrate/runtime/session/Cargo.toml create mode 100644 substrate/substrate/runtime/session/src/lib.rs create mode 100644 substrate/substrate/runtime/staking/Cargo.toml create mode 100644 substrate/substrate/runtime/staking/src/lib.rs create mode 100644 substrate/substrate/runtime/system/Cargo.toml create mode 100644 substrate/substrate/runtime/system/src/lib.rs create mode 100644 substrate/substrate/runtime/timestamp/Cargo.toml create mode 100644 substrate/substrate/runtime/timestamp/src/lib.rs mode change 100755 => 100644 substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 995c0525af..880e992909 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -228,7 +228,10 @@ dependencies = [ "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-staking 0.1.0", "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", "substrate-state-machine 0.1.0", "triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -242,6 +245,7 @@ dependencies = [ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-primitives 0.1.0", "substrate-runtime-std 0.1.0", "substrate-serializer 0.1.0", ] @@ -252,17 +256,26 @@ version = "0.1.0" dependencies = [ "demo-primitives 0.1.0", "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "integer-sqrt 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-council 0.1.0", + "substrate-runtime-democracy 0.1.0", + "substrate-runtime-executive 0.1.0", "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-staking 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", + "substrate-runtime-timestamp 0.1.0", ] [[package]] @@ -971,6 +984,11 @@ name = "num-traits" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num-traits" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "num_cpus" version = "1.8.0" @@ -1162,6 +1180,7 @@ dependencies = [ "substrate-keyring 0.1.0", "substrate-network 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-support 0.1.0", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1491,6 +1510,13 @@ dependencies = [ "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "safe-mix" +version = "0.1.0" +dependencies = [ + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "safemem" version = "0.2.0" @@ -1633,6 +1659,7 @@ dependencies = [ "substrate-executor 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-support 0.1.0", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1780,6 +1807,78 @@ dependencies = [ "substrate-rpc 0.1.0", ] +[[package]] +name = "substrate-runtime-consensus" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", +] + +[[package]] +name = "substrate-runtime-council" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "integer-sqrt 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-democracy 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-staking 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + +[[package]] +name = "substrate-runtime-democracy" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-staking 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + +[[package]] +name = "substrate-runtime-executive" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-staking 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + [[package]] name = "substrate-runtime-io" version = "0.1.0" @@ -1794,6 +1893,58 @@ dependencies = [ "triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "substrate-runtime-primitives" +version = "0.1.0" +dependencies = [ + "integer-sqrt 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", +] + +[[package]] +name = "substrate-runtime-session" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + +[[package]] +name = "substrate-runtime-staking" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + [[package]] name = "substrate-runtime-std" version = "0.1.0" @@ -1808,14 +1959,43 @@ name = "substrate-runtime-support" version = "0.1.0" dependencies = [ "ed25519 0.1.0", - "environmental 0.1.0", "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-std 0.1.0", ] +[[package]] +name = "substrate-runtime-system" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", +] + +[[package]] +name = "substrate-runtime-timestamp" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", +] + [[package]] name = "substrate-serializer" version = "0.1.0" @@ -2302,6 +2482,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num-traits 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "9936036cc70fe4a8b2d338ab665900323290efb03983c86cbe235ae800ad8017" +"checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml index b4d18443da..4c5c692750 100644 --- a/substrate/Cargo.toml +++ b/substrate/Cargo.toml @@ -39,6 +39,15 @@ members = [ "substrate/runtime-io", "substrate/runtime-std", "substrate/runtime-support", + "substrate/runtime/consensus", + "substrate/runtime/council", + "substrate/runtime/democracy", + "substrate/runtime/executive", + "substrate/runtime/primitives", + "substrate/runtime/session", + "substrate/runtime/staking", + "substrate/runtime/system", + "substrate/runtime/timestamp", "substrate/serializer", "substrate/state-machine", "substrate/test-runtime", @@ -46,6 +55,7 @@ members = [ "demo/primitives", "demo/executor", "demo/cli", + "safe-mix", ] exclude = [ "polkadot/runtime/wasm", diff --git a/substrate/build.sh b/substrate/build.sh index d6545f4f4f..43d8deb8c1 100755 --- a/substrate/build.sh +++ b/substrate/build.sh @@ -1,6 +1,6 @@ #!/bin/sh +cd demo/runtime/wasm && ./build.sh && cd ../../.. cd substrate/executor/wasm && ./build.sh && cd ../../.. cd substrate/test-runtime/wasm && ./build.sh && cd ../../.. cd polkadot/runtime/wasm && ./build.sh && cd ../../.. -cd demo/runtime/wasm && ./build.sh && cd ../../.. diff --git a/substrate/demo/cli/src/lib.rs b/substrate/demo/cli/src/lib.rs index 63ee1e3811..b58295775b 100644 --- a/substrate/demo/cli/src/lib.rs +++ b/substrate/demo/cli/src/lib.rs @@ -22,6 +22,7 @@ extern crate env_logger; extern crate ed25519; extern crate triehash; extern crate substrate_codec as codec; +extern crate substrate_runtime_io as runtime_io; extern crate substrate_state_machine as state_machine; extern crate substrate_client as client; extern crate substrate_primitives as primitives; @@ -43,7 +44,9 @@ pub mod error; use std::sync::Arc; use codec::Slicable; -use demo_runtime::genesismap::{additional_storage_with_genesis, GenesisConfig}; +use runtime_io::with_externalities; +use demo_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfig, + SessionConfig, StakingConfig, BuildExternalities}; use client::genesis; /// Parse command line arguments and start the node. @@ -71,32 +74,52 @@ pub fn run(args: I) -> error::Result<()> where let god_key = hex!["3d866ec8a9190c8343c2fc593d21d8a6d0c5c4763aaab2349de3a6111d64d124"]; let genesis_config = GenesisConfig { - validators: vec![god_key.clone()], - authorities: vec![god_key.clone()], - balances: vec![(god_key.clone(), 1u64 << 63)].into_iter().collect(), - block_time: 5, // 5 second block time. - session_length: 720, // that's 1 hour per session. - sessions_per_era: 24, // 24 hours per era. - bonding_duration: 90, // 90 days per bond. - launch_period: 120 * 24 * 14, // 2 weeks per public referendum - voting_period: 120 * 24 * 28, // 4 weeks to discuss & vote on an active referendum - minimum_deposit: 1000, // 1000 as the minimum deposit for a referendum - candidacy_bond: 1000, // 1000 to become a council candidate - voter_bond: 100, // 100 down to vote for a candidate - present_slash_per_voter: 1, // slash by 1 per voter for an invalid presentation. - carry_count: 24, // carry over the 24 runners-up to the next council election - presentation_duration: 120 * 24, // one day for presenting winners. - council_election_voting_period: 7 * 120 * 24, // one week period between possible council elections. - council_term_duration: 180 * 120 * 24, // 180 day term duration for the council. - desired_seats: 0, // start with no council: we'll raise this once the stake has been dispersed a bit. - inactive_grace_period: 1, // one addition vote should go by before an inactive voter can be reaped. - cooloff_period: 90 * 120 * 24, // 90 day cooling off period if council member vetoes a proposal. - council_proposal_voting_period: 7 * 120 * 24, // 7 day voting period for council members. + consensus: Some(ConsensusConfig { + authorities: vec![god_key.clone()], + }), + system: None, +// block_time: 5, // 5 second block time. + session: Some(SessionConfig { + validators: vec![god_key.clone()], + session_length: 720, // that's 1 hour per session. + }), + staking: Some(StakingConfig { + current_era: 0, + intentions: vec![], + transaction_fee: 100, + balances: vec![(god_key.clone(), 1u64 << 63)].into_iter().collect(), + validator_count: 12, + sessions_per_era: 24, // 24 hours per era. + bonding_duration: 90, // 90 days per bond. + }), + democracy: Some(DemocracyConfig { + launch_period: 120 * 24 * 14, // 2 weeks per public referendum + voting_period: 120 * 24 * 28, // 4 weeks to discuss & vote on an active referendum + minimum_deposit: 1000, // 1000 as the minimum deposit for a referendum + }), + council: Some(CouncilConfig { + active_council: vec![], + candidacy_bond: 1000, // 1000 to become a council candidate + voter_bond: 100, // 100 down to vote for a candidate + present_slash_per_voter: 1, // slash by 1 per voter for an invalid presentation. + carry_count: 24, // carry over the 24 runners-up to the next council election + presentation_duration: 120 * 24, // one day for presenting winners. + approval_voting_period: 7 * 120 * 24, // one week period between possible council elections. + term_duration: 180 * 120 * 24, // 180 day term duration for the council. + desired_seats: 0, // start with no council: we'll raise this once the stake has been dispersed a bit. + inactive_grace_period: 1, // one addition vote should go by before an inactive voter can be reaped. + + cooloff_period: 90 * 120 * 24, // 90 day cooling off period if council member vetoes a proposal. + voting_period: 7 * 120 * 24, // 7 day voting period for council members. + }), }; let prepare_genesis = || { - storage = genesis_config.genesis_map(); + storage = genesis_config.build_externalities(); let block = genesis::construct_genesis_block(&storage); - storage.extend(additional_storage_with_genesis(&block)); + with_externalities(&mut storage, || + // TODO: use api.rs to dispatch instead + demo_runtime::System::initialise_genesis_state(&block.header) + ); (primitives::block::Header::decode(&mut block.header.encode().as_ref()).expect("to_vec() always gives a valid serialisation; qed"), storage.into_iter().collect()) }; let client = Arc::new(client::new_in_mem(executor, prepare_genesis)?); diff --git a/substrate/demo/executor/Cargo.toml b/substrate/demo/executor/Cargo.toml index ad2d53f992..2cdc008839 100644 --- a/substrate/demo/executor/Cargo.toml +++ b/substrate/demo/executor/Cargo.toml @@ -19,3 +19,6 @@ demo-runtime = { path = "../runtime" } [dev-dependencies] substrate-keyring = { path = "../../substrate/keyring" } +substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" } +substrate-runtime-staking = { path = "../../substrate/runtime/staking" } +substrate-runtime-system = { path = "../../substrate/runtime/system" } diff --git a/substrate/demo/executor/src/lib.rs b/substrate/demo/executor/src/lib.rs index 8d94b475ac..c64855a3d3 100644 --- a/substrate/demo/executor/src/lib.rs +++ b/substrate/demo/executor/src/lib.rs @@ -28,7 +28,10 @@ extern crate ed25519; extern crate triehash; #[cfg(test)] extern crate substrate_keyring as keyring; +#[cfg(test)] extern crate substrate_runtime_primitives as runtime_primitives; #[cfg(test)] extern crate substrate_runtime_support as runtime_support; +#[cfg(test)] extern crate substrate_runtime_staking as staking; +#[cfg(test)] extern crate substrate_runtime_system as system; #[cfg(test)] #[macro_use] extern crate hex_literal; native_executor_instance!(pub Executor, demo_runtime::api::dispatch, include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm")); @@ -43,12 +46,11 @@ mod tests { use runtime_support::{Hashable, StorageValue, StorageMap}; use state_machine::{CodeExecutor, TestExternalities}; use primitives::twox_128; - use demo_primitives::{Hash, Header, BlockNumber, Digest}; - use demo_runtime::transaction::{Transaction, UncheckedTransaction}; - use demo_runtime::block::Block; - use demo_runtime::runtime::staking::{FreeBalanceOf, balance}; - use demo_runtime::runtime::{staking, system}; - use demo_runtime::dispatch; + use demo_primitives::{Hash, BlockNumber}; + use runtime_primitives::traits::Header as HeaderT; + use {staking, system}; + use demo_runtime::{Header, Block, UncheckedExtrinsic, Extrinsic, Call, Concrete, Staking, + BuildExternalities, GenesisConfig, SessionConfig, StakingConfig}; use ed25519::{Public, Pair}; const BLOATY_CODE: &[u8] = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm"); @@ -61,121 +63,145 @@ mod tests { ) } - fn tx() -> UncheckedTransaction { - let transaction = Transaction { + fn xt() -> UncheckedExtrinsic { + let extrinsic = Extrinsic { signed: Alice.into(), - nonce: 0, - function: dispatch::PubCall::Staking(staking::public::Call::transfer(Bob.into(), 69)), + index: 0, + function: Call::Staking(staking::Call::transfer::(Bob.into(), 69)), }; - let signature = Keyring::from_raw_public(transaction.signed).unwrap() - .sign(&transaction.encode()); + let signature = Keyring::from_raw_public(extrinsic.signed).unwrap() + .sign(&extrinsic.encode()).into(); - UncheckedTransaction { transaction, signature } + UncheckedExtrinsic { extrinsic, signature } + } + + fn from_block_number(n: u64) -> Header { + Header::new(n, Default::default(), Default::default(), [69; 32].into(), Default::default()) } #[test] fn panic_execution_with_foreign_code_gives_error() { let mut t: TestExternalities = map![ - twox_128(&FreeBalanceOf::key_for(*Alice)).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(staking::TransactionFee::key()).to_vec() => vec![0u8; 8], - twox_128(&system::BlockHashAt::key_for(0)).to_vec() => vec![0u8; 32] + twox_128(&>::key_for(*Alice)).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; - let r = Executor::new().call(&mut t, BLOATY_CODE, "initialise_block", &vec![].and(&Header::from_block_number(1u64))); + let r = Executor::new().call(&mut t, BLOATY_CODE, "initialise_block", &vec![].and(&from_block_number(1u64))); assert!(r.is_ok()); - let r = Executor::new().call(&mut t, BLOATY_CODE, "execute_transaction", &vec![].and(&tx())); + let r = Executor::new().call(&mut t, BLOATY_CODE, "apply_extrinsic", &vec![].and(&xt())); assert!(r.is_err()); } #[test] fn panic_execution_with_native_equivalent_code_gives_error() { let mut t: TestExternalities = map![ - twox_128(&FreeBalanceOf::key_for(*Alice)).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(staking::TransactionFee::key()).to_vec() => vec![0u8; 8], - twox_128(&system::BlockHashAt::key_for(0)).to_vec() => vec![0u8; 32] + twox_128(&>::key_for(*Alice)).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; - let r = Executor::new().call(&mut t, COMPACT_CODE, "initialise_block", &vec![].and(&Header::from_block_number(1u64))); + let r = Executor::new().call(&mut t, COMPACT_CODE, "initialise_block", &vec![].and(&from_block_number(1u64))); assert!(r.is_ok()); - let r = Executor::new().call(&mut t, COMPACT_CODE, "execute_transaction", &vec![].and(&tx())); + let r = Executor::new().call(&mut t, COMPACT_CODE, "apply_extrinsic", &vec![].and(&xt())); assert!(r.is_err()); } #[test] fn successful_execution_with_native_equivalent_code_gives_ok() { let mut t: TestExternalities = map![ - twox_128(&FreeBalanceOf::key_for(*Alice)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(staking::TransactionFee::key()).to_vec() => vec![0u8; 8], - twox_128(&system::BlockHashAt::key_for(0)).to_vec() => vec![0u8; 32] + twox_128(&>::key_for(*Alice)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; - let r = Executor::new().call(&mut t, COMPACT_CODE, "initialise_block", &vec![].and(&Header::from_block_number(1u64))); + let r = Executor::new().call(&mut t, COMPACT_CODE, "initialise_block", &vec![].and(&from_block_number(1u64))); assert!(r.is_ok()); - let r = Executor::new().call(&mut t, COMPACT_CODE, "execute_transaction", &vec![].and(&tx())); + let r = Executor::new().call(&mut t, COMPACT_CODE, "apply_extrinsic", &vec![].and(&xt())); assert!(r.is_ok()); runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&Alice), 42); - assert_eq!(balance(&Bob), 69); + assert_eq!(Staking::balance(&Alice), 42); + assert_eq!(Staking::balance(&Bob), 69); }); } #[test] fn successful_execution_with_foreign_code_gives_ok() { let mut t: TestExternalities = map![ - twox_128(&FreeBalanceOf::key_for(*Alice)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(staking::TransactionFee::key()).to_vec() => vec![0u8; 8], - twox_128(&system::BlockHashAt::key_for(0)).to_vec() => vec![0u8; 32] + twox_128(&>::key_for(*Alice)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; - let r = Executor::new().call(&mut t, BLOATY_CODE, "initialise_block", &vec![].and(&Header::from_block_number(1u64))); + let r = Executor::new().call(&mut t, BLOATY_CODE, "initialise_block", &vec![].and(&from_block_number(1u64))); assert!(r.is_ok()); - let r = Executor::new().call(&mut t, BLOATY_CODE, "execute_transaction", &vec![].and(&tx())); + let r = Executor::new().call(&mut t, BLOATY_CODE, "apply_extrinsic", &vec![].and(&xt())); assert!(r.is_ok()); runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&Alice), 42); - assert_eq!(balance(&Bob), 69); + assert_eq!(Staking::balance(&Alice), 42); + assert_eq!(Staking::balance(&Bob), 69); }); } fn new_test_ext() -> TestExternalities { - staking::testing::externalities(2, 2, 0) + use keyring::Keyring::*; + let three = [3u8; 32]; + GenesisConfig { + consensus: Some(Default::default()), + system: Some(Default::default()), + session: Some(SessionConfig { + session_length: 2, + validators: vec![One.into(), Two.into(), three], + }), + staking: Some(StakingConfig { + sessions_per_era: 2, + current_era: 0, + balances: vec![(Alice.into(), 111)], + intentions: vec![Alice.into(), Bob.into(), Charlie.into()], + validator_count: 3, + bonding_duration: 0, + transaction_fee: 1, + }), + democracy: Some(Default::default()), + council: Some(Default::default()), + }.build_externalities() } - fn construct_block(number: BlockNumber, parent_hash: Hash, state_root: Hash, txs: Vec) -> (Vec, Hash) { + fn construct_block(number: BlockNumber, parent_hash: Hash, state_root: Hash, extrinsics: Vec) -> (Vec, Hash) { use triehash::ordered_trie_root; - let transactions = txs.into_iter().map(|transaction| { - let signature = Pair::from(Keyring::from_public(Public::from_raw(transaction.signed)).unwrap()) - .sign(&transaction.encode()); + let extrinsics = extrinsics.into_iter().map(|extrinsic| { + let signature = Pair::from(Keyring::from_public(Public::from_raw(extrinsic.signed)).unwrap()) + .sign(&extrinsic.encode()).into(); - UncheckedTransaction { transaction, signature } + UncheckedExtrinsic { extrinsic, signature } }).collect::>(); - let transaction_root = ordered_trie_root(transactions.iter().map(Slicable::encode)).0.into(); + let extrinsics_root = ordered_trie_root(extrinsics.iter().map(Slicable::encode)).0.into(); let header = Header { parent_hash, number, state_root, - transaction_root, - digest: Digest { logs: vec![], }, + extrinsics_root, + digest: Default::default(), }; let hash = header.blake2_256(); - (Block { header, transactions }.encode(), hash.into()) + (Block { header, extrinsics }.encode(), hash.into()) } fn block1() -> (Vec, Hash) { construct_block( 1, [69u8; 32].into(), - hex!("7a388ce5b4eeadbb9268ae96e8822b223f4fd1841327d99f4e1c21fad81f97f2").into(), - vec![Transaction { + hex!("4d58afeca0dec7604a0bcfb29573e6ad202efe65c8535b013c0c79b5a8c9114d").into(), + vec![Extrinsic { signed: Alice.into(), - nonce: 0, - function: dispatch::PubCall::Staking(staking::public::Call::transfer(Bob.into(), 69)), + index: 0, + function: Call::Staking(staking::Call::transfer(Bob.into(), 69)), }] ) } @@ -184,17 +210,17 @@ mod tests { construct_block( 2, block1().1, - hex!("e4eb71be8b816f2061f32f284e9b429562cdc1b82f11725e5f965ff23439f5e9").into(), + hex!("218ce7bdf2350713aa52dbf0a12d1e8b0a3a9f1623e7c95aa4800886e96397d1").into(), vec![ - Transaction { + Extrinsic { signed: Bob.into(), - nonce: 0, - function: dispatch::PubCall::Staking(staking::public::Call::transfer(Alice.into(), 5)), + index: 0, + function: Call::Staking(staking::Call::transfer(Alice.into(), 5)), }, - Transaction { + Extrinsic { signed: Alice.into(), - nonce: 1, - function: dispatch::PubCall::Staking(staking::public::Call::transfer(Bob.into(), 15)), + index: 1, + function: Call::Staking(staking::Call::transfer(Bob.into(), 15)), } ] ) @@ -207,15 +233,15 @@ mod tests { Executor::new().call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&Alice), 41); - assert_eq!(balance(&Bob), 69); + assert_eq!(Staking::balance(&Alice), 41); + assert_eq!(Staking::balance(&Bob), 69); }); Executor::new().call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&Alice), 30); - assert_eq!(balance(&Bob), 78); + assert_eq!(Staking::balance(&Alice), 30); + assert_eq!(Staking::balance(&Bob), 78); }); } @@ -226,50 +252,50 @@ mod tests { WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&Alice), 41); - assert_eq!(balance(&Bob), 69); + assert_eq!(Staking::balance(&Alice), 41); + assert_eq!(Staking::balance(&Bob), 69); }); WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&Alice), 30); - assert_eq!(balance(&Bob), 78); + assert_eq!(Staking::balance(&Alice), 30); + assert_eq!(Staking::balance(&Bob), 78); }); } #[test] fn panic_execution_gives_error() { let mut t: TestExternalities = map![ - twox_128(&FreeBalanceOf::key_for(*Alice)).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(staking::TransactionFee::key()).to_vec() => vec![0u8; 8], - twox_128(&system::BlockHashAt::key_for(0)).to_vec() => vec![0u8; 32] + twox_128(&>::key_for(*Alice)).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm"); - let r = WasmExecutor.call(&mut t, &foreign_code[..], "initialise_block", &vec![].and(&Header::from_block_number(1u64))); + let r = WasmExecutor.call(&mut t, &foreign_code[..], "initialise_block", &vec![].and(&from_block_number(1u64))); assert!(r.is_ok()); - let r = WasmExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &vec![].and(&tx())); + let r = WasmExecutor.call(&mut t, &foreign_code[..], "apply_extrinsic", &vec![].and(&xt())); assert!(r.is_err()); } #[test] fn successful_execution_gives_ok() { let mut t: TestExternalities = map![ - twox_128(&FreeBalanceOf::key_for(*Alice)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(staking::TransactionFee::key()).to_vec() => vec![0u8; 8], - twox_128(&system::BlockHashAt::key_for(0)).to_vec() => vec![0u8; 32] + twox_128(&>::key_for(*Alice)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm"); - let r = WasmExecutor.call(&mut t, &foreign_code[..], "initialise_block", &vec![].and(&Header::from_block_number(1u64))); + let r = WasmExecutor.call(&mut t, &foreign_code[..], "initialise_block", &vec![].and(&from_block_number(1u64))); assert!(r.is_ok()); - let r = WasmExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &vec![].and(&tx())); + let r = WasmExecutor.call(&mut t, &foreign_code[..], "apply_extrinsic", &vec![].and(&xt())); assert!(r.is_ok()); runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&Alice), 42); - assert_eq!(balance(&Bob), 69); + assert_eq!(Staking::balance(&Alice), 42); + assert_eq!(Staking::balance(&Bob), 69); }); } } diff --git a/substrate/demo/primitives/Cargo.toml b/substrate/demo/primitives/Cargo.toml index a8365cf41f..1a359e06e7 100644 --- a/substrate/demo/primitives/Cargo.toml +++ b/substrate/demo/primitives/Cargo.toml @@ -9,6 +9,7 @@ serde_derive = { version = "1.0", optional = true } substrate-codec = { path = "../../substrate/codec", default_features = false } substrate-primitives = { path = "../../substrate/primitives", default_features = false } substrate-runtime-std = { path = "../../substrate/runtime-std", default_features = false } +substrate-runtime-primitives = { path = "../../substrate/runtime/primitives", default_features = false } [dev-dependencies] substrate-serializer = { path = "../../substrate/serializer" } @@ -20,6 +21,7 @@ std = [ "substrate-codec/std", "substrate-primitives/std", "substrate-runtime-std/std", + "substrate-runtime-primitives/std", "serde_derive", "serde/std", ] diff --git a/substrate/demo/primitives/src/block.rs b/substrate/demo/primitives/src/block.rs deleted file mode 100644 index f5119ac4b3..0000000000 --- a/substrate/demo/primitives/src/block.rs +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Demo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Demo. If not, see . - -//! Block and header type definitions. - -#[cfg(feature = "std")] -use primitives::bytes; -use primitives::H256; -use rstd::vec::Vec; -use codec::{Input, Slicable}; - -pub use primitives::block::Id; - -/// Used to refer to a block number. -pub type Number = u64; - -/// Hash used to refer to a block hash. -pub type HeaderHash = H256; - -/// Execution log (event) -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub struct Log(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); - -impl Slicable for Log { - fn decode(input: &mut I) -> Option { - Vec::::decode(input).map(Log) - } - - fn using_encoded R>(&self, f: F) -> R { - self.0.using_encoded(f) - } -} - -impl ::codec::NonTrivialSlicable for Log { } - -/// The digest of a block, useful for light-clients. -#[derive(Clone, Default, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub struct Digest { - /// All logs that have happened in the block. - pub logs: Vec, -} - -impl Slicable for Digest { - fn decode(input: &mut I) -> Option { - Vec::::decode(input).map(|logs| Digest { logs }) - } - - fn using_encoded R>(&self, f: F) -> R { - self.logs.using_encoded(f) - } -} - -/// Header for a block. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] -#[cfg_attr(feature = "std", serde(deny_unknown_fields))] -pub struct Header { - /// Block parent's hash. - pub parent_hash: HeaderHash, - /// Block number. - pub number: Number, - /// State root after this transition. - pub state_root: H256, - /// The root of the trie that represents this block's transactions, indexed by a 32-byte integer. - pub transaction_root: H256, - /// The digest of activity on the block. - pub digest: Digest, -} - -impl Header { - /// Create a new instance with default fields except `number`, which is given as an argument. - pub fn from_block_number(number: Number) -> Self { - Header { - parent_hash: Default::default(), - number, - state_root: Default::default(), - transaction_root: Default::default(), - digest: Default::default(), - } - } -} - -impl Slicable for Header { - fn decode(input: &mut I) -> Option { - Some(Header { - parent_hash: try_opt!(Slicable::decode(input)), - number: try_opt!(Slicable::decode(input)), - state_root: try_opt!(Slicable::decode(input)), - transaction_root: try_opt!(Slicable::decode(input)), - digest: try_opt!(Slicable::decode(input)), - }) - } - - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - self.parent_hash.using_encoded(|s| v.extend(s)); - self.number.using_encoded(|s| v.extend(s)); - self.state_root.using_encoded(|s| v.extend(s)); - self.transaction_root.using_encoded(|s| v.extend(s)); - self.digest.using_encoded(|s| v.extend(s)); - - v - } -} - -#[cfg(test)] -mod tests { - use super::*; - use codec::Slicable; - use substrate_serializer as ser; - - #[test] - fn test_header_serialization() { - let header = Header { - parent_hash: 5.into(), - number: 67, - state_root: 3.into(), - transaction_root: 6.into(), - digest: Digest { logs: vec![Log(vec![1])] }, - }; - - assert_eq!(ser::to_string_pretty(&header), r#"{ - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000005", - "number": 67, - "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000003", - "transactionRoot": "0x0000000000000000000000000000000000000000000000000000000000000006", - "digest": { - "logs": [ - "0x01" - ] - } -}"#); - - let v = header.encode(); - assert_eq!(Header::decode(&mut &v[..]).unwrap(), header); - } -} diff --git a/substrate/demo/primitives/src/lib.rs b/substrate/demo/primitives/src/lib.rs index c65d4a63ef..ecfb5f7e7d 100644 --- a/substrate/demo/primitives/src/lib.rs +++ b/substrate/demo/primitives/src/lib.rs @@ -21,47 +21,32 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc))] - -#[cfg(feature = "std")] -#[macro_use] -extern crate serde_derive; -#[cfg(feature = "std")] -extern crate serde; +#[cfg(feature = "std")] extern crate serde; extern crate substrate_runtime_std as rstd; +extern crate substrate_runtime_primitives as runtime_primitives; extern crate substrate_primitives as primitives; -#[cfg(test)] -extern crate substrate_serializer; - extern crate substrate_codec as codec; -macro_rules! try_opt { - ($e: expr) => { - match $e { - Some(x) => x, - None => return None, - } - } -} - -pub mod block; - -pub use self::block::{Header, Log, Digest}; -pub use self::block::Number as BlockNumber; +/// An index to a block. +pub type BlockNumber = u64; /// Alias to Ed25519 pubkey that identifies an account on the relay chain. This will almost /// certainly continue to be the same as the substrate's `AuthorityId`. pub type AccountId = primitives::AuthorityId; +/// Balance of an account. +pub type Balance = u64; + /// The Ed25519 pub key of an session that belongs to an authority of the relay chain. This is /// exactly equivalent to what the substrate calls an "authority". pub type SessionKey = primitives::AuthorityId; /// Index of a transaction in the relay chain. -pub type TxOrder = u64; +pub type Index = u64; /// A hash of some data used by the relay chain. pub type Hash = primitives::H256; -/// Alias to 520-bit hash when used in the context of a signature on the relay chain. -pub type Signature = primitives::hash::H512; +/// Alias to 512-bit hash when used in the context of a signature on the relay chain. +pub type Signature = runtime_primitives::traits::Ed25519Signature; diff --git a/substrate/demo/runtime/Cargo.toml b/substrate/demo/runtime/Cargo.toml index 4033111d7d..cb9988ffc9 100644 --- a/substrate/demo/runtime/Cargo.toml +++ b/substrate/demo/runtime/Cargo.toml @@ -9,25 +9,44 @@ hex-literal = "0.1.0" log = { version = "0.3", optional = true } serde = { version = "1.0", default_features = false } serde_derive = { version = "1.0", optional = true } +safe-mix = { path = "../../safe-mix", default_features = false} substrate-codec = { path = "../../substrate/codec" } substrate-runtime-std = { path = "../../substrate/runtime-std" } substrate-runtime-io = { path = "../../substrate/runtime-io" } substrate-runtime-support = { path = "../../substrate/runtime-support" } substrate-primitives = { path = "../../substrate/primitives" } substrate-keyring = { path = "../../substrate/keyring" } +substrate-runtime-consensus = { path = "../../substrate/runtime/consensus" } +substrate-runtime-council = { path = "../../substrate/runtime/council" } +substrate-runtime-democracy = { path = "../../substrate/runtime/democracy" } +substrate-runtime-executive = { path = "../../substrate/runtime/executive" } +substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" } +substrate-runtime-session = { path = "../../substrate/runtime/session" } +substrate-runtime-staking = { path = "../../substrate/runtime/staking" } +substrate-runtime-system = { path = "../../substrate/runtime/system" } +substrate-runtime-timestamp = { path = "../../substrate/runtime/timestamp" } demo-primitives = { path = "../primitives" } -integer-sqrt = "0.1.0" [features] default = ["std"] std = [ "substrate-codec/std", + "substrate-primitives/std", "substrate-runtime-std/std", "substrate-runtime-io/std", "substrate-runtime-support/std", - "substrate-primitives/std", + "substrate-runtime-consensus/std", + "substrate-runtime-council/std", + "substrate-runtime-democracy/std", + "substrate-runtime-executive/std", + "substrate-runtime-primitives/std", + "substrate-runtime-session/std", + "substrate-runtime-staking/std", + "substrate-runtime-system/std", + "substrate-runtime-timestamp/std", "demo-primitives/std", "serde_derive", "serde/std", - "log" + "log", + "safe-mix/std" ] diff --git a/substrate/demo/runtime/src/api.rs b/substrate/demo/runtime/src/api.rs deleted file mode 100644 index d590150061..0000000000 --- a/substrate/demo/runtime/src/api.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Demo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Demo. If not, see . - -use runtime::{system, consensus, session}; - -impl_stubs!( - execute_block => |block| system::internal::execute_block(block), - initialise_block => |header| system::internal::initialise_block(&header), - execute_transaction => |utx| system::internal::execute_transaction(utx), - finalise_block => |()| system::internal::finalise_block(), - validator_count => |()| session::validator_count(), - validators => |()| session::validators(), - authorities => |()| consensus::authorities() -); diff --git a/substrate/demo/runtime/src/block.rs b/substrate/demo/runtime/src/block.rs deleted file mode 100644 index 182f9ca89b..0000000000 --- a/substrate/demo/runtime/src/block.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Demo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Demo. If not, see . - -//! Block and header type definitions. - -use rstd::prelude::*; -use codec::{Input, Slicable}; -use transaction::UncheckedTransaction; - -pub use demo_primitives::block::{Header, Digest, Log, Number, HeaderHash}; - -/// The block "body": A bunch of transactions. -pub type Body = Vec; - -/// A block on the chain. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub struct Block { - /// The block header. - pub header: Header, - /// All relay-chain transactions. - pub transactions: Body, -} - -impl Slicable for Block { - fn decode(input: &mut I) -> Option { - let (header, transactions) = Slicable::decode(input)?; - Some(Block { header, transactions }) - } - - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - v.extend(self.header.encode()); - v.extend(self.transactions.encode()); - - v - } -} diff --git a/substrate/demo/runtime/src/dispatch.rs b/substrate/demo/runtime/src/dispatch.rs deleted file mode 100644 index 8290d071aa..0000000000 --- a/substrate/demo/runtime/src/dispatch.rs +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Demo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Demo. If not, see . - -//! Dispatch system. Just dispatches calls. - -use runtime::{staking, democracy}; -pub use rstd::prelude::Vec; -pub use codec::{Slicable, Input, NonTrivialSlicable}; - -/// Implement a dispatch module to create a pairing of a dispatch trait and enum. -#[macro_export] -macro_rules! impl_dispatch { - ( - pub mod $mod_name:ident; - $( - fn $fn_name:ident( - $( - $param_name:ident : $param:ty - ),* - ) - = $id:expr ; - )* - ) => { - pub mod $mod_name { - use super::*; - - #[derive(Clone, Copy, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] - #[repr(u32)] - #[allow(non_camel_case_types)] - enum Id { - $( - #[allow(non_camel_case_types)] - $fn_name = $id, - )* - } - - impl Id { - /// Derive `Some` value from a `u8`, or `None` if it's invalid. - fn from_u8(value: u8) -> Option { - match value { - $( - $id => Some(Id::$fn_name), - )* - _ => None, - } - } - } - - #[derive(Clone, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] - #[allow(missing_docs)] - pub enum Call { - $( - #[allow(non_camel_case_types)] - $fn_name ( $( $param ),* ) - ,)* - } - - pub trait Dispatch: Sized { - $( - fn $fn_name (self, $( $param_name: $param ),* ); - )* - } - - impl Call { - pub fn dispatch(self, d: D) { - match self { - $( - Call::$fn_name( $( $param_name ),* ) => - d.$fn_name( $( $param_name ),* ), - )* - } - } - } - - impl $crate::dispatch::Slicable for Call { - fn decode(input: &mut I) -> Option { - let id = u8::decode(input).and_then(Id::from_u8)?; - Some(match id { - $( - Id::$fn_name => { - $( - let $param_name = $crate::dispatch::Slicable::decode(input)?; - )* - Call :: $fn_name( $( $param_name ),* ) - } - )* - }) - } - - fn encode(&self) -> $crate::dispatch::Vec { - let mut v = $crate::dispatch::Vec::new(); - match *self { - $( - Call::$fn_name( - $( - ref $param_name - ),* - ) => { - (Id::$fn_name as u8).using_encoded(|s| v.extend(s)); - $( - $param_name.using_encoded(|s| v.extend(s)); - )* - } - )* - } - v - } - - fn using_encoded R>(&self, f: F) -> R { - f(self.encode().as_slice()) - } - } - impl $crate::dispatch::NonTrivialSlicable for Call {} - } - } -} - -macro_rules! impl_meta_dispatch { - ( - pub mod $super_name:ident; - path $path:ident; - trait $trait:ty; - $( - $camelcase:ident(mod $sub_name:ident) = $id:expr ; - )* - ) => { - pub mod $super_name { - use super::*; - - #[derive(Clone, Copy, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] - #[repr(u32)] - #[allow(non_camel_case_types)] - enum Id { - $( - #[allow(non_camel_case_types)] - $camelcase = $id, - )* - } - - impl Id { - /// Derive `Some` value from a `u8`, or `None` if it's invalid. - fn from_u8(value: u8) -> Option { - match value { - $( - $id => Some(Id::$camelcase), - )* - _ => None, - } - } - } - - #[derive(Clone, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] - #[allow(missing_docs)] - pub enum Call { - $( - #[allow(non_camel_case_types)] - $camelcase ( $crate::runtime::$sub_name::$path::Call ) - ,)* - } - - impl Call { - pub fn dispatch(self, d: $trait) { - match self { - $( - Call::$camelcase(x) => x.dispatch(d), - )* - } - } - } - - impl $crate::dispatch::Slicable for Call { - fn decode(input: &mut I) -> Option { - let id = u8::decode(input).and_then(Id::from_u8)?; - Some(match id { - $( - Id::$camelcase => - Call::$camelcase( $crate::dispatch::Slicable::decode(input)? ), - )* - }) - } - - fn encode(&self) -> Vec { - let mut v = $crate::dispatch::Vec::new(); - match *self { - $( - Call::$camelcase( ref sub ) => { - (Id::$camelcase as u8).using_encoded(|s| v.extend(s)); - sub.using_encoded(|s| v.extend(s)); - } - )* - } - v - } - - fn using_encoded R>(&self, f: F) -> R { - f(self.encode().as_slice()) - } - } - impl $crate::dispatch::NonTrivialSlicable for Call {} - } - } -} - -impl_meta_dispatch! { - pub mod public; - path public; - trait staking::PublicPass; - Session(mod session) = 1; - Staking(mod staking) = 2; - Timestamp(mod timestamp) = 3; - Democracy(mod democracy) = 5; - Council(mod council) = 6; - CouncilVote(mod council) = 7; -} - -impl_meta_dispatch! { - pub mod privileged; - path privileged; - trait democracy::PrivPass; - System(mod system) = 0; - Session(mod session) = 1; - Staking(mod staking) = 2; - Democracy(mod democracy) = 5; - Council(mod council) = 6; - CouncilVote(mod council) = 7; -} - -pub use self::privileged::Call as PrivCall; -pub use self::public::Call as PubCall; diff --git a/substrate/demo/runtime/src/genesismap.rs b/substrate/demo/runtime/src/genesismap.rs deleted file mode 100644 index 5fa83499b3..0000000000 --- a/substrate/demo/runtime/src/genesismap.rs +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Demo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Demo. If not, see . - -//! Tool for creating the genesis block. - -use codec::{KeyedVec, Joiner}; -use std::collections::HashMap; -use runtime_io::twox_128; -use runtime_support::{Hashable, StorageMap, StorageList, StorageValue}; -use primitives::Block; -use demo_primitives::{BlockNumber, AccountId}; -use runtime::staking::Balance; -use runtime::{staking, session, consensus, system, democracy, council, council_vote}; - -/// Configuration of a general Substrate Demo genesis block. -pub struct GenesisConfig { - pub validators: Vec, - pub authorities: Vec, - pub balances: Vec<(AccountId, Balance)>, - pub block_time: u64, - pub session_length: BlockNumber, - pub sessions_per_era: BlockNumber, - pub bonding_duration: BlockNumber, - pub launch_period: BlockNumber, - pub voting_period: BlockNumber, - pub minimum_deposit: Balance, - pub candidacy_bond: Balance, - pub voter_bond: Balance, - pub present_slash_per_voter: Balance, - pub carry_count: u32, - pub presentation_duration: BlockNumber, - pub council_election_voting_period: BlockNumber, - pub council_term_duration: BlockNumber, - pub desired_seats: u32, - pub inactive_grace_period: BlockNumber, - pub cooloff_period: BlockNumber, - pub council_proposal_voting_period: BlockNumber, -} - -impl GenesisConfig { - pub fn new_simple(authorities_validators: Vec, balance: Balance) -> Self { - GenesisConfig { - validators: authorities_validators.clone(), - authorities: authorities_validators.clone(), - balances: authorities_validators.iter().map(|v| (v.clone(), balance)).collect(), - block_time: 30, // 30 second block time. - session_length: 120, // that's 1 hour per session. - sessions_per_era: 24, // 24 hours per era. - bonding_duration: 90, // 90 days per bond. - launch_period: 120 * 24 * 14, // 2 weeks per public referendum - voting_period: 120 * 24 * 28, // 4 weeks to discuss & vote on an active referendum - minimum_deposit: 1000, // 1000 as the minimum deposit for a referendum - candidacy_bond: 1000, // 1000 to become a council candidate - voter_bond: 100, // 100 down to vote for a candidate - present_slash_per_voter: 1, // slash by 1 per voter for an invalid presentation. - carry_count: 24, // carry over the 24 runners-up to the next council election - presentation_duration: 120 * 24, // one day for presenting winners. - council_election_voting_period: 7 * 120 * 24, // one week period between possible council elections. - council_term_duration: 180 * 120 * 24, // 180 day term duration for the council. - desired_seats: 0, // start with no council: we'll raise this once the stake has been dispersed a bit. - inactive_grace_period: 1, // one addition vote should go by before an inactive voter can be reaped. - cooloff_period: 90 * 120 * 24, // 90 day cooling off period if council member vetoes a proposal. - council_proposal_voting_period: 7 * 120 * 24, // 7 day voting period for council members. - } - } - - pub fn genesis_map(&self) -> HashMap, Vec> { - let wasm_runtime = include_bytes!("../wasm/genesis.wasm").to_vec(); - vec![ - (session::SessionLength::key(), vec![].and(&self.session_length)), - (session::Validators::key(), vec![].and(&self.validators)), - - (&staking::Intention::len_key()[..], vec![].and(&0u32)), - (&staking::SessionsPerEra::key()[..], vec![].and(&self.sessions_per_era)), - (&staking::CurrentEra::key()[..], vec![].and(&0u64)), - - (democracy::LaunchPeriod::key(), vec![].and(&self.launch_period)), - (democracy::VotingPeriod::key(), vec![].and(&self.voting_period)), - (democracy::MinimumDeposit::key(), vec![].and(&self.minimum_deposit)), - - (council::CandidacyBond::key(), vec![].and(&self.candidacy_bond)), - (council::VotingBond::key(), vec![].and(&self.voter_bond)), - (council::PresentSlashPerVoter::key(), vec![].and(&self.present_slash_per_voter)), - (council::CarryCount::key(), vec![].and(&self.carry_count)), - (council::PresentationDuration::key(), vec![].and(&self.presentation_duration)), - (council::VotingPeriod::key(), vec![].and(&self.council_election_voting_period)), - (council::TermDuration::key(), vec![].and(&self.council_term_duration)), - (council::DesiredSeats::key(), vec![].and(&self.desired_seats)), - (council::InactiveGracePeriod::key(), vec![].and(&self.inactive_grace_period)), - - (council_vote::CooloffPeriod::key(), vec![].and(&self.cooloff_period)), - (council_vote::VotingPeriod::key(), vec![].and(&self.council_proposal_voting_period)) - ].into_iter() - .map(|(k, v)| (k.into(), v)) - .chain(self.balances.iter() - .map(|&(account, balance)| (staking::FreeBalanceOf::key_for(&account), vec![].and(&balance))) - ) - .map(|(k, v)| (twox_128(&k[..])[..].to_vec(), v.to_vec())) - .chain(vec![ - (system::CODE.to_vec(), wasm_runtime), - (consensus::AUTHORITY_COUNT[..].into(), vec![].and(&(self.authorities.len() as u32))), - ].into_iter()) - .chain(self.authorities.iter() - .enumerate() - .map(|(i, account)| ((i as u32).to_keyed_vec(consensus::AUTHORITY_AT), vec![].and(account))) - ) - .collect() - } -} - -pub fn additional_storage_with_genesis(genesis_block: &Block) -> HashMap, Vec> { - use codec::Slicable; - map![ - system::BlockHashAt::key_for(&0) => genesis_block.header.blake2_256().encode() - ] -} diff --git a/substrate/demo/runtime/src/lib.rs b/substrate/demo/runtime/src/lib.rs index 9dc1ca8a13..e6ac39823b 100644 --- a/substrate/demo/runtime/src/lib.rs +++ b/substrate/demo/runtime/src/lib.rs @@ -18,30 +18,150 @@ #![cfg_attr(not(feature = "std"), no_std)] -#[allow(unused_imports)] #[macro_use] extern crate substrate_runtime_std as rstd; -#[macro_use] extern crate substrate_runtime_io as runtime_io; -#[macro_use] extern crate substrate_runtime_support as runtime_support; -#[cfg(any(feature = "std", test))] extern crate substrate_keyring as keyring; +#[macro_use] +extern crate substrate_runtime_io as runtime_io; -#[cfg(feature = "std")] #[macro_use] extern crate serde_derive; -#[cfg(feature = "std")] extern crate serde; +#[macro_use] +extern crate substrate_runtime_support as runtime_support; -#[cfg(feature = "std")] extern crate rustc_hex; +#[macro_use] +extern crate substrate_runtime_primitives as runtime_primitives; -extern crate substrate_codec as codec; -#[cfg(feature = "std")] #[macro_use] extern crate substrate_primitives as primitives; +extern crate substrate_runtime_std as rstd; +extern crate substrate_runtime_consensus as consensus; +extern crate substrate_runtime_council as council; +extern crate substrate_runtime_democracy as democracy; +extern crate substrate_runtime_executive as executive; +extern crate substrate_runtime_session as session; +extern crate substrate_runtime_staking as staking; +extern crate substrate_runtime_system as system; +extern crate substrate_runtime_timestamp as timestamp; extern crate demo_primitives; -#[cfg(test)] #[macro_use] extern crate hex_literal; +use rstd::prelude::*; +use runtime_io::BlakeTwo256; +use demo_primitives::{AccountId, Balance, BlockNumber, Hash, Index, SessionKey, Signature}; +use runtime_primitives::generic; +use runtime_primitives::traits::{Identity, HasPublicAux}; -extern crate integer_sqrt; +#[cfg(any(feature = "std", test))] +pub use runtime_primitives::BuildExternalities; -#[macro_use] pub mod dispatch; +/// Concrete runtime type used to parameterize the various modules. +pub struct Concrete; -pub mod safe_mix; -pub mod block; -pub mod transaction; -pub mod runtime; -pub mod api; +impl HasPublicAux for Concrete { + type PublicAux = AccountId; +} -#[cfg(feature = "std")] pub mod genesismap; +impl timestamp::Trait for Concrete { + type Value = u64; +} + +/// Timestamp module for this concrete runtime. +pub type Timestamp = timestamp::Module; + +impl consensus::Trait for Concrete { + type SessionKey = SessionKey; +} + +/// Consensus module for this concrete runtime. +pub type Consensus = consensus::Module; + +impl system::Trait for Concrete { + type Index = Index; + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hashing = BlakeTwo256; + type Digest = generic::Digest>; + type AccountId = AccountId; + type Header = generic::Header>; +} + +/// System module for this concrete runtime. +pub type System = system::Module; + +impl session::Trait for Concrete { + type PublicAux = ::PublicAux; + type ConvertAccountIdToSessionKey = Identity; +} + +/// Session module for this concrete runtime. +pub type Session = session::Module; + +impl staking::Trait for Concrete { + type Balance = Balance; + type DetermineContractAddress = BlakeTwo256; +} + +/// Staking module for this concrete runtime. +pub type Staking = staking::Module; + +impl democracy::Trait for Concrete { + type Proposal = PrivCall; +} + +/// Democracy module for this concrete runtime. +pub type Democracy = democracy::Module; + +impl council::Trait for Concrete {} + +/// Council module for this concrete runtime. +pub type Council = council::Module; +/// Council voting module for this concrete runtime. +pub type CouncilVoting = council::voting::Module; + +impl_outer_dispatch! { + pub enum Call where aux: ::PublicAux { + Session = 1, + Staking = 2, + Timestamp = 3, + Democracy = 5, + Council = 6, + CouncilVoting = 7, + } + + pub enum PrivCall { + Consensus = 0, + Session = 1, + Staking = 2, + Democracy = 5, + Council = 6, + CouncilVoting = 7, + } +} + +/// Block header type as expected by this runtime. +pub type Header = generic::Header>; +/// Block type as expected by this runtime. +pub type Block = generic::Block, AccountId, Index, Call, Signature>; +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +/// Extrinsic type as expected by this runtime. +pub type Extrinsic = generic::Extrinsic; +/// Executive: handles dispatch to the various modules. +pub type Executive = executive::Executive; + +impl_outer_config! { + pub struct GenesisConfig for Concrete { + ConsensusConfig => consensus, + SystemConfig => system, + SessionConfig => session, + StakingConfig => staking, + DemocracyConfig => democracy, + CouncilConfig => council, + } +} + +pub mod api { + impl_stubs!( + authorities => |()| super::Consensus::authorities(), + initialise_block => |header| super::Executive::initialise_block(&header), + apply_extrinsic => |extrinsic| super::Executive::apply_extrinsic(extrinsic), + execute_block => |block| super::Executive::execute_block(block), + finalise_block => |()| super::Executive::finalise_block(), + validator_count => |()| super::Session::validator_count(), + validators => |()| super::Session::validators() + ); +} diff --git a/substrate/demo/runtime/src/runtime/consensus.rs b/substrate/demo/runtime/src/runtime/consensus.rs deleted file mode 100644 index 8d631d0bb8..0000000000 --- a/substrate/demo/runtime/src/runtime/consensus.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Demo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Demo. If not, see . - -//! Conensus module for runtime; manages the authority set ready for the native code. - -use rstd::prelude::*; -use runtime_support::storage::unhashed::StorageVec; -use demo_primitives::SessionKey; - -pub const AUTHORITY_AT: &'static[u8] = b":auth:"; -pub const AUTHORITY_COUNT: &'static[u8] = b":auth:len"; - -struct AuthorityStorageVec {} -impl StorageVec for AuthorityStorageVec { - type Item = SessionKey; - const PREFIX: &'static[u8] = AUTHORITY_AT; -} - -/// Get the current set of authorities. These are the session keys. -pub fn authorities() -> Vec { - AuthorityStorageVec::items() -} - -pub mod internal { - use super::*; - - /// Set the current set of authorities' session keys. - /// - /// Called by `next_session` only. - pub fn set_authorities(authorities: &[SessionKey]) { - AuthorityStorageVec::set_items(authorities); - } - - /// Set a single authority by index. - pub fn set_authority(index: u32, key: &SessionKey) { - AuthorityStorageVec::set_item(index, key); - } -} diff --git a/substrate/demo/runtime/src/runtime/council.rs b/substrate/demo/runtime/src/runtime/council.rs deleted file mode 100644 index 6f9c155839..0000000000 --- a/substrate/demo/runtime/src/runtime/council.rs +++ /dev/null @@ -1,1312 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Demo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Demo. If not, see . - -//! Council system: Handles the voting in and maintenance of council members. - -use rstd::prelude::*; -use codec::KeyedVec; -use runtime_support::{StorageMap, StorageValue}; -use demo_primitives::{AccountId, Hash, BlockNumber}; -use runtime::{staking, system, session}; -use runtime::democracy::PrivPass; -use runtime::staking::{PublicPass, Balance}; - -// no polynomial attacks: -// -// all unbonded public operations should be constant time. -// all other public operations must be linear time in terms of prior public operations and: -// - those "valid" ones that cost nothing be limited to a constant number per single protected operation -// - the rest costing the same order as the computational complexity -// all protected operations must complete in at most O(public operations) -// -// we assume "beneficial" transactions will have the same access as attack transactions. -// -// any storage requirements should be bonded by the same order as the volume. - -// public operations: -// - express approvals (you pay in a "voter" bond the first time you do this; O(1); one extra DB entry, one DB change) -// - remove active voter (you get your "voter" bond back; O(1); one fewer DB entry, one DB change) -// - remove inactive voter (either you or the target is removed; if the target, you get their "voter" bond back; O(1); one fewer DB entry, one DB change) -// - submit candidacy (you pay a "candidate" bond; O(1); one extra DB entry, two DB changes) -// - present winner/runner-up (you may pay a "presentation" bond of O(voters) if the presentation is invalid; O(voters) compute; ) -// protected operations: -// - remove candidacy (remove all votes for a candidate) (one fewer DB entry, two DB changes) - -// to avoid a potentially problematic case of not-enough approvals prior to voting causing a -// back-to-back votes that have no way of ending, then there's a forced grace period between votes. -// to keep the system as stateless as possible (making it a bit easier to reason about), we just -// restrict when votes can begin to blocks that lie on boundaries (`voting_period`). - -// for an approval vote of C councilers: - -// top K runners-up are maintained between votes. all others are discarded. -// - candidate removed & bond returned when elected. -// - candidate removed & bond burned when discarded. - -// at the point that the vote ends (), all voters' balances are snapshotted. - -// for B blocks following, there's a counting period whereby each of the candidates that believe -// they fall in the top K+C voted can present themselves. they get the total stake -// recorded (based on the snapshot); an ordered list is maintained (the leaderboard). Noone may -// present themselves that, if elected, would result in being included twice on the council -// (important since existing councilers will will have their approval votes as it may be that they -// don't get removed), nor if existing presenters would mean they're not in the top K+C. - -// following B blocks, the top C candidates are elected and have their bond returned. the top C -// candidates and all other candidates beyond the top C+K are cleared. - -// vote-clearing happens lazily; for an approval to count, the most recent vote at the time of the -// voter's most recent vote must be no later than the most recent vote at the time that the -// candidate in the approval position was registered there. as candidates are removed from the -// register and others join in their place, this prevent an approval meant for an earlier candidate -// being used to elect a new candidate. - -// the candidate list increases as needed, but the contents (though not really the capacity) reduce -// after each vote as all but K entries are cleared. newly registering candidates must use cleared -// entries before they increase the capacity. - -pub type VoteIndex = u32; - -storage_items! { - // parameters - // How much should be locked up in order to submit one's candidacy. - pub CandidacyBond get(candidacy_bond): b"cou:cbo" => required Balance; - // How much should be locked up in order to be able to submit votes. - pub VotingBond get(voting_bond): b"cou:vbo" => required Balance; - // The punishment, per voter, if you provide an invalid presentation. - pub PresentSlashPerVoter get(present_slash_per_voter): b"cou:pss" => required Balance; - // How many runners-up should have their approvals persist until the next vote. - pub CarryCount get(carry_count): b"cou:cco" => required u32; - // How long to give each top candidate to present themselves after the vote ends. - pub PresentationDuration get(presentation_duration): b"cou:pdu" => required BlockNumber; - // How many votes need to go by after a voter's last vote before they can be reaped if their - // approvals are moot. - pub InactiveGracePeriod get(inactivity_grace_period): b"cou:vgp" => required VoteIndex; - // How often (in blocks) to check for new votes. - pub VotingPeriod get(voting_period): b"cou:per" => required BlockNumber; - // How long each position is active for. - pub TermDuration get(term_duration): b"cou:trm" => required BlockNumber; - // Number of accounts that should be sitting on the council. - pub DesiredSeats get(desired_seats): b"cou:sts" => required u32; - - // permanent state (always relevant, changes only at the finalisation of voting) - // The current council. When there's a vote going on, this should still be used for executive - // matters. - pub ActiveCouncil get(active_council): b"cou:act" => default Vec<(AccountId, BlockNumber)>; - // The total number of votes that have happened or are in progress. - pub VoteCount get(vote_index): b"cou:vco" => default VoteIndex; - - // persistent state (always relevant, changes constantly) - // The last cleared vote index that this voter was last active at. - pub ApprovalsOf get(approvals_of): b"cou:apr" => default map [ AccountId => Vec ]; - // The vote index and list slot that the candidate `who` was registered or `None` if they are not - // currently registered. - pub RegisterInfoOf get(candidate_reg_info): b"cou:reg" => map [ AccountId => (VoteIndex, u32) ]; - // The last cleared vote index that this voter was last active at. - pub LastActiveOf get(voter_last_active): b"cou:lac" => map [ AccountId => VoteIndex ]; - // The present voter list. - pub Voters get(voters): b"cou:vrs" => default Vec; - // The present candidate list. - pub Candidates get(candidates): b"cou:can" => default Vec; // has holes - pub CandidateCount get(candidate_count): b"cou:cnc" => default u32; - - // temporary state (only relevant during finalisation/presentation) - // The accounts holding the seats that will become free on the next tally. - pub NextFinalise get(next_finalise): b"cou:nxt" => (BlockNumber, u32, Vec); - // The stakes as they were at the point that the vote ended. - pub SnapshotedStakes get(snapshoted_stakes): b"cou:sss" => required Vec; - // Get the leaderboard if we;re in the presentation phase. - pub Leaderboard get(leaderboard): b"cou:win" => Vec<(Balance, AccountId)>; // ORDERED low -> high -} - -/// True if we're currently in a presentation period. -pub fn presentation_active() -> bool { - NextFinalise::exists() -} - -/// If `who` a candidate at the moment? -pub fn is_a_candidate(who: &AccountId) -> bool { - RegisterInfoOf::exists(who) -} - -/// Determine the block that a vote can happen on which is no less than `n`. -pub fn next_vote_from(n: BlockNumber) -> BlockNumber { - let voting_period = voting_period(); - (n + voting_period - 1) / voting_period * voting_period -} - -/// The block number on which the tally for the next election will happen. `None` only if the -/// desired seats of the council is zero. -pub fn next_tally() -> Option { - let desired_seats = desired_seats(); - if desired_seats == 0 { - None - } else { - let c = active_council(); - let (next_possible, count, coming) = - if let Some((tally_end, comers, leavers)) = next_finalise() { - // if there's a tally in progress, then next tally can begin immediately afterwards - (tally_end, c.len() - leavers.len() + comers as usize, comers) - } else { - (system::block_number(), c.len(), 0) - }; - if count < desired_seats as usize { - Some(next_possible) - } else { - // next tally begins once enough council members expire to bring members below desired. - if desired_seats <= coming { - // the entire amount of desired seats is less than those new members - we'll have - // to wait until they expire. - Some(next_possible + term_duration()) - } else { - Some(c[c.len() - (desired_seats - coming) as usize].1) - } - }.map(next_vote_from) - } -} - -impl_dispatch! { - pub mod public; - fn set_approvals(votes: Vec, index: VoteIndex) = 0; - fn reap_inactive_voter(signed_index: u32, who: AccountId, who_index: u32, assumed_vote_index: VoteIndex) = 1; - fn retract_voter(index: u32) = 2; - fn submit_candidacy(slot: u32) = 3; - fn present_winner(candidate: AccountId, total: Balance, index: VoteIndex) = 4; -} - -impl<'a> public::Dispatch for PublicPass<'a> { - /// Set candidate approvals. Approval slots stay valid as long as candidates in those slots - /// are registered. - fn set_approvals(self, votes: Vec, index: VoteIndex) { - assert!(!presentation_active()); - assert_eq!(index, vote_index()); - if !LastActiveOf::exists(*self) { - // not yet a voter - deduct bond. - staking::internal::reserve_balance(&self, voting_bond()); - Voters::put({ - let mut v = Voters::get(); - v.push(self.clone()); - v - }); - } - ApprovalsOf::insert(*self, votes); - LastActiveOf::insert(*self, index); - } - - /// Remove a voter. For it not to be a bond-consuming no-op, all approved candidate indices - /// must now be either unregistered or registered to a candidate that registered the slot after - /// the voter gave their last approval set. - /// - /// May be called by anyone. Returns the voter deposit to `signed`. - fn reap_inactive_voter(self, signed_index: u32, who: AccountId, who_index: u32, assumed_vote_index: VoteIndex) { - assert!(!presentation_active(), "cannot reap during presentation period"); - assert!(voter_last_active(*self).is_some(), "reaper must be a voter"); - let last_active = voter_last_active(&who).expect("target for inactivity cleanup must be active"); - assert!(assumed_vote_index == vote_index(), "vote index not current"); - assert!(last_active < assumed_vote_index - inactivity_grace_period(), "cannot reap during grace perid"); - let voters = voters(); - let signed_index = signed_index as usize; - let who_index = who_index as usize; - assert!(signed_index < voters.len() && voters[signed_index] == *self, "bad reporter index"); - assert!(who_index < voters.len() && voters[who_index] == who, "bad target index"); - - // will definitely kill one of signed or who now. - - let valid = !approvals_of(&who).iter() - .zip(candidates().iter()) - .any(|(&appr, addr)| - appr && - *addr != AccountId::default() && - candidate_reg_info(addr) - .expect("all items in candidates list are registered").0 <= last_active); - - remove_voter( - if valid { &who } else { &self }, - if valid { who_index } else { signed_index }, - voters - ); - if valid { - staking::internal::transfer_reserved_balance(&who, &self, voting_bond()); - } else { - staking::internal::slash_reserved(&self, voting_bond()); - } - } - - /// Remove a voter. All votes are cancelled and the voter deposit is returned. - fn retract_voter(self, index: u32) { - assert!(!presentation_active(), "cannot retract when presenting"); - assert!(LastActiveOf::exists(*self), "cannot retract non-voter"); - let voters = voters(); - let index = index as usize; - assert!(index < voters.len(), "retraction index invalid"); - assert!(voters[index] == *self, "retraction index mismatch"); - remove_voter(&self, index, voters); - staking::internal::unreserve_balance(&self, voting_bond()); - } - - /// Submit oneself for candidacy. - /// - /// Account must have enough transferrable funds in it to pay the bond. - fn submit_candidacy(self, slot: u32) { - assert!(!is_a_candidate(&self), "duplicate candidate submission"); - assert!(staking::internal::deduct_unbonded(&self, candidacy_bond()), "candidate has not enough funds"); - - let slot = slot as usize; - let count = CandidateCount::get() as usize; - let candidates = Candidates::get(); - assert!( - (slot == count && count == candidates.len()) || - (slot < candidates.len() && candidates[slot] == AccountId::default()), - "invalid candidate slot" - ); - - let mut candidates = candidates; - if slot == candidates.len() { - candidates.push(self.clone()); - } else { - candidates[slot] = self.clone(); - } - Candidates::put(candidates); - CandidateCount::put(count as u32 + 1); - RegisterInfoOf::insert(*self, (vote_index(), slot as u32)); - } - - /// Claim that `signed` is one of the top carry_count() + current_vote().1 candidates. - /// Only works if the `block_number >= current_vote().0` and `< current_vote().0 + presentation_duration()`` - /// `signed` should have at least - fn present_winner(self, candidate: AccountId, total: Balance, index: VoteIndex) { - assert_eq!(index, vote_index(), "index not current"); - let (_, _, expiring) = NextFinalise::get() - .expect("cannot present outside of presentation period"); - let stakes = SnapshotedStakes::get(); - let voters = Voters::get(); - let bad_presentation_punishment = present_slash_per_voter() * voters.len() as Balance; - assert!(staking::can_slash(&self, bad_presentation_punishment), "presenter must have sufficient slashable funds"); - - let mut leaderboard = leaderboard().expect("leaderboard must exist while present phase active"); - assert!(total > leaderboard[0].0, "candidate not worthy of leaderboard"); - - if let Some(p) = active_council().iter().position(|&(ref c, _)| c == &candidate) { - assert!(p < expiring.len(), "candidate must not form a duplicated member if elected"); - } - - let (registered_since, candidate_index): (VoteIndex, u32) = - RegisterInfoOf::get(candidate).expect("presented candidate must be current"); - let actual_total = voters.iter() - .zip(stakes.iter()) - .filter_map(|(voter, stake)| - match voter_last_active(voter) { - Some(b) if b >= registered_since => - approvals_of(voter).get(candidate_index as usize) - .and_then(|approved| if *approved { Some(*stake) } else { None }), - _ => None, - }) - .sum(); - let dupe = leaderboard.iter().find(|&&(_, ref c)| c == &candidate).is_some(); - if total == actual_total && !dupe { - // insert into leaderboard - leaderboard[0] = (total, candidate.clone()); - leaderboard.sort_by_key(|&(t, _)| t); - Leaderboard::put(leaderboard); - } else { - staking::internal::slash(&self, bad_presentation_punishment); - } - } -} - -impl_dispatch! { - pub mod privileged; - fn set_desired_seats(count: u32) = 0; - fn remove_member(who: AccountId) = 1; - fn set_presentation_duration(count: BlockNumber) = 2; - fn set_term_duration(count: BlockNumber) = 3; -} - -impl privileged::Dispatch for PrivPass { - /// Set the desired member count; if lower than the current count, then seats will not be up - /// election when they expire. If more, then a new vote will be started if one is not already - /// in progress. - fn set_desired_seats(self, count: u32) { - DesiredSeats::put(count); - } - - /// Remove a particular member. A tally will happen instantly (if not already in a presentation - /// period) to fill the seat if removal means that the desired members are not met. - /// This is effective immediately. - fn remove_member(self, who: AccountId) { - let new_council: Vec<(AccountId, BlockNumber)> = active_council() - .into_iter() - .filter(|i| i.0 != who) - .collect(); - ActiveCouncil::put(new_council); - } - - /// Set the presentation duration. If there is current a vote being presented for, will - /// invoke `finalise_vote`. - fn set_presentation_duration(self, count: BlockNumber) { - PresentationDuration::put(count); - } - - /// Set the presentation duration. If there is current a vote being presented for, will - /// invoke `finalise_vote`. - fn set_term_duration(self, count: BlockNumber) { - TermDuration::put(count); - } -} - -pub mod internal { - use super::*; - - /// Check there's nothing to do this block - pub fn end_block() { - let block_number = system::block_number(); - if block_number % voting_period() == 0 { - if let Some(number) = next_tally() { - if block_number == number { - start_tally(); - } - } - } - if let Some((number, _, _)) = next_finalise() { - if block_number == number { - finalise_tally(); - } - } - } -} - -/// Remove a voter from the system. Trusts that voters()[index] != voter. -fn remove_voter(voter: &AccountId, index: usize, mut voters: Vec) { - Voters::put({ voters.swap_remove(index); voters }); - ApprovalsOf::remove(voter); - LastActiveOf::remove(voter); -} - -/// Close the voting, snapshot the staking and the number of seats that are actually up for grabs. -fn start_tally() { - let active_council = active_council(); - let desired_seats = desired_seats() as usize; - let number = system::block_number(); - let expiring = active_council.iter().take_while(|i| i.1 == number).map(|i| i.0).collect::>(); - if active_council.len() - expiring.len() < desired_seats { - let empty_seats = desired_seats - (active_council.len() - expiring.len()); - NextFinalise::put((number + presentation_duration(), empty_seats as u32, expiring)); - - let voters = Voters::get(); - let votes = voters.iter().map(staking::balance).collect::>(); - SnapshotedStakes::put(votes); - - // initialise leaderboard. - let leaderboard_size = empty_seats + carry_count() as usize; - Leaderboard::put(vec![(0 as Balance, AccountId::default()); leaderboard_size]); - } -} - -/// Finalise the vote, removing each of the `removals` and inserting `seats` of the most approved -/// candidates in their place. If the total council members is less than the desired membership -/// a new vote is started. -/// Clears all presented candidates, returning the bond of the elected ones. -fn finalise_tally() { - SnapshotedStakes::kill(); - let (_, coming, expiring): (BlockNumber, u32, Vec) = NextFinalise::take() - .expect("finalise can only be called after a tally is started."); - let leaderboard: Vec<(Balance, AccountId)> = Leaderboard::take().unwrap_or_default(); - let new_expiry = system::block_number() + term_duration(); - - // return bond to winners. - let candidacy_bond = candidacy_bond(); - for &(_, ref w) in leaderboard.iter() - .rev() - .take_while(|&&(b, _)| b != 0) - .take(coming as usize) - { - staking::internal::refund(w, candidacy_bond); - } - - // set the new council. - let mut new_council: Vec<_> = active_council() - .into_iter() - .skip(expiring.len()) - .chain(leaderboard.iter() - .rev() - .take_while(|&&(b, _)| b != 0) - .take(coming as usize) - .cloned() - .map(|(_, a)| (a, new_expiry))) - .collect(); - new_council.sort_by_key(|&(_, expiry)| expiry); - ActiveCouncil::put(new_council); - - // clear all except runners-up from candidate list. - let candidates = Candidates::get(); - let mut new_candidates = vec![AccountId::default(); candidates.len()]; // shrink later. - let runners_up = leaderboard.into_iter() - .rev() - .take_while(|&(b, _)| b != 0) - .skip(coming as usize) - .map(|(_, a)| (a, candidate_reg_info(&a).expect("runner up must be registered").1)); - let mut count = 0u32; - for (address, slot) in runners_up { - new_candidates[slot as usize] = address; - count += 1; - } - for (old, new) in candidates.iter().zip(new_candidates.iter()) { - if old != new { - // removed - kill it - RegisterInfoOf::remove(old); - } - } - // discard any superfluous slots. - if let Some(last_index) = new_candidates.iter().rposition(|c| *c != AccountId::default()) { - new_candidates.truncate(last_index + 1); - } - Candidates::put(new_candidates); - CandidateCount::put(count); - VoteCount::put(vote_index() + 1); -} - -#[cfg(test)] -pub mod testing { - use super::*; - use runtime_io::{twox_128, TestExternalities}; - use codec::Joiner; - use runtime::democracy; - - pub fn externalities() -> TestExternalities { - let extras: TestExternalities = map![ - twox_128(CandidacyBond::key()).to_vec() => vec![].and(&9u64), - twox_128(VotingBond::key()).to_vec() => vec![].and(&3u64), - twox_128(PresentSlashPerVoter::key()).to_vec() => vec![].and(&1u64), - twox_128(CarryCount::key()).to_vec() => vec![].and(&2u32), - twox_128(PresentationDuration::key()).to_vec() => vec![].and(&2u64), - twox_128(VotingPeriod::key()).to_vec() => vec![].and(&4u64), - twox_128(TermDuration::key()).to_vec() => vec![].and(&5u64), - twox_128(DesiredSeats::key()).to_vec() => vec![].and(&2u32), - twox_128(InactiveGracePeriod::key()).to_vec() => vec![].and(&1u32) - ]; - democracy::testing::externalities() - .into_iter().chain(extras.into_iter()).collect() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use runtime_io::{with_externalities, twox_128, TestExternalities}; - use codec::{KeyedVec, Joiner}; - use keyring::Keyring::*; - use demo_primitives::AccountId; - use runtime::{staking, session, democracy}; - use super::public::Dispatch; - use super::privileged::Dispatch as PrivDispatch; - - fn new_test_ext() -> TestExternalities { - testing::externalities() - } - - #[test] - fn basic_environment_works() { - let mut t = new_test_ext(); - with_externalities(&mut t, || { - system::testing::set_block_number(1); - assert_eq!(next_vote_from(1), 4); - assert_eq!(next_vote_from(4), 4); - assert_eq!(next_vote_from(5), 8); - assert_eq!(vote_index(), 0); - assert_eq!(candidacy_bond(), 9); - assert_eq!(voting_bond(), 3); - assert_eq!(present_slash_per_voter(), 1); - assert_eq!(presentation_duration(), 2); - assert_eq!(voting_period(), 4); - assert_eq!(term_duration(), 5); - assert_eq!(desired_seats(), 2); - assert_eq!(carry_count(), 2); - - assert_eq!(active_council(), vec![]); - assert_eq!(next_tally(), Some(4)); - assert_eq!(presentation_active(), false); - assert_eq!(next_finalise(), None); - - assert_eq!(candidates(), Vec::::new()); - assert_eq!(is_a_candidate(&Alice), false); - assert_eq!(candidate_reg_info(*Alice), None); - - assert_eq!(voters(), Vec::::new()); - assert_eq!(voter_last_active(*Alice), None); - assert_eq!(approvals_of(*Alice), vec![]); - }); - } - - #[test] - fn simple_candidate_submission_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - assert_eq!(candidates(), Vec::::new()); - assert_eq!(candidate_reg_info(*Alice), None); - assert_eq!(candidate_reg_info(*Bob), None); - assert_eq!(is_a_candidate(&Alice), false); - assert_eq!(is_a_candidate(&Bob), false); - - PublicPass::test(&Alice).submit_candidacy(0); - assert_eq!(candidates(), vec![Alice.to_raw_public()]); - assert_eq!(candidate_reg_info(*Alice), Some((0 as VoteIndex, 0u32))); - assert_eq!(candidate_reg_info(*Bob), None); - assert_eq!(is_a_candidate(&Alice), true); - assert_eq!(is_a_candidate(&Bob), false); - - PublicPass::test(&Bob).submit_candidacy(1); - assert_eq!(candidates(), vec![Alice.to_raw_public(), Bob.into()]); - assert_eq!(candidate_reg_info(*Alice), Some((0 as VoteIndex, 0u32))); - assert_eq!(candidate_reg_info(*Bob), Some((0 as VoteIndex, 1u32))); - assert_eq!(is_a_candidate(&Alice), true); - assert_eq!(is_a_candidate(&Bob), true); - }); - } - - fn new_test_ext_with_candidate_holes() -> TestExternalities { - let mut t = new_test_ext(); - t.insert(twox_128(Candidates::key()).to_vec(), vec![].and(&vec![AccountId::default(), AccountId::default(), Alice.to_raw_public()])); - t.insert(twox_128(CandidateCount::key()).to_vec(), vec![].and(&1u32)); - t.insert(twox_128(&RegisterInfoOf::key_for(*Alice)).to_vec(), vec![].and(&(0 as VoteIndex, 2u32))); - t - } - - #[test] - fn candidate_submission_using_free_slot_should_work() { - let mut t = new_test_ext_with_candidate_holes(); - - with_externalities(&mut t, || { - system::testing::set_block_number(1); - assert_eq!(candidates(), vec![AccountId::default(), AccountId::default(), Alice.to_raw_public()]); - - PublicPass::test(&Bob).submit_candidacy(1); - assert_eq!(candidates(), vec![AccountId::default(), Bob.into(), Alice.to_raw_public()]); - - PublicPass::test(&Charlie).submit_candidacy(0); - assert_eq!(candidates(), vec![Charlie.into(), Bob.into(), Alice.to_raw_public()]); - }); - } - - #[test] - fn candidate_submission_using_alternative_free_slot_should_work() { - let mut t = new_test_ext_with_candidate_holes(); - - with_externalities(&mut t, || { - system::testing::set_block_number(1); - assert_eq!(candidates(), vec![AccountId::default(), AccountId::default(), Alice.into()]); - - PublicPass::test(&Bob).submit_candidacy(0); - assert_eq!(candidates(), vec![Bob.into(), AccountId::default(), Alice.into()]); - - PublicPass::test(&Charlie).submit_candidacy(1); - assert_eq!(candidates(), vec![Bob.to_raw_public(), Charlie.into(), Alice.into()]); - }); - } - - #[test] - #[should_panic(expected = "invalid candidate slot")] - fn candidate_submission_not_using_free_slot_should_panic() { - let mut t = new_test_ext_with_candidate_holes(); - - with_externalities(&mut t, || { - system::testing::set_block_number(1); - PublicPass::test(&Dave).submit_candidacy(3); - }); - } - - #[test] - #[should_panic(expected = "invalid candidate slot")] - fn bad_candidate_slot_submission_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - assert_eq!(candidates(), Vec::::new()); - PublicPass::test(&Alice).submit_candidacy(1); - }); - } - - #[test] - #[should_panic(expected = "invalid candidate slot")] - fn non_free_candidate_slot_submission_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - assert_eq!(candidates(), Vec::::new()); - PublicPass::test(&Alice).submit_candidacy(0); - PublicPass::test(&Bob).submit_candidacy(0); - }); - } - - #[test] - #[should_panic(expected = "duplicate candidate submission")] - fn dupe_candidate_submission_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - assert_eq!(candidates(), Vec::::new()); - PublicPass::test(&Alice).submit_candidacy(0); - PublicPass::test(&Alice).submit_candidacy(1); - }); - } - - #[test] - #[should_panic(expected = "candidate has not enough funds")] - fn poor_candidate_submission_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - assert_eq!(candidates(), Vec::::new()); - PublicPass::test(&One).submit_candidacy(0); - }); - } - - #[test] - fn voting_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - - PublicPass::test(&Eve).submit_candidacy(0); - - PublicPass::test(&Alice).set_approvals(vec![true], 0); - PublicPass::test(&Dave).set_approvals(vec![true], 0); - - assert_eq!(approvals_of(*Alice), vec![true]); - assert_eq!(approvals_of(*Dave), vec![true]); - assert_eq!(voters(), vec![Alice.to_raw_public(), Dave.into()]); - - PublicPass::test(&Bob).submit_candidacy(1); - PublicPass::test(&Charlie).submit_candidacy(2); - - PublicPass::test(&Bob).set_approvals(vec![false, true, true], 0); - PublicPass::test(&Charlie).set_approvals(vec![false, true, true], 0); - - assert_eq!(approvals_of(*Alice), vec![true]); - assert_eq!(approvals_of(*Dave), vec![true]); - assert_eq!(approvals_of(*Bob), vec![false, true, true]); - assert_eq!(approvals_of(*Charlie), vec![false, true, true]); - - assert_eq!(voters(), vec![Alice.to_raw_public(), Dave.into(), Bob.into(), Charlie.into()]); - }); - } - - #[test] - fn resubmitting_voting_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - - PublicPass::test(&Eve).submit_candidacy(0); - PublicPass::test(&Dave).set_approvals(vec![true], 0); - - assert_eq!(approvals_of(*Dave), vec![true]); - - PublicPass::test(&Bob).submit_candidacy(1); - PublicPass::test(&Charlie).submit_candidacy(2); - PublicPass::test(&Dave).set_approvals(vec![true, false, true], 0); - - assert_eq!(approvals_of(*Dave), vec![true, false, true]); - }); - } - - #[test] - fn retracting_voter_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - - PublicPass::test(&Eve).submit_candidacy(0); - PublicPass::test(&Bob).submit_candidacy(1); - PublicPass::test(&Charlie).submit_candidacy(2); - - PublicPass::test(&Alice).set_approvals(vec![true], 0); - PublicPass::test(&Bob).set_approvals(vec![false, true, true], 0); - PublicPass::test(&Charlie).set_approvals(vec![false, true, true], 0); - PublicPass::test(&Dave).set_approvals(vec![true, false, true], 0); - - assert_eq!(voters(), vec![Alice.to_raw_public(), Bob.into(), Charlie.into(), Dave.into()]); - assert_eq!(approvals_of(*Alice), vec![true]); - assert_eq!(approvals_of(*Bob), vec![false, true, true]); - assert_eq!(approvals_of(*Charlie), vec![false, true, true]); - assert_eq!(approvals_of(*Dave), vec![true, false, true]); - - PublicPass::test(&Alice).retract_voter(0); - - assert_eq!(voters(), vec![Dave.to_raw_public(), Bob.into(), Charlie.into()]); - assert_eq!(approvals_of(*Alice), Vec::::new()); - assert_eq!(approvals_of(*Bob), vec![false, true, true]); - assert_eq!(approvals_of(*Charlie), vec![false, true, true]); - assert_eq!(approvals_of(*Dave), vec![true, false, true]); - - PublicPass::test(&Bob).retract_voter(1); - - assert_eq!(voters(), vec![Dave.to_raw_public(), Charlie.into()]); - assert_eq!(approvals_of(*Alice), Vec::::new()); - assert_eq!(approvals_of(*Bob), Vec::::new()); - assert_eq!(approvals_of(*Charlie), vec![false, true, true]); - assert_eq!(approvals_of(*Dave), vec![true, false, true]); - - PublicPass::test(&Charlie).retract_voter(1); - - assert_eq!(voters(), vec![Dave.to_raw_public()]); - assert_eq!(approvals_of(*Alice), Vec::::new()); - assert_eq!(approvals_of(*Bob), Vec::::new()); - assert_eq!(approvals_of(*Charlie), Vec::::new()); - assert_eq!(approvals_of(*Dave), vec![true, false, true]); - }); - } - - #[test] - #[should_panic(expected = "retraction index mismatch")] - fn invalid_retraction_index_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - PublicPass::test(&Charlie).submit_candidacy(0); - PublicPass::test(&Alice).set_approvals(vec![true], 0); - PublicPass::test(&Bob).set_approvals(vec![true], 0); - PublicPass::test(&Alice).retract_voter(1); - }); - } - - #[test] - #[should_panic(expected = "retraction index invalid")] - fn overflow_retraction_index_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - PublicPass::test(&Charlie).submit_candidacy(0); - PublicPass::test(&Alice).set_approvals(vec![true], 0); - PublicPass::test(&Alice).retract_voter(1); - }); - } - - #[test] - #[should_panic(expected = "cannot retract non-voter")] - fn non_voter_retraction_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - PublicPass::test(&Charlie).submit_candidacy(0); - PublicPass::test(&Alice).set_approvals(vec![true], 0); - PublicPass::test(&Bob).retract_voter(0); - }); - } - - #[test] - fn simple_tally_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - assert!(!presentation_active()); - - PublicPass::test(&Bob).submit_candidacy(0); - PublicPass::test(&Eve).submit_candidacy(1); - PublicPass::test(&Bob).set_approvals(vec![true, false], 0); - PublicPass::test(&Eve).set_approvals(vec![false, true], 0); - internal::end_block(); - - system::testing::set_block_number(6); - assert!(presentation_active()); - PublicPass::test(&Dave).present_winner(Bob.into(), 11, 0); - PublicPass::test(&Dave).present_winner(Eve.into(), 41, 0); - assert_eq!(leaderboard(), Some(vec![(0, AccountId::default()), (0, AccountId::default()), (11, Bob.into()), (41, Eve.into())])); - - internal::end_block(); - - assert!(!presentation_active()); - assert_eq!(active_council(), vec![(Eve.to_raw_public(), 11), (Bob.into(), 11)]); - - assert!(!is_a_candidate(&Bob)); - assert!(!is_a_candidate(&Eve)); - assert_eq!(vote_index(), 1); - assert_eq!(voter_last_active(*Bob), Some(0)); - assert_eq!(voter_last_active(*Eve), Some(0)); - }); - } - - #[test] - fn double_presentations_should_be_punished() { - with_externalities(&mut new_test_ext(), || { - assert!(staking::can_slash(&Dave, 10)); - - system::testing::set_block_number(4); - PublicPass::test(&Bob).submit_candidacy(0); - PublicPass::test(&Eve).submit_candidacy(1); - PublicPass::test(&Bob).set_approvals(vec![true, false], 0); - PublicPass::test(&Eve).set_approvals(vec![false, true], 0); - internal::end_block(); - - system::testing::set_block_number(6); - PublicPass::test(&Dave).present_winner(Bob.into(), 11, 0); - PublicPass::test(&Dave).present_winner(Eve.into(), 41, 0); - PublicPass::test(&Dave).present_winner(Eve.into(), 41, 0); - internal::end_block(); - - assert_eq!(active_council(), vec![(Eve.to_raw_public(), 11), (Bob.into(), 11)]); - assert_eq!(staking::balance(&Dave), 38); - }); - } - - #[test] - fn retracting_inactive_voter_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - PublicPass::test(&Bob).submit_candidacy(0); - PublicPass::test(&Bob).set_approvals(vec![true], 0); - internal::end_block(); - - system::testing::set_block_number(6); - PublicPass::test(&Dave).present_winner(Bob.into(), 11, 0); - internal::end_block(); - - system::testing::set_block_number(8); - PublicPass::test(&Eve).submit_candidacy(0); - PublicPass::test(&Eve).set_approvals(vec![true], 1); - internal::end_block(); - - system::testing::set_block_number(10); - PublicPass::test(&Dave).present_winner(Eve.into(), 41, 1); - internal::end_block(); - - PublicPass::test(&Eve).reap_inactive_voter( - voters().iter().position(|&i| i == *Eve).unwrap() as u32, - Bob.into(), voters().iter().position(|&i| i == *Bob).unwrap() as u32, - 2 - ); - - assert_eq!(voters(), vec![Eve.to_raw_public()]); - assert_eq!(approvals_of(*Bob).len(), 0); - assert_eq!(staking::balance(&Bob), 17); - assert_eq!(staking::balance(&Eve), 53); - }); - } - - #[test] - #[should_panic(expected = "candidate must not form a duplicated member if elected")] - fn presenting_for_double_election_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - PublicPass::test(&Bob).submit_candidacy(0); - PublicPass::test(&Bob).set_approvals(vec![true], 0); - internal::end_block(); - - system::testing::set_block_number(6); - PublicPass::test(&Dave).present_winner(Bob.into(), 11, 0); - internal::end_block(); - - system::testing::set_block_number(8); - PublicPass::test(&Bob).submit_candidacy(0); - PublicPass::test(&Bob).set_approvals(vec![true], 1); - internal::end_block(); - - system::testing::set_block_number(10); - PublicPass::test(&Dave).present_winner(Bob.into(), 11, 1); - }); - } - - #[test] - fn retracting_inactive_voter_with_other_candidates_in_slots_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - PublicPass::test(&Bob).submit_candidacy(0); - PublicPass::test(&Bob).set_approvals(vec![true], 0); - internal::end_block(); - - system::testing::set_block_number(6); - PublicPass::test(&Dave).present_winner(Bob.into(), 11, 0); - internal::end_block(); - - system::testing::set_block_number(8); - PublicPass::test(&Eve).submit_candidacy(0); - PublicPass::test(&Eve).set_approvals(vec![true], 1); - internal::end_block(); - - system::testing::set_block_number(10); - PublicPass::test(&Dave).present_winner(Eve.into(), 41, 1); - internal::end_block(); - - system::testing::set_block_number(11); - PublicPass::test(&Alice).submit_candidacy(0); - - PublicPass::test(&Eve).reap_inactive_voter( - voters().iter().position(|&i| i == *Eve).unwrap() as u32, - Bob.into(), voters().iter().position(|&i| i == *Bob).unwrap() as u32, - 2 - ); - - assert_eq!(voters(), vec![Eve.to_raw_public()]); - assert_eq!(approvals_of(*Bob).len(), 0); - assert_eq!(staking::balance(&Bob), 17); - assert_eq!(staking::balance(&Eve), 53); - }); - } - - #[test] - #[should_panic(expected = "bad reporter index")] - fn retracting_inactive_voter_with_bad_reporter_index_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - PublicPass::test(&Bob).submit_candidacy(0); - PublicPass::test(&Bob).set_approvals(vec![true], 0); - internal::end_block(); - - system::testing::set_block_number(6); - PublicPass::test(&Dave).present_winner(Bob.into(), 8, 0); - internal::end_block(); - - system::testing::set_block_number(8); - PublicPass::test(&Eve).submit_candidacy(0); - PublicPass::test(&Eve).set_approvals(vec![true], 1); - internal::end_block(); - - system::testing::set_block_number(10); - PublicPass::test(&Dave).present_winner(Eve.into(), 38, 1); - internal::end_block(); - - PublicPass::test(&Bob).reap_inactive_voter( - 42, - Bob.into(), voters().iter().position(|&i| i == *Bob).unwrap() as u32, - 2 - ); - }); - } - - #[test] - #[should_panic(expected = "bad target index")] - fn retracting_inactive_voter_with_bad_target_index_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - PublicPass::test(&Bob).submit_candidacy(0); - PublicPass::test(&Bob).set_approvals(vec![true], 0); - internal::end_block(); - - system::testing::set_block_number(6); - PublicPass::test(&Dave).present_winner(Bob.into(), 8, 0); - internal::end_block(); - - system::testing::set_block_number(8); - PublicPass::test(&Eve).submit_candidacy(0); - PublicPass::test(&Eve).set_approvals(vec![true], 1); - internal::end_block(); - - system::testing::set_block_number(10); - PublicPass::test(&Dave).present_winner(Eve.into(), 38, 1); - internal::end_block(); - - PublicPass::test(&Bob).reap_inactive_voter( - voters().iter().position(|&i| i == *Bob).unwrap() as u32, - Bob.into(), 42, - 2 - ); - }); - } - - #[test] - fn attempting_to_retract_active_voter_should_slash_reporter() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - PublicPass::test(&Bob).submit_candidacy(0); - PublicPass::test(&Charlie).submit_candidacy(1); - PublicPass::test(&Dave).submit_candidacy(2); - PublicPass::test(&Eve).submit_candidacy(3); - PublicPass::test(&Bob).set_approvals(vec![true, false, false, false], 0); - PublicPass::test(&Charlie).set_approvals(vec![false, true, false, false], 0); - PublicPass::test(&Dave).set_approvals(vec![false, false, true, false], 0); - PublicPass::test(&Eve).set_approvals(vec![false, false, false, true], 0); - internal::end_block(); - - system::testing::set_block_number(6); - PublicPass::test(&Dave).present_winner(Bob.into(), 11, 0); - PublicPass::test(&Dave).present_winner(Charlie.into(), 21, 0); - PublicPass::test(&Dave).present_winner(Dave.into(), 31, 0); - PublicPass::test(&Dave).present_winner(Eve.into(), 41, 0); - internal::end_block(); - - system::testing::set_block_number(8); - PrivPass::test().set_desired_seats(3); - internal::end_block(); - - system::testing::set_block_number(10); - PublicPass::test(&Dave).present_winner(Bob.into(), 11, 1); - PublicPass::test(&Dave).present_winner(Charlie.into(), 21, 1); - internal::end_block(); - - PublicPass::test(&Dave).reap_inactive_voter( - voters().iter().position(|&i| i == *Dave).unwrap() as u32, - Bob.into(), voters().iter().position(|&i| i == *Bob).unwrap() as u32, - 2 - ); - - assert_eq!(voters(), vec![Bob.to_raw_public(), Charlie.into(), Eve.into()]); - assert_eq!(approvals_of(*Dave).len(), 0); - assert_eq!(staking::balance(&Dave), 37); - }); - } - - #[test] - #[should_panic(expected = "reaper must be a voter")] - fn attempting_to_retract_inactive_voter_by_nonvoter_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - PublicPass::test(&Bob).submit_candidacy(0); - PublicPass::test(&Bob).set_approvals(vec![true], 0); - internal::end_block(); - - system::testing::set_block_number(6); - PublicPass::test(&Dave).present_winner(Bob.into(), 11, 0); - internal::end_block(); - - system::testing::set_block_number(8); - PublicPass::test(&Eve).submit_candidacy(0); - PublicPass::test(&Eve).set_approvals(vec![true], 1); - internal::end_block(); - - system::testing::set_block_number(10); - PublicPass::test(&Dave).present_winner(Eve.into(), 41, 1); - internal::end_block(); - - PublicPass::test(&Dave).reap_inactive_voter( - 0, - Bob.into(), voters().iter().position(|&i| i == *Bob).unwrap() as u32, - 2 - ); - }); - } - - #[test] - #[should_panic(expected = "candidate not worthy of leaderboard")] - fn presenting_loser_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - PublicPass::test(&Alice).submit_candidacy(0); - PublicPass::test(&Ferdie).set_approvals(vec![true], 0); - PublicPass::test(&Bob).submit_candidacy(1); - PublicPass::test(&Bob).set_approvals(vec![false, true], 0); - PublicPass::test(&Charlie).submit_candidacy(2); - PublicPass::test(&Charlie).set_approvals(vec![false, false, true], 0); - PublicPass::test(&Dave).submit_candidacy(3); - PublicPass::test(&Dave).set_approvals(vec![false, false, false, true], 0); - PublicPass::test(&Eve).submit_candidacy(4); - PublicPass::test(&Eve).set_approvals(vec![false, false, false, false, true], 0); - internal::end_block(); - - system::testing::set_block_number(6); - PublicPass::test(&Dave).present_winner(Alice.into(), 60, 0); - PublicPass::test(&Dave).present_winner(Charlie.into(), 21, 0); - PublicPass::test(&Dave).present_winner(Dave.into(), 31, 0); - PublicPass::test(&Dave).present_winner(Eve.into(), 41, 0); - PublicPass::test(&Dave).present_winner(Bob.into(), 11, 0); - }); - } - - #[test] - fn presenting_loser_first_should_not_matter() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - PublicPass::test(&Alice).submit_candidacy(0); - PublicPass::test(&Ferdie).set_approvals(vec![true], 0); - PublicPass::test(&Bob).submit_candidacy(1); - PublicPass::test(&Bob).set_approvals(vec![false, true], 0); - PublicPass::test(&Charlie).submit_candidacy(2); - PublicPass::test(&Charlie).set_approvals(vec![false, false, true], 0); - PublicPass::test(&Dave).submit_candidacy(3); - PublicPass::test(&Dave).set_approvals(vec![false, false, false, true], 0); - PublicPass::test(&Eve).submit_candidacy(4); - PublicPass::test(&Eve).set_approvals(vec![false, false, false, false, true], 0); - internal::end_block(); - - system::testing::set_block_number(6); - PublicPass::test(&Dave).present_winner(Bob.into(), 11, 0); - PublicPass::test(&Dave).present_winner(Alice.into(), 60, 0); - PublicPass::test(&Dave).present_winner(Charlie.into(), 21, 0); - PublicPass::test(&Dave).present_winner(Dave.into(), 31, 0); - PublicPass::test(&Dave).present_winner(Eve.into(), 41, 0); - - assert_eq!(leaderboard(), Some(vec![ - (21, Charlie.into()), - (31, Dave.into()), - (41, Eve.into()), - (60, Alice.to_raw_public()) - ])); - }); - } - - #[test] - #[should_panic(expected = "cannot present outside of presentation period")] - fn present_panics_outside_of_presentation_period() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - assert!(!presentation_active()); - PublicPass::test(&Eve).present_winner(Eve.into(), 1, 0); - }); - } - - #[test] - #[should_panic(expected = "index not current")] - fn present_panics_with_invalid_vote_index() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - PublicPass::test(&Bob).submit_candidacy(0); - PublicPass::test(&Eve).submit_candidacy(1); - PublicPass::test(&Bob).set_approvals(vec![true, false], 0); - PublicPass::test(&Eve).set_approvals(vec![false, true], 0); - internal::end_block(); - - system::testing::set_block_number(6); - PublicPass::test(&Dave).present_winner(Bob.into(), 11, 1); - }); - } - - #[test] - #[should_panic(expected = "presenter must have sufficient slashable funds")] - fn present_panics_when_presenter_is_poor() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - assert!(!presentation_active()); - - PublicPass::test(&Alice).submit_candidacy(0); - PublicPass::test(&Eve).submit_candidacy(1); - PublicPass::test(&Bob).set_approvals(vec![true, false], 0); - PublicPass::test(&Eve).set_approvals(vec![false, true], 0); - internal::end_block(); - - system::testing::set_block_number(6); - assert_eq!(staking::balance(&Alice), 1); - PublicPass::test(&Alice).present_winner(Alice.into(), 30, 0); - }); - } - - #[test] - fn invalid_present_tally_should_slash() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - assert!(!presentation_active()); - assert_eq!(staking::balance(&Dave), 40); - - PublicPass::test(&Bob).submit_candidacy(0); - PublicPass::test(&Eve).submit_candidacy(1); - PublicPass::test(&Bob).set_approvals(vec![true, false], 0); - PublicPass::test(&Eve).set_approvals(vec![false, true], 0); - internal::end_block(); - - system::testing::set_block_number(6); - PublicPass::test(&Dave).present_winner(Bob.into(), 80, 0); - - assert_eq!(staking::balance(&Dave), 38); - }); - } - - #[test] - fn runners_up_should_be_kept() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - assert!(!presentation_active()); - - PublicPass::test(&Alice).submit_candidacy(0); - PublicPass::test(&Ferdie).set_approvals(vec![true], 0); - PublicPass::test(&Bob).submit_candidacy(1); - PublicPass::test(&Bob).set_approvals(vec![false, true], 0); - PublicPass::test(&Charlie).submit_candidacy(2); - PublicPass::test(&Charlie).set_approvals(vec![false, false, true], 0); - PublicPass::test(&Dave).submit_candidacy(3); - PublicPass::test(&Dave).set_approvals(vec![false, false, false, true], 0); - PublicPass::test(&Eve).submit_candidacy(4); - PublicPass::test(&Eve).set_approvals(vec![false, false, false, false, true], 0); - - internal::end_block(); - - system::testing::set_block_number(6); - assert!(presentation_active()); - PublicPass::test(&Dave).present_winner(Alice.into(), 60, 0); - assert_eq!(leaderboard(), Some(vec![ - (0, AccountId::default()), - (0, AccountId::default()), - (0, AccountId::default()), - (60, Alice.to_raw_public()) - ])); - PublicPass::test(&Dave).present_winner(Charlie.into(), 21, 0); - PublicPass::test(&Dave).present_winner(Dave.into(), 31, 0); - PublicPass::test(&Dave).present_winner(Eve.into(), 41, 0); - assert_eq!(leaderboard(), Some(vec![ - (21, Charlie.into()), - (31, Dave.into()), - (41, Eve.into()), - (60, Alice.to_raw_public()) - ])); - - internal::end_block(); - - assert!(!presentation_active()); - assert_eq!(active_council(), vec![(Alice.to_raw_public(), 11), (Eve.into(), 11)]); - - assert!(!is_a_candidate(&Alice)); - assert!(!is_a_candidate(&Eve)); - assert!(!is_a_candidate(&Bob)); - assert!(is_a_candidate(&Charlie)); - assert!(is_a_candidate(&Dave)); - assert_eq!(vote_index(), 1); - assert_eq!(voter_last_active(*Bob), Some(0)); - assert_eq!(voter_last_active(*Charlie), Some(0)); - assert_eq!(voter_last_active(*Dave), Some(0)); - assert_eq!(voter_last_active(*Eve), Some(0)); - assert_eq!(voter_last_active(*Ferdie), Some(0)); - assert_eq!(candidate_reg_info(*Charlie), Some((0, 2))); - assert_eq!(candidate_reg_info(*Dave), Some((0, 3))); - }); - } - - #[test] - fn second_tally_should_use_runners_up() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(4); - PublicPass::test(&Alice).submit_candidacy(0); - PublicPass::test(&Ferdie).set_approvals(vec![true], 0); - PublicPass::test(&Bob).submit_candidacy(1); - PublicPass::test(&Bob).set_approvals(vec![false, true], 0); - PublicPass::test(&Charlie).submit_candidacy(2); - PublicPass::test(&Charlie).set_approvals(vec![false, false, true], 0); - PublicPass::test(&Dave).submit_candidacy(3); - PublicPass::test(&Dave).set_approvals(vec![false, false, false, true], 0); - PublicPass::test(&Eve).submit_candidacy(4); - PublicPass::test(&Eve).set_approvals(vec![false, false, false, false, true], 0); - internal::end_block(); - - system::testing::set_block_number(6); - PublicPass::test(&Dave).present_winner(Alice.into(), 60, 0); - PublicPass::test(&Dave).present_winner(Charlie.into(), 21, 0); - PublicPass::test(&Dave).present_winner(Dave.into(), 31, 0); - PublicPass::test(&Dave).present_winner(Eve.into(), 41, 0); - internal::end_block(); - - system::testing::set_block_number(8); - PublicPass::test(&Ferdie).set_approvals(vec![false, false, true, false], 1); - PrivPass::test().set_desired_seats(3); - internal::end_block(); - - system::testing::set_block_number(10); - PublicPass::test(&Dave).present_winner(Charlie.into(), 81, 1); - PublicPass::test(&Dave).present_winner(Dave.into(), 31, 1); - internal::end_block(); - - assert!(!presentation_active()); - assert_eq!(active_council(), vec![(Alice.to_raw_public(), 11), (Eve.into(), 11), (Charlie.into(), 15)]); - - assert!(!is_a_candidate(&Alice)); - assert!(!is_a_candidate(&Bob)); - assert!(!is_a_candidate(&Charlie)); - assert!(!is_a_candidate(&Eve)); - assert!(is_a_candidate(&Dave)); - assert_eq!(vote_index(), 2); - assert_eq!(voter_last_active(*Bob), Some(0)); - assert_eq!(voter_last_active(*Charlie), Some(0)); - assert_eq!(voter_last_active(*Dave), Some(0)); - assert_eq!(voter_last_active(*Eve), Some(0)); - assert_eq!(voter_last_active(*Ferdie), Some(1)); - - assert_eq!(candidate_reg_info(*Dave), Some((0, 3))); - }); - } -} diff --git a/substrate/demo/runtime/src/runtime/council_vote.rs b/substrate/demo/runtime/src/runtime/council_vote.rs deleted file mode 100644 index 876bb906e7..0000000000 --- a/substrate/demo/runtime/src/runtime/council_vote.rs +++ /dev/null @@ -1,493 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Demo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Demo. If not, see . - -//! Council voting system. - -use rstd::prelude::*; -use rstd::borrow::Borrow; -use codec::{KeyedVec, Slicable, Input, NonTrivialSlicable}; -use runtime_support::Hashable; -use runtime_support::{StorageValue, StorageMap}; -use demo_primitives::{AccountId, Hash, BlockNumber}; -use runtime::{system, democracy, council}; -use runtime::staking::{PublicPass, Balance}; -use runtime::democracy::PrivPass; -use dispatch::PrivCall as Proposal; - -type ProposalHash = [u8; 32]; - -storage_items! { - pub CooloffPeriod get(cooloff_period): b"cov:cooloff" => required BlockNumber; - pub VotingPeriod get(voting_period): b"cov:period" => required BlockNumber; - pub Proposals get(proposals): b"cov:prs" => default Vec<(BlockNumber, ProposalHash)>; // ordered by expiry. - pub ProposalOf get(proposal_of): b"cov:pro" => map [ ProposalHash => Proposal ]; - pub ProposalVoters get(proposal_voters): b"cov:voters:" => default map [ ProposalHash => Vec ]; - pub CouncilVoteOf get(vote_of): b"cov:vote:" => map [ (ProposalHash, AccountId) => bool ]; - pub VetoedProposal get(veto_of): b"cov:veto:" => map [ ProposalHash => (BlockNumber, Vec) ]; -} - -pub fn is_vetoed>(proposal: B) -> bool { - VetoedProposal::get(proposal.borrow()) - .map(|(expiry, _): (BlockNumber, Vec)| system::block_number() < expiry) - .unwrap_or(false) -} - -fn set_veto_of(proposal: &ProposalHash, expiry: BlockNumber, vetoers: Vec) { - VetoedProposal::insert(proposal, (expiry, vetoers)); -} - -fn kill_veto_of(proposal: &ProposalHash) { - VetoedProposal::remove(proposal); -} - -pub fn will_still_be_councillor_at(who: &AccountId, n: BlockNumber) -> bool { - council::active_council().iter() - .find(|&&(ref a, _)| a == who) - .map(|&(_, expires)| expires > n) - .unwrap_or(false) -} - -pub fn is_councillor(who: &AccountId) -> bool { - council::active_council().iter() - .any(|&(ref a, _)| a == who) -} - -pub fn tally(proposal_hash: &ProposalHash) -> (u32, u32, u32) { - generic_tally(proposal_hash, |w: &AccountId, p: &ProposalHash| CouncilVoteOf::get((*p, *w))) -} - -fn take_tally(proposal_hash: &ProposalHash) -> (u32, u32, u32) { - generic_tally(proposal_hash, |w: &AccountId, p: &ProposalHash| CouncilVoteOf::take((*p, *w))) -} - -fn generic_tally Option>(proposal_hash: &ProposalHash, vote_of: F) -> (u32, u32, u32) { - let c = council::active_council(); - let (approve, reject) = c.iter() - .filter_map(|&(ref a, _)| vote_of(a, proposal_hash)) - .map(|approve| if approve { (1, 0) } else { (0, 1) }) - .fold((0, 0), |(a, b), (c, d)| (a + c, b + d)); - (approve, reject, c.len() as u32 - approve - reject) -} - -fn set_proposals(p: &Vec<(BlockNumber, ProposalHash)>) { - Proposals::put(p); -} - -fn take_proposal_if_expiring_at(n: BlockNumber) -> Option<(Proposal, ProposalHash)> { - let mut proposals = proposals(); - match proposals.first() { - Some(&(expiry, hash)) if expiry == n => { - // yes this is horrible, but fixing it will need substantial work in storage. - set_proposals(&proposals[1..].to_vec()); - let proposal = ProposalOf::take(hash).expect("all queued proposal hashes must have associated proposals"); - Some((proposal, hash)) - } - _ => None, - } -} - -impl_dispatch! { - pub mod public; - fn propose(proposal: Box) = 0; - fn vote(proposal: ProposalHash, approve: bool) = 1; - fn veto(proposal_hash: ProposalHash) = 2; -} - -impl<'a> public::Dispatch for PublicPass<'a> { - fn propose(self, proposal: Box) { - let expiry = system::block_number() + voting_period(); - assert!(will_still_be_councillor_at(&self, expiry)); - - let proposal_hash = proposal.blake2_256(); - - assert!(!is_vetoed(&proposal_hash)); - - let mut proposals = proposals(); - proposals.push((expiry, proposal_hash)); - proposals.sort_by_key(|&(expiry, _)| expiry); - set_proposals(&proposals); - - ProposalOf::insert(proposal_hash, *proposal); - ProposalVoters::insert(proposal_hash, vec![*self]); - CouncilVoteOf::insert((proposal_hash, *self), true); - } - - fn vote(self, proposal: ProposalHash, approve: bool) { - if vote_of((*self, proposal)).is_none() { - let mut voters = proposal_voters(&proposal); - voters.push(*self); - ProposalVoters::insert(proposal, voters); - } - CouncilVoteOf::insert((proposal, *self), approve); - } - - fn veto(self, proposal_hash: ProposalHash) { - assert!(is_councillor(&self), "only councillors may veto council proposals"); - assert!(ProposalVoters::exists(&proposal_hash), "proposal must exist to be vetoed"); - - let mut existing_vetoers = veto_of(&proposal_hash) - .map(|pair| pair.1) - .unwrap_or_else(Vec::new); - let insert_position = existing_vetoers.binary_search(&self) - .expect_err("a councillor may not veto a proposal twice"); - existing_vetoers.insert(insert_position, *self); - set_veto_of(&proposal_hash, system::block_number() + cooloff_period(), existing_vetoers); - - set_proposals(&proposals().into_iter().filter(|&(_, h)| h != proposal_hash).collect::>()); - ProposalVoters::remove(proposal_hash); - ProposalOf::remove(proposal_hash); - for (c, _) in council::active_council() { - CouncilVoteOf::remove((proposal_hash, c)); - } - } -} - -impl_dispatch! { - pub mod privileged; - fn set_cooloff_period(blocks: BlockNumber) = 0; - fn set_voting_period(blocks: BlockNumber) = 1; -} - -impl privileged::Dispatch for PrivPass { - fn set_cooloff_period(self, blocks: BlockNumber) { - CooloffPeriod::put(blocks); - } - - fn set_voting_period(self, blocks: BlockNumber) { - VotingPeriod::put(blocks); - } -} - -pub mod internal { - use super::*; - use runtime::democracy::privileged::Dispatch; - use runtime::democracy::VoteThreshold; - use runtime::democracy::internal::start_referendum; - - pub fn end_block(now: BlockNumber) { - while let Some((proposal, proposal_hash)) = take_proposal_if_expiring_at(now) { - let tally = take_tally(&proposal_hash); - if let &Proposal::Democracy(democracy::privileged::Call::cancel_referendum(ref_index)) = &proposal { - if let (_, 0, 0) = tally { - democracy::internal::cancel_referendum(ref_index); - } - } else { - if tally.0 > tally.1 + tally.2 { - kill_veto_of(&proposal_hash); - match tally { - (_, 0, 0) => start_referendum(proposal, VoteThreshold::SuperMajorityAgainst), - _ => start_referendum(proposal, VoteThreshold::SimpleMajority), - }; - } - } - } - } -} - -#[cfg(test)] -pub mod testing { - use super::*; - use runtime_io::{twox_128, TestExternalities}; - use keyring::Keyring::{Alice, Bob, Charlie}; - use codec::Joiner; - use runtime::{council, democracy}; - - pub fn externalities() -> TestExternalities { - let expiry: BlockNumber = 10; - let extras: TestExternalities = map![ - twox_128(council::ActiveCouncil::key()).to_vec() => vec![].and(&vec![ - (Alice.to_raw_public(), expiry), - (Bob.into(), expiry), - (Charlie.into(), expiry) - ]), - twox_128(CooloffPeriod::key()).to_vec() => vec![].and(&2u64), - twox_128(VotingPeriod::key()).to_vec() => vec![].and(&1u64), - twox_128(democracy::VotingPeriod::key()).to_vec() => vec![].and(&3u64) - ]; - council::testing::externalities() - .into_iter().chain(extras.into_iter()).collect() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use runtime_io::{with_externalities, twox_128, TestExternalities}; - use codec::{KeyedVec, Joiner}; - use keyring::Keyring::{Alice, Bob, Charlie, Dave}; - use demo_primitives::AccountId; - use runtime::democracy::VoteThreshold; - use runtime::{staking, council, democracy}; - use super::public::Dispatch; - use super::privileged::Dispatch as PrivDispatch; - - fn new_test_ext() -> TestExternalities { - testing::externalities() - } - - #[test] - fn basic_environment_works() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - assert_eq!(staking::bonding_duration(), 0); - assert_eq!(cooloff_period(), 2); - assert_eq!(voting_period(), 1); - assert_eq!(will_still_be_councillor_at(&Alice, 1), true); - assert_eq!(will_still_be_councillor_at(&Alice, 10), false); - assert_eq!(will_still_be_councillor_at(&Dave, 10), false); - assert_eq!(is_councillor(&Alice), true); - assert_eq!(is_councillor(&Dave), false); - assert_eq!(proposals(), Vec::<(BlockNumber, ProposalHash)>::new()); - assert_eq!(proposal_voters(ProposalHash::default()), Vec::::new()); - assert_eq!(is_vetoed(&ProposalHash::default()), false); - assert_eq!(vote_of((*Alice, ProposalHash::default())), None); - assert_eq!(tally(&ProposalHash::default()), (0, 0, 3)); - }); - } - - fn sessions_per_era_proposal(value: u64) -> Proposal { - Proposal::Staking(staking::privileged::Call::set_sessions_per_era(value)) - } - - fn bonding_duration_proposal(value: u64) -> Proposal { - Proposal::Staking(staking::privileged::Call::set_bonding_duration(value)) - } - - fn cancel_referendum_proposal(id: u32) -> Proposal { - Proposal::Democracy(democracy::privileged::Call::cancel_referendum(id)) - } - - #[test] - fn referendum_cancellation_should_work_when_unanimous() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let proposal = bonding_duration_proposal(42); - democracy::internal::start_referendum(proposal.clone(), VoteThreshold::SuperMajorityApprove); - assert_eq!(democracy::active_referendums(), vec![(0, 4, proposal, VoteThreshold::SuperMajorityApprove)]); - - let cancellation = cancel_referendum_proposal(0); - let hash = cancellation.blake2_256(); - PublicPass::new(&Alice).propose(Box::new(cancellation)); - PublicPass::new(&Bob).vote(hash, true); - PublicPass::new(&Charlie).vote(hash, true); - assert_eq!(proposals(), vec![(2, hash)]); - internal::end_block(1); - - system::testing::set_block_number(2); - internal::end_block(2); - assert_eq!(democracy::active_referendums(), vec![]); - assert_eq!(staking::bonding_duration(), 0); - }); - } - - #[test] - fn referendum_cancellation_should_fail_when_not_unanimous() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let proposal = bonding_duration_proposal(42); - democracy::internal::start_referendum(proposal.clone(), VoteThreshold::SuperMajorityApprove); - - let cancellation = cancel_referendum_proposal(0); - let hash = cancellation.blake2_256(); - PublicPass::new(&Alice).propose(Box::new(cancellation)); - PublicPass::new(&Bob).vote(hash, true); - PublicPass::new(&Charlie).vote(hash, false); - internal::end_block(1); - - system::testing::set_block_number(2); - internal::end_block(2); - assert_eq!(democracy::active_referendums(), vec![(0, 4, proposal, VoteThreshold::SuperMajorityApprove)]); - }); - } - - #[test] - fn referendum_cancellation_should_fail_when_abstentions() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let proposal = bonding_duration_proposal(42); - democracy::internal::start_referendum(proposal.clone(), VoteThreshold::SuperMajorityApprove); - - let cancellation = cancel_referendum_proposal(0); - let hash = cancellation.blake2_256(); - PublicPass::new(&Alice).propose(Box::new(cancellation)); - PublicPass::new(&Bob).vote(hash, true); - internal::end_block(1); - - system::testing::set_block_number(2); - internal::end_block(2); - assert_eq!(democracy::active_referendums(), vec![(0, 4, proposal, VoteThreshold::SuperMajorityApprove)]); - }); - } - - #[test] - fn veto_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let proposal = bonding_duration_proposal(42); - let hash = proposal.blake2_256(); - PublicPass::new(&Alice).propose(Box::new(proposal.clone())); - PublicPass::new(&Bob).veto(hash); - assert_eq!(proposals().len(), 0); - assert_eq!(democracy::active_referendums().len(), 0); - }); - } - - #[test] - #[should_panic] - fn double_veto_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let proposal = bonding_duration_proposal(42); - let hash = proposal.blake2_256(); - PublicPass::new(&Alice).propose(Box::new(proposal.clone())); - PublicPass::new(&Bob).veto(hash); - - system::testing::set_block_number(3); - PublicPass::new(&Alice).propose(Box::new(proposal.clone())); - PublicPass::new(&Bob).veto(hash); - }); - } - - #[test] - #[should_panic] - fn retry_in_cooloff_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let proposal = bonding_duration_proposal(42); - let hash = proposal.blake2_256(); - PublicPass::new(&Alice).propose(Box::new(proposal.clone())); - PublicPass::new(&Bob).veto(hash); - - system::testing::set_block_number(2); - PublicPass::new(&Alice).propose(Box::new(proposal.clone())); - }); - } - - #[test] - fn retry_after_cooloff_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let proposal = bonding_duration_proposal(42); - let hash = proposal.blake2_256(); - PublicPass::new(&Alice).propose(Box::new(proposal.clone())); - PublicPass::new(&Bob).veto(hash); - - system::testing::set_block_number(3); - PublicPass::new(&Alice).propose(Box::new(proposal.clone())); - PublicPass::new(&Bob).vote(hash, false); - PublicPass::new(&Charlie).vote(hash, true); - internal::end_block(3); - - system::testing::set_block_number(4); - internal::end_block(4); - assert_eq!(proposals().len(), 0); - assert_eq!(democracy::active_referendums(), vec![(0, 7, bonding_duration_proposal(42), VoteThreshold::SimpleMajority)]); - }); - } - - #[test] - fn alternative_double_veto_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let proposal = bonding_duration_proposal(42); - let hash = proposal.blake2_256(); - PublicPass::new(&Alice).propose(Box::new(proposal.clone())); - PublicPass::new(&Bob).veto(hash); - - system::testing::set_block_number(3); - PublicPass::new(&Alice).propose(Box::new(proposal.clone())); - PublicPass::new(&Charlie).veto(hash); - assert_eq!(proposals().len(), 0); - assert_eq!(democracy::active_referendums().len(), 0); - }); - } - - #[test] - fn simple_propose_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let proposal = bonding_duration_proposal(42); - let hash = proposal.blake2_256(); - PublicPass::new(&Alice).propose(Box::new(proposal.clone())); - assert_eq!(proposals().len(), 1); - assert_eq!(proposal_voters(&hash), vec![Alice.to_raw_public()]); - assert_eq!(vote_of((hash, *Alice)), Some(true)); - assert_eq!(tally(&hash), (1, 0, 2)); - }); - } - - #[test] - fn unvoted_proposal_should_expire_without_action() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let proposal = bonding_duration_proposal(42); - PublicPass::new(&Alice).propose(Box::new(proposal.clone())); - assert_eq!(tally(&proposal.blake2_256()), (1, 0, 2)); - internal::end_block(1); - - system::testing::set_block_number(2); - internal::end_block(2); - assert_eq!(proposals().len(), 0); - assert_eq!(democracy::active_referendums().len(), 0); - }); - } - - #[test] - fn unanimous_proposal_should_expire_with_biased_referendum() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let proposal = bonding_duration_proposal(42); - PublicPass::new(&Alice).propose(Box::new(proposal.clone())); - PublicPass::new(&Bob).vote(proposal.blake2_256(), true); - PublicPass::new(&Charlie).vote(proposal.blake2_256(), true); - assert_eq!(tally(&proposal.blake2_256()), (3, 0, 0)); - internal::end_block(1); - - system::testing::set_block_number(2); - internal::end_block(2); - assert_eq!(proposals().len(), 0); - assert_eq!(democracy::active_referendums(), vec![(0, 5, proposal, VoteThreshold::SuperMajorityAgainst)]); - }); - } - - #[test] - fn majority_proposal_should_expire_with_unbiased_referendum() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let proposal = bonding_duration_proposal(42); - PublicPass::new(&Alice).propose(Box::new(proposal.clone())); - PublicPass::new(&Bob).vote(proposal.blake2_256(), true); - PublicPass::new(&Charlie).vote(proposal.blake2_256(), false); - assert_eq!(tally(&proposal.blake2_256()), (2, 1, 0)); - internal::end_block(1); - - system::testing::set_block_number(2); - internal::end_block(2); - assert_eq!(proposals().len(), 0); - assert_eq!(democracy::active_referendums(), vec![(0, 5, proposal, VoteThreshold::SimpleMajority)]); - }); - } - - #[test] - #[should_panic] - fn propose_by_public_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let proposal = bonding_duration_proposal(42); - PublicPass::new(&Dave).propose(Box::new(proposal)); - }); - } -} diff --git a/substrate/demo/runtime/src/runtime/democracy.rs b/substrate/demo/runtime/src/runtime/democracy.rs deleted file mode 100644 index d3d4a098be..0000000000 --- a/substrate/demo/runtime/src/runtime/democracy.rs +++ /dev/null @@ -1,623 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Demo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Demo. If not, see . - -//! Democratic system: Handles administration of general stakeholder voting. - -use rstd::prelude::*; -use integer_sqrt::IntegerSquareRoot; -use codec::{KeyedVec, Slicable, Input, NonTrivialSlicable}; -use runtime_support::{StorageValue, StorageMap}; -use demo_primitives::{AccountId, Hash, BlockNumber}; -use dispatch::PrivCall as Proposal; -use runtime::{staking, system, session}; -use runtime::staking::{PublicPass, Balance}; - -/// A token for privileged dispatch. Can only be created in this module. -pub struct PrivPass((),); - -impl PrivPass { - fn new() -> PrivPass { PrivPass((),) } - - #[cfg(test)] - pub fn test() -> PrivPass { PrivPass((),) } -} - -/// A proposal index. -pub type PropIndex = u32; -/// A referendum index. -pub type ReferendumIndex = u32; - -/// A means of determining if a vote is past pass threshold. -#[derive(Clone, Copy, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub enum VoteThreshold { - /// A supermajority of approvals is needed to pass this vote. - SuperMajorityApprove, - /// A supermajority of rejects is needed to fail this vote. - SuperMajorityAgainst, - /// A simple majority of approvals is needed to pass this vote. - SimpleMajority, -} - -impl Slicable for VoteThreshold { - fn decode(input: &mut I) -> Option { - u8::decode(input).and_then(|v| match v { - 0 => Some(VoteThreshold::SuperMajorityApprove), - 1 => Some(VoteThreshold::SuperMajorityAgainst), - 2 => Some(VoteThreshold::SimpleMajority), - _ => None, - }) - } - - fn using_encoded R>(&self, f: F) -> R { - match *self { - VoteThreshold::SuperMajorityApprove => 0u8, - VoteThreshold::SuperMajorityAgainst => 1u8, - VoteThreshold::SimpleMajority => 2u8, - }.using_encoded(f) - } -} -impl NonTrivialSlicable for VoteThreshold {} - -trait Approved { - /// Given `approve` votes for and `against` votes against from a total electorate size of - /// `electorate` (`electorate - (approve + against)` are abstainers), then returns true if the - /// overall outcome is in favour of approval. - fn approved(&self, approve: Balance, against: Balance, electorate: Balance) -> bool; -} - -impl Approved for VoteThreshold { - /// Given `approve` votes for and `against` votes against from a total electorate size of - /// `electorate` (`electorate - (approve + against)` are abstainers), then returns true if the - /// overall outcome is in favour of approval. - fn approved(&self, approve: Balance, against: Balance, electorate: Balance) -> bool { - let voters = approve + against; - match *self { - VoteThreshold::SuperMajorityApprove => - voters.integer_sqrt() * approve / electorate.integer_sqrt() > against, - VoteThreshold::SuperMajorityAgainst => - approve > voters.integer_sqrt() * against / electorate.integer_sqrt(), - VoteThreshold::SimpleMajority => approve > against, - } - } -} - -storage_items! { - // The number of (public) proposals that have been made so far. - pub PublicPropCount get(public_prop_count): b"dem:ppc" => default PropIndex; - // The public proposals. Unsorted. - pub PublicProps get(public_props): b"dem:pub" => default Vec<(PropIndex, Proposal, AccountId)>; - // Those who have locked a deposit. - pub DepositOf get(deposit_lockers): b"dem:dep:" => map [ PropIndex => (Balance, Vec) ]; - // How often (in blocks) new public referenda are launched. - pub LaunchPeriod get(launch_period): b"dem:lau" => required BlockNumber; - // The minimum amount to be used as a deposit for a public referendum proposal. - pub MinimumDeposit get(minimum_deposit): b"dem:min" => required Balance; - - // How often (in blocks) to check for new votes. - pub VotingPeriod get(voting_period): b"dem:per" => required BlockNumber; - - // The next free referendum index, aka the number of referendums started so far. - pub ReferendumCount get(next_free_ref_index): b"dem:rco" => default ReferendumIndex; - // The next referendum index that should be tallied. - pub NextTally get(next_tally): b"dem:nxt" => default ReferendumIndex; - // Information concerning any given referendum. - pub ReferendumInfoOf get(referendum_info): b"dem:pro:" => map [ ReferendumIndex => (BlockNumber, Proposal, VoteThreshold) ]; - - // Get the voters for the current proposal. - pub VotersFor get(voters_for): b"dem:vtr:" => default map [ ReferendumIndex => Vec ]; - - // Get the vote, if Some, of `who`. - pub VoteOf get(vote_of): b"dem:vot:" => map [ (ReferendumIndex, AccountId) => bool ]; -} - -// public proposals - -/// Get the amount locked in support of `proposal`; false if proposal isn't a valid proposal -/// index. -pub fn locked_for(proposal: PropIndex) -> Option { - deposit_lockers(proposal).map(|(d, l)| d * (l.len() as Balance)) -} - -/// Return true if `ref_index` is an on-going referendum. -pub fn is_active_referendum(ref_index: ReferendumIndex) -> bool { - ReferendumInfoOf::exists(ref_index) -} - -/// Get all referendums currently active. -pub fn active_referendums() -> Vec<(ReferendumIndex, BlockNumber, Proposal, VoteThreshold)> { - let next = NextTally::get(); - let last = ReferendumCount::get(); - (next..last).into_iter() - .filter_map(|i| referendum_info(i).map(|(n, p, t)| (i, n, p, t))) - .collect() -} - -/// Get all referendums ready for tally at block `n`. -pub fn maturing_referendums_at(n: BlockNumber) -> Vec<(ReferendumIndex, BlockNumber, Proposal, VoteThreshold)> { - let next = NextTally::get(); - let last = ReferendumCount::get(); - (next..last).into_iter() - .filter_map(|i| referendum_info(i).map(|(n, p, t)| (i, n, p, t))) - .take_while(|&(_, block_number, _, _)| block_number == n) - .collect() -} - -/// Get the voters for the current proposal. -pub fn tally(ref_index: ReferendumIndex) -> (staking::Balance, staking::Balance) { - voters_for(ref_index).iter() - .map(|a| (staking::balance(a), vote_of((ref_index, *a)).expect("all items come from `voters`; for an item to be in `voters` there must be a vote registered; qed"))) - .map(|(bal, vote)| if vote { (bal, 0) } else { (0, bal) }) - .fold((0, 0), |(a, b), (c, d)| (a + c, b + d)) -} - -impl_dispatch! { - pub mod public; - fn propose(proposal: Box, value: Balance) = 0; - fn second(proposal: PropIndex) = 1; - fn vote(ref_index: ReferendumIndex, approve_proposal: bool) = 2; -} - -impl<'a> public::Dispatch for PublicPass<'a> { - /// Propose a sensitive action to be taken. - fn propose(self, proposal: Box, value: Balance) { - assert!(value >= minimum_deposit()); - assert!(staking::internal::deduct_unbonded(&self, value)); - - let index = PublicPropCount::get(); - PublicPropCount::put(index + 1); - DepositOf::insert(index, (value, vec![*self])); - - let mut props = public_props(); - props.push((index, (*proposal).clone(), *self)); - PublicProps::put(props); - } - - /// Propose a sensitive action to be taken. - fn second(self, proposal: PropIndex) { - let mut deposit = DepositOf::get(proposal).expect("can only second an existing proposal"); - assert!(staking::internal::deduct_unbonded(&self, deposit.0)); - - deposit.1.push(*self); - DepositOf::insert(proposal, deposit); - } - - /// Vote in a referendum. If `approve_proposal` is true, the vote is to enact the proposal; - /// false would be a vote to keep the status quo.. - fn vote(self, ref_index: ReferendumIndex, approve_proposal: bool) { - if !is_active_referendum(ref_index) { - panic!("vote given for invalid referendum.") - } - if staking::balance(&self) == 0 { - panic!("transactor must have balance to signal approval."); - } - if !VoteOf::exists(&(ref_index, *self)) { - let mut voters = voters_for(ref_index); - voters.push(self.clone()); - VotersFor::insert(ref_index, voters); - } - VoteOf::insert(&(ref_index, *self), approve_proposal); - } -} - -impl_dispatch! { - pub mod privileged; - fn start_referendum(proposal: Box, vote_threshold: VoteThreshold) = 0; - fn cancel_referendum(ref_index: ReferendumIndex) = 1; -} - -impl privileged::Dispatch for PrivPass { - /// Start a referendum. - fn start_referendum(self, proposal: Box, vote_threshold: VoteThreshold) { - inject_referendum(system::block_number() + voting_period(), *proposal, vote_threshold); - } - - /// Remove a referendum. - fn cancel_referendum(self, ref_index: ReferendumIndex) { - clear_referendum(ref_index); - } -} - -pub mod internal { - use super::*; - use dispatch; - - /// Can be called directly by the council. - pub fn start_referendum(proposal: Proposal, vote_threshold: VoteThreshold) { - inject_referendum(system::block_number() + voting_period(), proposal, vote_threshold); - } - - /// Remove a referendum. - pub fn cancel_referendum(ref_index: ReferendumIndex) { - clear_referendum(ref_index); - } - - /// Current era is ending; we should finish up any proposals. - pub fn end_block(now: BlockNumber) { - // pick out another public referendum if it's time. - if now % launch_period() == 0 { - let mut public_props = public_props(); - if let Some((winner_index, _)) = public_props.iter() - .enumerate() - .max_by_key(|x| locked_for((x.1).0).expect("All current public proposals have an amount locked")) - { - let (prop_index, proposal, _) = public_props.swap_remove(winner_index); - let (deposit, depositors): (Balance, Vec) = - DepositOf::take(prop_index).expect("depositors always exist for current proposals"); - // refund depositors - for d in &depositors { - staking::internal::refund(d, deposit); - } - PublicProps::put(public_props); - inject_referendum(now + voting_period(), proposal, VoteThreshold::SuperMajorityApprove); - } - } - - // tally up votes for any expiring referenda. - for (index, _, proposal, vote_threshold) in maturing_referendums_at(now) { - let (approve, against) = tally(index); - let total_stake = staking::total_stake(); - clear_referendum(index); - if vote_threshold.approved(approve, against, total_stake) { - proposal.dispatch(PrivPass::new()); - } - NextTally::put(index + 1); - } - } -} - -/// Start a referendum -fn inject_referendum( - end: BlockNumber, - proposal: Proposal, - vote_threshold: VoteThreshold -) -> ReferendumIndex { - let ref_index = next_free_ref_index(); - if ref_index > 0 && referendum_info(ref_index - 1).map(|i| i.0 > end).unwrap_or(false) { - panic!("Cannot inject a referendum that ends earlier than preceeding referendum"); - } - - ReferendumCount::put(ref_index + 1); - ReferendumInfoOf::insert(ref_index, (end, proposal, vote_threshold)); - ref_index -} - -/// Remove all info on a referendum. -fn clear_referendum(ref_index: ReferendumIndex) { - ReferendumInfoOf::remove(ref_index); - VotersFor::remove(ref_index); - for v in voters_for(ref_index) { - VoteOf::remove((ref_index, v)); - } -} - -#[cfg(test)] -pub mod testing { - use super::*; - use runtime_io::{twox_128, TestExternalities}; - use runtime_support::{StorageList, StorageValue, StorageMap}; - use codec::Joiner; - use keyring::Keyring::*; - use runtime::{session, staking}; - - pub fn externalities() -> TestExternalities { - map![ - twox_128(session::SessionLength::key()).to_vec() => vec![].and(&1u64), - twox_128(session::Validators::key()).to_vec() => vec![].and(&vec![Alice.to_raw_public(), Bob.into(), Charlie.into()]), - twox_128(&staking::Intention::len_key()).to_vec() => vec![].and(&3u32), - twox_128(&staking::Intention::key_for(0)).to_vec() => Alice.to_raw_public_vec(), - twox_128(&staking::Intention::key_for(1)).to_vec() => Bob.to_raw_public_vec(), - twox_128(&staking::Intention::key_for(2)).to_vec() => Charlie.to_raw_public_vec(), - twox_128(&staking::FreeBalanceOf::key_for(*Alice)).to_vec() => vec![].and(&10u64), - twox_128(&staking::FreeBalanceOf::key_for(*Bob)).to_vec() => vec![].and(&20u64), - twox_128(&staking::FreeBalanceOf::key_for(*Charlie)).to_vec() => vec![].and(&30u64), - twox_128(&staking::FreeBalanceOf::key_for(*Dave)).to_vec() => vec![].and(&40u64), - twox_128(&staking::FreeBalanceOf::key_for(*Eve)).to_vec() => vec![].and(&50u64), - twox_128(&staking::FreeBalanceOf::key_for(*Ferdie)).to_vec() => vec![].and(&60u64), - twox_128(&staking::FreeBalanceOf::key_for(*One)).to_vec() => vec![].and(&1u64), - twox_128(staking::TotalStake::key()).to_vec() => vec![].and(&210u64), - twox_128(staking::SessionsPerEra::key()).to_vec() => vec![].and(&1u64), - twox_128(staking::ValidatorCount::key()).to_vec() => vec![].and(&3u64), - twox_128(staking::CurrentEra::key()).to_vec() => vec![].and(&1u64), - twox_128(staking::TransactionFee::key()).to_vec() => vec![].and(&1u64), - twox_128(staking::BondingDuration::key()).to_vec() => vec![].and(&0u64), - - twox_128(LaunchPeriod::key()).to_vec() => vec![].and(&1u64), - twox_128(VotingPeriod::key()).to_vec() => vec![].and(&1u64), - twox_128(MinimumDeposit::key()).to_vec() => vec![].and(&1u64) - ] - } -} - -#[cfg(test)] -mod tests { - use super::*; - use runtime_io::{with_externalities, twox_128, TestExternalities}; - use codec::{KeyedVec, Joiner}; - use keyring::Keyring::*; - use demo_primitives::AccountId; - use dispatch::PrivCall as Proposal; - use runtime::staking::PublicPass; - use super::public::Dispatch; - use super::privileged::Dispatch as PrivDispatch; - use runtime::{staking, session, democracy}; - - fn new_test_ext() -> TestExternalities { - testing::externalities() - } - - #[test] - fn params_should_work() { - with_externalities(&mut new_test_ext(), || { - assert_eq!(launch_period(), 1u64); - assert_eq!(voting_period(), 1u64); - assert_eq!(minimum_deposit(), 1u64); - assert_eq!(next_free_ref_index(), 0u32); - assert_eq!(staking::sessions_per_era(), 1u64); - assert_eq!(staking::total_stake(), 210u64); - }); - } - - // TODO: test VoteThreshold - - fn propose_sessions_per_era(who: &AccountId, value: u64, locked: Balance) { - PublicPass::test(who). - propose(Box::new(Proposal::Staking(staking::privileged::Call::set_sessions_per_era(value))), locked); - } - - #[test] - fn locked_for_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - propose_sessions_per_era(&Alice, 2, 2u64); - propose_sessions_per_era(&Alice, 4, 4u64); - propose_sessions_per_era(&Alice, 3, 3u64); - assert_eq!(locked_for(0), Some(2)); - assert_eq!(locked_for(1), Some(4)); - assert_eq!(locked_for(2), Some(3)); - }); - } - - #[test] - fn single_proposal_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - propose_sessions_per_era(&Alice, 2, 1u64); - democracy::internal::end_block(system::block_number()); - - system::testing::set_block_number(2); - let r = 0; - PublicPass::test(&Alice).vote(r, true); - - assert_eq!(next_free_ref_index(), 1); - assert_eq!(voters_for(r), vec![Alice.to_raw_public()]); - assert_eq!(vote_of((r, *Alice)), Some(true)); - assert_eq!(tally(r), (10, 0)); - - democracy::internal::end_block(system::block_number()); - staking::internal::check_new_era(); - - assert_eq!(staking::era_length(), 2u64); - }); - } - - #[test] - fn deposit_for_proposals_should_be_taken() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - propose_sessions_per_era(&Alice, 2, 5u64); - PublicPass::test(&Bob).second(0); - PublicPass::test(&Eve).second(0); - PublicPass::test(&Eve).second(0); - PublicPass::test(&Eve).second(0); - assert_eq!(staking::balance(&Alice), 5u64); - assert_eq!(staking::balance(&Bob), 15u64); - assert_eq!(staking::balance(&Eve), 35u64); - }); - } - - #[test] - fn deposit_for_proposals_should_be_returned() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - propose_sessions_per_era(&Alice, 2, 5u64); - PublicPass::test(&Bob).second(0); - PublicPass::test(&Eve).second(0); - PublicPass::test(&Eve).second(0); - PublicPass::test(&Eve).second(0); - democracy::internal::end_block(system::block_number()); - assert_eq!(staking::balance(&Alice), 10u64); - assert_eq!(staking::balance(&Bob), 20u64); - assert_eq!(staking::balance(&Eve), 50u64); - }); - } - - #[test] - #[should_panic] - fn proposal_with_deposit_below_minimum_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - propose_sessions_per_era(&Alice, 2, 0u64); - }); - } - - #[test] - #[should_panic] - fn poor_proposer_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - propose_sessions_per_era(&Alice, 2, 11u64); - }); - } - - #[test] - #[should_panic] - fn poor_seconder_should_panic() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - propose_sessions_per_era(&Bob, 2, 11u64); - PublicPass::test(&Alice).second(0); - }); - } - - fn propose_bonding_duration(who: &AccountId, value: u64, locked: Balance) { - PublicPass::test(who). - propose(Box::new(Proposal::Staking(staking::privileged::Call::set_bonding_duration(value))), locked); - } - - #[test] - fn runners_up_should_come_after() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(0); - propose_bonding_duration(&Alice, 2, 2u64); - propose_bonding_duration(&Alice, 4, 4u64); - propose_bonding_duration(&Alice, 3, 3u64); - democracy::internal::end_block(system::block_number()); - - system::testing::set_block_number(1); - PublicPass::test(&Alice).vote(0, true); - democracy::internal::end_block(system::block_number()); - staking::internal::check_new_era(); - assert_eq!(staking::bonding_duration(), 4u64); - - system::testing::set_block_number(2); - PublicPass::test(&Alice).vote(1, true); - democracy::internal::end_block(system::block_number()); - staking::internal::check_new_era(); - assert_eq!(staking::bonding_duration(), 3u64); - - system::testing::set_block_number(3); - PublicPass::test(&Alice).vote(2, true); - democracy::internal::end_block(system::block_number()); - staking::internal::check_new_era(); - assert_eq!(staking::bonding_duration(), 2u64); - }); - } - - fn sessions_per_era_propsal(value: u64) -> Proposal { - Proposal::Staking(staking::privileged::Call::set_sessions_per_era(value)) - } - - #[test] - fn simple_passing_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let r = inject_referendum(1, sessions_per_era_propsal(2), VoteThreshold::SuperMajorityApprove); - PublicPass::test(&Alice).vote(r, true); - - assert_eq!(voters_for(r), vec![Alice.to_raw_public()]); - assert_eq!(vote_of((r, *Alice)), Some(true)); - assert_eq!(tally(r), (10, 0)); - - democracy::internal::end_block(system::block_number()); - staking::internal::check_new_era(); - - assert_eq!(staking::era_length(), 2u64); - }); - } - - #[test] - fn cancel_referendum_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let r = inject_referendum(1, sessions_per_era_propsal(2), VoteThreshold::SuperMajorityApprove); - PublicPass::test(&Alice).vote(r, true); - PrivPass::test().cancel_referendum(r); - - democracy::internal::end_block(system::block_number()); - staking::internal::check_new_era(); - - assert_eq!(staking::era_length(), 1u64); - }); - } - - #[test] - fn simple_failing_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let r = inject_referendum(1, sessions_per_era_propsal(2), VoteThreshold::SuperMajorityApprove); - PublicPass::test(&Alice).vote(r, false); - - assert_eq!(voters_for(r), vec![Alice.to_raw_public()]); - assert_eq!(vote_of((r, *Alice)), Some(false)); - assert_eq!(tally(r), (0, 10)); - - democracy::internal::end_block(system::block_number()); - staking::internal::check_new_era(); - - assert_eq!(staking::era_length(), 1u64); - }); - } - - #[test] - fn controversial_voting_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let r = inject_referendum(1, sessions_per_era_propsal(2), VoteThreshold::SuperMajorityApprove); - PublicPass::test(&Alice).vote(r, true); - PublicPass::test(&Bob).vote(r, false); - PublicPass::test(&Charlie).vote(r, false); - PublicPass::test(&Dave).vote(r, true); - PublicPass::test(&Eve).vote(r, false); - PublicPass::test(&Ferdie).vote(r, true); - - assert_eq!(tally(r), (110, 100)); - - democracy::internal::end_block(system::block_number()); - staking::internal::check_new_era(); - - assert_eq!(staking::era_length(), 2u64); - }); - } - - #[test] - fn controversial_low_turnout_voting_should_work() { - with_externalities(&mut new_test_ext(), || { - system::testing::set_block_number(1); - let r = inject_referendum(1, sessions_per_era_propsal(2), VoteThreshold::SuperMajorityApprove); - PublicPass::test(&Eve).vote(r, false); - PublicPass::test(&Ferdie).vote(r, true); - - assert_eq!(tally(r), (60, 50)); - - democracy::internal::end_block(system::block_number()); - staking::internal::check_new_era(); - - assert_eq!(staking::era_length(), 1u64); - }); - } - - #[test] - fn passing_low_turnout_voting_should_work() { - with_externalities(&mut new_test_ext(), || { - assert_eq!(staking::era_length(), 1u64); - assert_eq!(staking::total_stake(), 210u64); - - system::testing::set_block_number(1); - let r = inject_referendum(1, sessions_per_era_propsal(2), VoteThreshold::SuperMajorityApprove); - PublicPass::test(&Dave).vote(r, true); - PublicPass::test(&Eve).vote(r, false); - PublicPass::test(&Ferdie).vote(r, true); - - assert_eq!(tally(r), (100, 50)); - - democracy::internal::end_block(system::block_number()); - staking::internal::check_new_era(); - - assert_eq!(staking::era_length(), 2u64); - }); - } -} diff --git a/substrate/demo/runtime/src/runtime/mod.rs b/substrate/demo/runtime/src/runtime/mod.rs deleted file mode 100644 index bba91af86d..0000000000 --- a/substrate/demo/runtime/src/runtime/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Demo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Demo. If not, see . - -//! The Substrate Demo runtime. - -#[allow(unused)] -pub mod system; -#[allow(unused)] -pub mod consensus; -#[allow(unused)] -pub mod staking; -#[allow(unused)] -pub mod timestamp; -#[allow(unused)] -pub mod session; -#[allow(unused)] -pub mod democracy; -#[allow(unused)] -pub mod council; -#[allow(unused)] -pub mod council_vote; diff --git a/substrate/demo/runtime/src/runtime/session.rs b/substrate/demo/runtime/src/runtime/session.rs deleted file mode 100644 index 430a095a20..0000000000 --- a/substrate/demo/runtime/src/runtime/session.rs +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Demo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Demo. If not, see . - -//! Session manager: is told the validators and allows them to manage their session keys for the -//! consensus module. - -use rstd::prelude::*; -use codec::KeyedVec; -use runtime_support::{storage, StorageValue, StorageMap}; -use demo_primitives::{AccountId, SessionKey, BlockNumber}; -use runtime::{system, staking, consensus}; -use runtime::democracy::PrivPass; -use runtime::staking::PublicPass; - -storage_items!{ - // The current set of validators. - pub Validators get(validators): b"ses:val" => required Vec; - // Current length of the session. - pub SessionLength get(length): b"ses:len" => required BlockNumber; - // Current index of the session. - pub CurrentIndex get(current_index): b"ses:ind" => required BlockNumber; - - // Block at which the session length last changed. - LastLengthChange: b"ses:llc" => default BlockNumber; - // The next key for a given validator. - NextKeyFor: b"ses:nxt:" => map [ AccountId => SessionKey ]; - // The next session length. - NextSessionLength: b"ses:nln" => BlockNumber; -} - -/// The number of validators currently. -pub fn validator_count() -> u32 { - Validators::get().len() as u32 // TODO: can probably optimised -} - -impl_dispatch! { - pub mod public; - fn set_key(key: SessionKey) = 0; -} - -impl<'a> public::Dispatch for PublicPass<'a> { - /// Sets the session key of `_validator` to `_key`. This doesn't take effect until the next - /// session. - fn set_key(self, key: SessionKey) { - // set new value for next session - NextKeyFor::insert(*self, key) - } -} - -impl_dispatch! { - pub mod privileged; - fn set_length(new: BlockNumber) = 0; - fn force_new_session() = 1; -} - -impl privileged::Dispatch for PrivPass { - /// Set a new era length. Won't kick in until the next era change (at current length). - fn set_length(self, new: BlockNumber) { - NextSessionLength::put(new); - } - - /// Forces a new session. - fn force_new_session(self) { - internal::rotate_session(); - } -} - -// INTERNAL API (available to other runtime modules) - -pub mod internal { - use super::*; - - /// Set the current set of validators. - /// - /// Called by `staking::next_era()` only. `next_session` should be called after this in order to - /// update the session keys to the next validator set. - pub fn set_validators(new: &[AccountId]) { - Validators::put(&new.to_vec()); // TODO: optimise. - consensus::internal::set_authorities(new); - } - - /// Hook to be called after transaction processing. - pub fn check_rotate_session() { - // do this last, after the staking system has had chance to switch out the authorities for the - // new set. - // check block number and call next_session if necessary. - if (system::block_number() - LastLengthChange::get()) % length() == 0 { - rotate_session(); - } - } - - /// Move onto next session: register the new authority set. - pub fn rotate_session() { - // Increment current session index. - CurrentIndex::put(CurrentIndex::get() + 1); - - // Enact era length change. - if let Some(next_len) = NextSessionLength::take() { - SessionLength::put(next_len); - LastLengthChange::put(system::block_number()); - } - - // Update any changes in session keys. - validators().iter().enumerate().for_each(|(i, v)| { - if let Some(n) = NextKeyFor::take(v) { - consensus::internal::set_authority(i as u32, &n); - } - }); - } -} - -#[cfg(any(feature = "std", test))] -pub mod testing { - use super::*; - use runtime_io::{twox_128, TestExternalities}; - use codec::{Joiner, KeyedVec}; - use keyring::Keyring::*; - use runtime::system; - - pub fn externalities(session_length: u64) -> TestExternalities { - let three = [3u8; 32]; - - let extras: TestExternalities = map![ - twox_128(SessionLength::key()).to_vec() => vec![].and(&session_length), - twox_128(CurrentIndex::key()).to_vec() => vec![].and(&0u64), - twox_128(Validators::key()).to_vec() => vec![].and(&vec![One.into(), Two.into(), three]) - ]; - system::testing::externalities().into_iter().chain(extras.into_iter()).collect() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use super::public::*; - use super::privileged::Dispatch as PrivDispatch; - use super::internal::*; - use runtime_io::{with_externalities, twox_128, TestExternalities}; - use codec::{KeyedVec, Joiner}; - use keyring::Keyring; - use demo_primitives::AccountId; - use runtime::{consensus, session}; - - fn simple_setup() -> TestExternalities { - map![ - twox_128(SessionLength::key()).to_vec() => vec![].and(&2u64), - twox_128(CurrentIndex::key()).to_vec() => vec![].and(&0u64), - // the validators (10, 20, ...) - twox_128(Validators::key()).to_vec() => vec![].and(&vec![[10u8; 32], [20; 32]]), - // initial session keys (11, 21, ...) - b":auth:len".to_vec() => vec![].and(&2u32), - 0u32.to_keyed_vec(b":auth:") => vec![11; 32], - 1u32.to_keyed_vec(b":auth:") => vec![21; 32] - ] - } - - #[test] - fn simple_setup_should_work() { - let mut t = simple_setup(); - with_externalities(&mut t, || { - assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); - assert_eq!(length(), 2u64); - assert_eq!(validators(), vec![[10u8; 32], [20u8; 32]]); - }); - } - - #[test] - fn session_length_change_should_work() { - let mut t = simple_setup(); - with_externalities(&mut t, || { - // Block 1: Change to length 3; no visible change. - system::testing::set_block_number(1); - PrivPass::test().set_length(3); - check_rotate_session(); - assert_eq!(length(), 2); - assert_eq!(current_index(), 0); - - // Block 2: Length now changed to 3. Index incremented. - system::testing::set_block_number(2); - PrivPass::test().set_length(3); - check_rotate_session(); - assert_eq!(length(), 3); - assert_eq!(current_index(), 1); - - // Block 3: Length now changed to 3. Index incremented. - system::testing::set_block_number(3); - check_rotate_session(); - assert_eq!(length(), 3); - assert_eq!(current_index(), 1); - - // Block 4: Change to length 2; no visible change. - system::testing::set_block_number(4); - PrivPass::test().set_length(2); - check_rotate_session(); - assert_eq!(length(), 3); - assert_eq!(current_index(), 1); - - // Block 5: Length now changed to 2. Index incremented. - system::testing::set_block_number(5); - check_rotate_session(); - assert_eq!(length(), 2); - assert_eq!(current_index(), 2); - - // Block 6: No change. - system::testing::set_block_number(6); - check_rotate_session(); - assert_eq!(length(), 2); - assert_eq!(current_index(), 2); - - // Block 7: Next index. - system::testing::set_block_number(7); - check_rotate_session(); - assert_eq!(length(), 2); - assert_eq!(current_index(), 3); - }); - } - - #[test] - fn session_change_should_work() { - let mut t = simple_setup(); - with_externalities(&mut t, || { - // Block 1: No change - system::testing::set_block_number(1); - check_rotate_session(); - assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); - - // Block 2: Session rollover, but no change. - system::testing::set_block_number(2); - check_rotate_session(); - assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); - - // Block 3: Set new key for validator 2; no visible change. - system::testing::set_block_number(3); - PublicPass::test(&[20; 32]).set_key([22; 32]); - assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); - - check_rotate_session(); - assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); - - // Block 4: Session rollover, authority 2 changes. - system::testing::set_block_number(4); - check_rotate_session(); - assert_eq!(consensus::authorities(), vec![[11u8; 32], [22u8; 32]]); - }); - } -} diff --git a/substrate/demo/runtime/src/runtime/staking.rs b/substrate/demo/runtime/src/runtime/staking.rs deleted file mode 100644 index d772aad898..0000000000 --- a/substrate/demo/runtime/src/runtime/staking.rs +++ /dev/null @@ -1,885 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Demo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Demo. If not, see . - -//! Staking manager: Handles balances and periodically determines the best set of validators. - -use rstd::prelude::*; -use rstd::{ops, cmp}; -use rstd::cell::RefCell; -use rstd::collections::btree_map::{BTreeMap, Entry}; -use runtime_io::{print, blake2_256}; -use codec::{Slicable, Input, KeyedVec}; -use runtime_support::{storage, StorageValue, StorageList, StorageMap}; -use demo_primitives::{BlockNumber, AccountId}; -use runtime::{system, session, democracy}; - -/// The balance of an account. -pub type Balance = u64; - -/// The amount of bonding period left in an account. Measured in eras. -pub type Bondage = u64; - -storage_items! { - // The length of the bonding duration in eras. - pub BondingDuration get(bonding_duration): b"sta:loc" => required BlockNumber; - // The length of a staking era in sessions. - pub ValidatorCount get(validator_count): b"sta:vac" => required u32; - // The length of a staking era in sessions. - pub SessionsPerEra get(sessions_per_era): b"sta:spe" => required BlockNumber; - // The total amount of stake on the system. - pub TotalStake get(total_stake): b"sta:tot" => required Balance; - // The fee to be paid for making a transaction. - pub TransactionFee get(transaction_fee): b"sta:fee" => required Balance; - - // The current era index. - pub CurrentEra get(current_era): b"sta:era" => required BlockNumber; - // All the accounts with a desire to stake. - pub Intention: b"sta:wil:" => list [ AccountId ]; - // The next value of sessions per era. - pub NextSessionsPerEra get(next_sessions_per_era): b"sta:nse" => BlockNumber; - // The block number at which the era length last changed. - pub LastEraLengthChange get(last_era_length_change): b"sta:lec" => default BlockNumber; - - // The balance of a given account. - pub FreeBalanceOf get(free_balance_of): b"sta:bal:" => default map [ AccountId => Balance ]; - - // The amount of the balance of a given account that is exterally reserved; this can still get - // slashed, but gets slashed last of all. - pub ReservedBalanceOf get(reserved_balance_of): b"sta:lbo:" => default map [ AccountId => Balance ]; - - // The block at which the `who`'s funds become entirely liquid. - pub BondageOf get(bondage_of): b"sta:bon:" => default map [ AccountId => Bondage ]; - - // The code associated with an account. - pub CodeOf: b"sta:cod:" => default map [ AccountId => Vec ]; // TODO Vec values should be optimised to not do a length prefix. - - // The storage items associated with an account/key. - pub StorageOf: b"sta:sto:" => map [ (AccountId, Vec) => Vec ]; // TODO: keys should also be able to take AsRef to ensure Vecs can be passed as &[u8] -} - -/// The length of a staking era in blocks. -pub fn era_length() -> BlockNumber { - SessionsPerEra::get() * session::length() -} - -/// The combined balance of `who`. -pub fn balance(who: &AccountId) -> Balance { - FreeBalanceOf::get(who) + ReservedBalanceOf::get(who) -} - -/// Some result as `slash(who, value)` (but without the side-effects) asuming there are no -/// balance changes in the meantime. -pub fn can_slash(who: &AccountId, value: Balance) -> bool { - balance(who) >= value -} - -#[derive(PartialEq, Copy, Clone)] -#[cfg_attr(test, derive(Debug))] -pub enum LockStatus { - Liquid, - LockedUntil(BlockNumber), - Staked, -} - -/// The block at which the `who`'s funds become entirely liquid. -pub fn unlock_block(who: &AccountId) -> LockStatus { - match BondageOf::get(who) { - i if i == Bondage::max_value() => LockStatus::Staked, - i if i <= system::block_number() => LockStatus::Liquid, - i => LockStatus::LockedUntil(i), - } -} - -pub struct PublicPass<'a> (&'a AccountId); - -const NOBODY: AccountId = [0u8; 32]; - -impl<'a> PublicPass<'a> { - pub fn new(transactor: &AccountId) -> PublicPass { - let b = FreeBalanceOf::get(transactor); - let transaction_fee = TransactionFee::get(); - assert!(b >= transaction_fee, "attempt to transact without enough funds to pay fee"); - FreeBalanceOf::insert(transactor, b - transaction_fee); - PublicPass(transactor) - } - - #[cfg(test)] - pub fn test(signed: &AccountId) -> PublicPass { - PublicPass(signed) - } - - #[cfg(test)] - pub fn nobody() -> PublicPass<'static> { - PublicPass(&NOBODY) - } - - /// Create a smart-contract account. - pub fn create(self, code: &[u8], value: Balance) { - // commit anything that made it this far to storage - if let Some(commit) = private::effect_create(self.0, code, value, private::DirectExt) { - private::commit_state(commit); - } - } -} - -impl<'a> ops::Deref for PublicPass<'a> { - type Target = AccountId; - fn deref(&self) -> &AccountId { - self.0 - } -} - -impl_dispatch! { - pub mod public; - fn transfer(dest: AccountId, value: Balance) = 0; - fn stake() = 1; - fn unstake() = 2; -} - -impl<'a> public::Dispatch for PublicPass<'a> { - /// Transfer some unlocked staking balance to another staker. - /// TODO: probably want to state gas-limit and gas-price. - fn transfer(self, dest: AccountId, value: Balance) { - // commit anything that made it this far to storage - if let Some(commit) = private::effect_transfer(&self, &dest, value, private::DirectExt) { - private::commit_state(commit); - } - } - - /// Declare the desire to stake for the transactor. - /// - /// Effects will be felt at the beginning of the next era. - fn stake(self) { - let mut intentions = Intention::items(); - // can't be in the list twice. - assert!(intentions.iter().find(|&t| *t == *self).is_none(), "Cannot stake if already staked."); - intentions.push(self.clone()); - Intention::set_items(&intentions); - BondageOf::insert(*self, u64::max_value()); - } - - /// Retract the desire to stake for the transactor. - /// - /// Effects will be felt at the beginning of the next era. - fn unstake(self) { - let mut intentions = Intention::items(); - if let Some(position) = intentions.iter().position(|&t| t == *self) { - intentions.swap_remove(position); - } else { - panic!("Cannot unstake if not already staked."); - } - Intention::set_items(&intentions); - BondageOf::insert(*self, CurrentEra::get() + BondingDuration::get()); - } -} - -impl_dispatch! { - pub mod privileged; - fn set_sessions_per_era(new: BlockNumber) = 0; - fn set_bonding_duration(new: BlockNumber) = 1; - fn set_validator_count(new: u32) = 2; - fn force_new_era() = 3; -} - -impl privileged::Dispatch for democracy::PrivPass { - /// Set the number of sessions in an era. - fn set_sessions_per_era(self, new: BlockNumber) { - NextSessionsPerEra::put(&new); - } - - /// The length of the bonding duration in eras. - fn set_bonding_duration(self, new: BlockNumber) { - BondingDuration::put(&new); - } - - /// The length of a staking era in sessions. - fn set_validator_count(self, new: u32) { - ValidatorCount::put(&new); - } - - /// Force there to be a new era. This also forces a new session immediately after. - fn force_new_era(self) { - new_era(); - session::internal::rotate_session(); - } -} - -// Each identity's stake may be in one of three bondage states, given by an integer: -// - n | n <= CurrentEra::get(): inactive: free to be transferred. -// - ~0: active: currently representing a validator. -// - n | n > CurrentEra::get(): deactivating: recently representing a validator and not yet -// ready for transfer. - -mod private { - use super::*; - - #[derive(Default)] - pub struct ChangeEntry { - balance: Option, - code: Option>, - storage: BTreeMap, Option>>, - } - - impl ChangeEntry { - pub fn balance_changed(b: Balance) -> Self { - ChangeEntry { balance: Some(b), code: None, storage: Default::default() } - } - } - - type State = BTreeMap; - - pub trait Externalities { - fn get_storage(&self, account: &AccountId, location: &[u8]) -> Option>; - fn get_code(&self, account: &AccountId) -> Vec; - fn get_balance(&self, account: &AccountId) -> Balance; - } - - struct Ext where - F1 : Fn(&AccountId, &[u8]) -> Option>, - F3 : Fn(&AccountId) -> Vec, - F5 : Fn(&AccountId) -> Balance - { - do_get_storage: F1, - do_get_code: F3, - do_get_balance: F5, - } - - pub struct DirectExt; - impl Externalities for DirectExt { - fn get_storage(&self, account: &AccountId, location: &[u8]) -> Option> { - StorageOf::get(&(*account, location.to_vec())) - } - fn get_code(&self, account: &AccountId) -> Vec { - CodeOf::get(account) - } - fn get_balance(&self, account: &AccountId) -> Balance { - FreeBalanceOf::get(account) - } - } - - impl Externalities for Ext where - F1 : Fn(&AccountId, &[u8]) -> Option>, - F3 : Fn(&AccountId) -> Vec, - F5 : Fn(&AccountId) -> Balance - { - fn get_storage(&self, account: &AccountId, location: &[u8]) -> Option> { - (self.do_get_storage)(account, location) - } - fn get_code(&self, account: &AccountId) -> Vec { - (self.do_get_code)(account) - } - fn get_balance(&self, account: &AccountId) -> Balance { - (self.do_get_balance)(account) - } - } - - pub fn commit_state(s: State) { - for (address, changed) in s.into_iter() { - if let Some(balance) = changed.balance { - FreeBalanceOf::insert(address, balance); - } - if let Some(code) = changed.code { - CodeOf::insert(&address, &code); - } - for (k, v) in changed.storage.into_iter() { - if let Some(value) = v { - StorageOf::insert(&(address, k), &value); - } else { - StorageOf::remove(&(address, k)); - } - } - } - } - - fn merge_state(commit_state: State, local: &mut State) { - for (address, changed) in commit_state.into_iter() { - match local.entry(address) { - Entry::Occupied(e) => { - let mut value = e.into_mut(); - if changed.balance.is_some() { - value.balance = changed.balance; - } - if changed.code.is_some() { - value.code = changed.code; - } - value.storage.extend(changed.storage.into_iter()); - } - Entry::Vacant(e) => { - e.insert(changed); - } - } - } - } - - pub fn effect_create( - transactor: &AccountId, - code: &[u8], - value: Balance, - ext: E - ) -> Option { - let from_balance = ext.get_balance(transactor); - // TODO: a fee. - assert!(from_balance >= value); - - let mut dest_pre = blake2_256(code).to_vec(); - dest_pre.extend(&transactor[..]); - let dest = blake2_256(&dest_pre); - - // early-out if degenerate. - if &dest == transactor { - return None; - } - - let mut local = BTreeMap::new(); - - // two inserts are safe - assert!(&dest != transactor); - local.insert(dest, ChangeEntry { balance: Some(value), code: Some(code.to_vec()), storage: Default::default() }); - local.insert(transactor.clone(), ChangeEntry::balance_changed(from_balance - value)); - - Some(local) - } - - pub fn effect_transfer( - transactor: &AccountId, - dest: &AccountId, - value: Balance, - ext: E - ) -> Option { - let from_balance = ext.get_balance(transactor); - assert!(from_balance >= value); - - let to_balance = ext.get_balance(dest); - assert!(BondageOf::get(transactor) <= BondageOf::get(dest)); - assert!(to_balance + value > to_balance); // no overflow - - // TODO: a fee, based upon gaslimit/gasprice. - // TODO: consider storing upper-bound for contract's gas limit in fixed-length runtime - // code in contract itself and use that. - - let local: RefCell = RefCell::new(BTreeMap::new()); - - if transactor != dest { - let mut local = local.borrow_mut(); - local.insert(transactor.clone(), ChangeEntry::balance_changed(from_balance - value)); - local.insert(dest.clone(), ChangeEntry::balance_changed(to_balance + value)); - } - - let should_commit = { - // Our local ext: Should be used for any transfers and creates that happen internally. - let ext = || Ext { - do_get_storage: |account: &AccountId, location: &[u8]| - local.borrow().get(account) - .and_then(|a| a.storage.get(location)) - .cloned() - .unwrap_or_else(|| ext.get_storage(account, location)), - do_get_code: |account: &AccountId| - local.borrow().get(account) - .and_then(|a| a.code.clone()) - .unwrap_or_else(|| ext.get_code(account)), - do_get_balance: |account: &AccountId| - local.borrow().get(account) - .and_then(|a| a.balance) - .unwrap_or_else(|| ext.get_balance(account)), - }; - let mut transfer = |inner_dest: &AccountId, value: Balance| { - if let Some(commit_state) = effect_transfer(dest, inner_dest, value, ext()) { - merge_state(commit_state, &mut *local.borrow_mut()); - } - }; - let mut create = |code: &[u8], value: Balance| { - if let Some(commit_state) = effect_create(dest, code, value, ext()) { - merge_state(commit_state, &mut *local.borrow_mut()); - } - }; - let mut put_storage = |location: Vec, value: Option>| { - local.borrow_mut() - .entry(dest.clone()) - .or_insert(Default::default()) - .storage.insert(location, value); - }; - - // TODO: logging (logs are just appended into a notable storage-based vector and cleared every - // block). - // TODO: execute code with ext(), put_storage, create and transfer as externalities. - true - }; - - if should_commit { - Some(local.into_inner()) - } else { - None - } - } -} - -pub mod internal { - use super::*; - - /// Hook to be called after to transaction processing. - pub fn check_new_era() { - // check block number and call new_era if necessary. - if (system::block_number() - LastEraLengthChange::get()) % era_length() == 0 { - new_era(); - } - } - - /// Deduct from an unbonded balance. true if it happened. - pub fn deduct_unbonded(who: &AccountId, value: Balance) -> bool { - if let LockStatus::Liquid = unlock_block(who) { - let b = FreeBalanceOf::get(who); - if b >= value { - FreeBalanceOf::insert(who, &(b - value)); - return true; - } - } - false - } - - /// Refund some balance. - pub fn refund(who: &AccountId, value: Balance) { - FreeBalanceOf::insert(who, &(FreeBalanceOf::get(who) + value)) - } - - /// Will slash any balance, but prefer free over reserved. - pub fn slash(who: &AccountId, value: Balance) -> bool { - let free_balance = FreeBalanceOf::get(who); - let free_slash = cmp::min(free_balance, value); - FreeBalanceOf::insert(who, &(free_balance - free_slash)); - if free_slash < value { - slash_reserved(who, value - free_slash) - } else { - true - } - } - - /// Moves `value` from balance to reserved balance. - pub fn reserve_balance(who: &AccountId, value: Balance) { - let b = FreeBalanceOf::get(who); - assert!(b >= value); - FreeBalanceOf::insert(who, &(b - value)); - ReservedBalanceOf::insert(who, &(ReservedBalanceOf::get(who) + value)); - } - - /// Moves `value` from reserved balance to balance. - pub fn unreserve_balance(who: &AccountId, value: Balance) { - let b = ReservedBalanceOf::get(who); - let value = cmp::min(b, value); - ReservedBalanceOf::insert(who, &(b - value)); - FreeBalanceOf::insert(who, &(FreeBalanceOf::get(who) + value)); - } - - /// Moves `value` from reserved balance to balance. - pub fn slash_reserved(who: &AccountId, value: Balance) -> bool { - let b = ReservedBalanceOf::get(who); - let slash = cmp::min(b, value); - ReservedBalanceOf::insert(who, &(b - slash)); - value == slash - } - - /// Moves `value` from reserved balance to balance. - pub fn transfer_reserved_balance(slashed: &AccountId, beneficiary: &AccountId, value: Balance) -> bool { - let b = ReservedBalanceOf::get(slashed); - let slash = cmp::min(b, value); - ReservedBalanceOf::insert(slashed, &(b - slash)); - FreeBalanceOf::insert(beneficiary, &(FreeBalanceOf::get(beneficiary) + slash)); - slash == value - } -} - -/// The era has changed - enact new staking set. -/// -/// NOTE: This always happens immediately before a session change to ensure that new validators -/// get a chance to set their session keys. -fn new_era() { - // Increment current era. - CurrentEra::put(&(CurrentEra::get() + 1)); - - // Enact era length change. - if let Some(next_spe) = NextSessionsPerEra::get() { - if next_spe != SessionsPerEra::get() { - SessionsPerEra::put(&next_spe); - LastEraLengthChange::put(&system::block_number()); - } - } - - // evaluate desired staking amounts and nominations and optimise to find the best - // combination of validators, then use session::internal::set_validators(). - // for now, this just orders would-be stakers by their balances and chooses the top-most - // ValidatorCount::get() of them. - let mut intentions = Intention::items() - .into_iter() - .map(|v| (balance(&v), v)) - .collect::>(); - intentions.sort_unstable_by(|&(b1, _), &(b2, _)| b2.cmp(&b1)); - session::internal::set_validators( - &intentions.into_iter() - .map(|(_, v)| v) - .take(ValidatorCount::get() as usize) - .collect::>() - ); -} - -#[cfg(any(feature = "std", test))] -pub mod testing { - use super::*; - use runtime_io::{twox_128, TestExternalities}; - use codec::{Joiner, KeyedVec}; - use keyring::Keyring::*; - use runtime::session; - use super::public::{Call, Dispatch}; - use super::privileged::{Dispatch as PrivDispatch, Call as PrivCall}; - - pub fn externalities(session_length: u64, sessions_per_era: u64, current_era: u64) -> TestExternalities { - let extras: TestExternalities = map![ - twox_128(&Intention::len_key()).to_vec() => vec![].and(&3u32), - twox_128(&Intention::key_for(0)).to_vec() => Alice.to_raw_public_vec(), - twox_128(&Intention::key_for(1)).to_vec() => Bob.to_raw_public_vec(), - twox_128(&Intention::key_for(2)).to_vec() => Charlie.to_raw_public_vec(), - twox_128(SessionsPerEra::key()).to_vec() => vec![].and(&sessions_per_era), - twox_128(ValidatorCount::key()).to_vec() => vec![].and(&3u64), - twox_128(BondingDuration::key()).to_vec() => vec![].and(&0u64), - twox_128(TransactionFee::key()).to_vec() => vec![].and(&1u64), - twox_128(CurrentEra::key()).to_vec() => vec![].and(¤t_era), - twox_128(&FreeBalanceOf::key_for(*Alice)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] - ]; - session::testing::externalities(session_length).into_iter().chain(extras.into_iter()).collect() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use super::internal::*; - use super::privileged::*; - - use runtime_io::{with_externalities, twox_128, TestExternalities}; - use codec::{KeyedVec, Joiner}; - use keyring::Keyring::*; - use demo_primitives::AccountId; - use runtime::{staking, session}; - use runtime::democracy::PrivPass; - use runtime::staking::public::{Call, Dispatch}; - use runtime::staking::privileged::{Call as PCall, Dispatch as PDispatch}; - - #[test] - fn staking_should_work() { - let mut t: TestExternalities = map![ - twox_128(session::SessionLength::key()).to_vec() => vec![].and(&1u64), - twox_128(session::Validators::key()).to_vec() => vec![].and(&vec![[10u8; 32], [20; 32]]), - twox_128(CurrentEra::key()).to_vec() => vec![].and(&0u64), - twox_128(SessionsPerEra::key()).to_vec() => vec![].and(&2u64), - twox_128(ValidatorCount::key()).to_vec() => vec![].and(&2u32), - twox_128(BondingDuration::key()).to_vec() => vec![].and(&3u64), - twox_128(TotalStake::key()).to_vec() => vec![].and(&100u64), - twox_128(TransactionFee::key()).to_vec() => vec![].and(&0u64), - twox_128(&FreeBalanceOf::key_for(*Alice)).to_vec() => vec![].and(&10u64), - twox_128(&FreeBalanceOf::key_for(*Bob)).to_vec() => vec![].and(&20u64), - twox_128(&FreeBalanceOf::key_for(*Charlie)).to_vec() => vec![].and(&30u64), - twox_128(&FreeBalanceOf::key_for(*Dave)).to_vec() => vec![].and(&40u64) - ]; - - with_externalities(&mut t, || { - assert_eq!(era_length(), 2u64); - assert_eq!(ValidatorCount::get(), 2); - assert_eq!(BondingDuration::get(), 3); - assert_eq!(session::validators(), vec![[10u8; 32], [20u8; 32]]); - - // Block 1: Add three validators. No obvious change. - system::testing::set_block_number(1); - public::Call::stake().dispatch(PublicPass::new(&Alice)); - PublicPass::new(&Bob).stake(); - PublicPass::new(&Dave).stake(); - check_new_era(); - assert_eq!(session::validators(), vec![[10u8; 32], [20u8; 32]]); - - // Block 2: New validator set now. - system::testing::set_block_number(2); - check_new_era(); - assert_eq!(session::validators(), vec![Dave.to_raw_public(), Bob.into()]); - - // Block 3: Unstake highest, introduce another staker. No change yet. - system::testing::set_block_number(3); - PublicPass::new(&Charlie).stake(); - PublicPass::new(&Dave).unstake(); - check_new_era(); - - // Block 4: New era - validators change. - system::testing::set_block_number(4); - check_new_era(); - assert_eq!(session::validators(), vec![Charlie.to_raw_public(), Bob.into()]); - - // Block 5: Transfer stake from highest to lowest. No change yet. - system::testing::set_block_number(5); - PublicPass::new(&Dave).transfer(Alice.to_raw_public(), 40); - check_new_era(); - - // Block 6: Lowest now validator. - system::testing::set_block_number(6); - check_new_era(); - assert_eq!(session::validators(), vec![Alice.to_raw_public(), Charlie.into()]); - - // Block 7: Unstake three. No change yet. - system::testing::set_block_number(7); - PublicPass::new(&Charlie).unstake(); - check_new_era(); - assert_eq!(session::validators(), vec![Alice.to_raw_public(), Charlie.into()]); - - // Block 8: Back to one and two. - system::testing::set_block_number(8); - check_new_era(); - assert_eq!(session::validators(), vec![Alice.to_raw_public(), Bob.into()]); - }); - } - - #[test] - fn staking_eras_work() { - let mut t: TestExternalities = map![ - twox_128(session::SessionLength::key()).to_vec() => vec![].and(&1u64), - twox_128(SessionsPerEra::key()).to_vec() => vec![].and(&2u64), - twox_128(ValidatorCount::key()).to_vec() => vec![].and(&2u32), - twox_128(CurrentEra::key()).to_vec() => vec![].and(&0u64) - ]; - with_externalities(&mut t, || { - assert_eq!(era_length(), 2u64); - assert_eq!(SessionsPerEra::get(), 2u64); - assert_eq!(LastEraLengthChange::get(), 0u64); - assert_eq!(CurrentEra::get(), 0u64); - - // Block 1: No change. - system::testing::set_block_number(1); - check_new_era(); - assert_eq!(SessionsPerEra::get(), 2u64); - assert_eq!(LastEraLengthChange::get(), 0u64); - assert_eq!(CurrentEra::get(), 0u64); - - // Block 2: Simple era change. - system::testing::set_block_number(2); - check_new_era(); - assert_eq!(SessionsPerEra::get(), 2u64); - assert_eq!(LastEraLengthChange::get(), 0u64); - assert_eq!(CurrentEra::get(), 1u64); - - // Block 3: Schedule an era length change; no visible changes. - system::testing::set_block_number(3); - PrivPass::test().set_sessions_per_era(3); - check_new_era(); - assert_eq!(SessionsPerEra::get(), 2u64); - assert_eq!(LastEraLengthChange::get(), 0u64); - assert_eq!(CurrentEra::get(), 1u64); - - // Block 4: Era change kicks in. - system::testing::set_block_number(4); - check_new_era(); - assert_eq!(SessionsPerEra::get(), 3u64); - assert_eq!(LastEraLengthChange::get(), 4u64); - assert_eq!(CurrentEra::get(), 2u64); - - // Block 5: No change. - system::testing::set_block_number(5); - check_new_era(); - assert_eq!(SessionsPerEra::get(), 3u64); - assert_eq!(LastEraLengthChange::get(), 4u64); - assert_eq!(CurrentEra::get(), 2u64); - - // Block 6: No change. - system::testing::set_block_number(6); - check_new_era(); - assert_eq!(SessionsPerEra::get(), 3u64); - assert_eq!(LastEraLengthChange::get(), 4u64); - assert_eq!(CurrentEra::get(), 2u64); - - // Block 7: Era increment. - system::testing::set_block_number(7); - check_new_era(); - assert_eq!(SessionsPerEra::get(), 3u64); - assert_eq!(LastEraLengthChange::get(), 4u64); - assert_eq!(CurrentEra::get(), 3u64); - }); - } - - #[test] - fn staking_balance_works() { - with_externalities(&mut testing::externalities(1, 3, 1), || { - FreeBalanceOf::insert(*Alice, 42); - assert_eq!(FreeBalanceOf::get(*Alice), 42); - assert_eq!(ReservedBalanceOf::get(*Alice), 0); - assert_eq!(balance(&Alice), 42); - assert_eq!(FreeBalanceOf::get(*Bob), 0); - assert_eq!(ReservedBalanceOf::get(*Bob), 0); - assert_eq!(balance(&Bob), 0); - }); - } - - #[test] - fn staking_balance_transfer_works() { - with_externalities(&mut testing::externalities(1, 3, 1), || { - FreeBalanceOf::insert(*Alice, 112); - PublicPass::new(&Alice).transfer(Bob.to_raw_public(), 69); - assert_eq!(balance(&Alice), 42); - assert_eq!(balance(&Bob), 69); - }); - } - - #[test] - #[should_panic] - fn staking_balance_transfer_when_bonded_panics() { - with_externalities(&mut testing::externalities(1, 3, 1), || { - FreeBalanceOf::insert(*Alice, 111); - PublicPass::new(&Alice).stake(); - PublicPass::new(&Alice).transfer(Bob.to_raw_public(), 69); - }); - } - - #[test] - fn reserving_balance_should_work() { - with_externalities(&mut testing::externalities(1, 3, 1), || { - FreeBalanceOf::insert(*Alice, 111); - - assert_eq!(balance(&Alice), 111); - assert_eq!(FreeBalanceOf::get(*Alice), 111); - assert_eq!(ReservedBalanceOf::get(*Alice), 0); - - reserve_balance(&Alice, 69); - - assert_eq!(balance(&Alice), 111); - assert_eq!(FreeBalanceOf::get(*Alice), 42); - assert_eq!(ReservedBalanceOf::get(*Alice), 69); - }); - } - - #[test] - #[should_panic] - fn staking_balance_transfer_when_reserved_panics() { - with_externalities(&mut testing::externalities(1, 3, 1), || { - FreeBalanceOf::insert(*Alice, 111); - reserve_balance(&Alice, 69); - PublicPass::new(&Alice).transfer(Bob.to_raw_public(), 69); - }); - } - - #[test] - fn deducting_balance_should_work() { - with_externalities(&mut testing::externalities(1, 3, 1), || { - FreeBalanceOf::insert(*Alice, 111); - assert!(deduct_unbonded(&Alice, 69)); - assert_eq!(FreeBalanceOf::get(*Alice), 42); - }); - } - - #[test] - fn deducting_balance_should_fail_when_bonded() { - let mut t: TestExternalities = map![ - twox_128(&FreeBalanceOf::key_for(*Alice)).to_vec() => vec![].and(&111u64), - twox_128(&BondageOf::key_for(*Alice)).to_vec() => vec![].and(&2u64) - ]; - with_externalities(&mut t, || { - system::testing::set_block_number(1); - assert_eq!(unlock_block(&Alice), LockStatus::LockedUntil(2)); - assert!(!deduct_unbonded(&Alice, 69)); - }); - } - - #[test] - fn refunding_balance_should_work() { - with_externalities(&mut testing::externalities(1, 3, 1), || { - FreeBalanceOf::insert(*Alice, 42); - refund(&Alice, 69); - assert_eq!(FreeBalanceOf::get(*Alice), 111); - }); - } - - #[test] - fn slashing_balance_should_work() { - with_externalities(&mut testing::externalities(1, 3, 1), || { - FreeBalanceOf::insert(*Alice, 111); - reserve_balance(&Alice, 69); - assert!(slash(&Alice, 69)); - assert_eq!(FreeBalanceOf::get(*Alice), 0); - assert_eq!(ReservedBalanceOf::get(*Alice), 42); - }); - } - - #[test] - fn slashing_incomplete_balance_should_work() { - with_externalities(&mut testing::externalities(1, 3, 1), || { - FreeBalanceOf::insert(*Alice, 42); - reserve_balance(&Alice, 21); - assert!(!slash(&Alice, 69)); - assert_eq!(FreeBalanceOf::get(*Alice), 0); - assert_eq!(ReservedBalanceOf::get(*Alice), 0); - }); - } - - #[test] - fn unreserving_balance_should_work() { - with_externalities(&mut testing::externalities(1, 3, 1), || { - FreeBalanceOf::insert(*Alice, 111); - reserve_balance(&Alice, 111); - unreserve_balance(&Alice, 42); - assert_eq!(ReservedBalanceOf::get(*Alice), 69); - assert_eq!(FreeBalanceOf::get(*Alice), 42); - }); - } - - #[test] - fn slashing_reserved_balance_should_work() { - with_externalities(&mut testing::externalities(1, 3, 1), || { - FreeBalanceOf::insert(*Alice, 111); - reserve_balance(&Alice, 111); - assert!(slash_reserved(&Alice, 42)); - assert_eq!(ReservedBalanceOf::get(*Alice), 69); - assert_eq!(FreeBalanceOf::get(*Alice), 0); - }); - } - - #[test] - fn slashing_incomplete_reserved_balance_should_work() { - with_externalities(&mut testing::externalities(1, 3, 1), || { - FreeBalanceOf::insert(*Alice, 111); - reserve_balance(&Alice, 42); - assert!(!slash_reserved(&Alice, 69)); - assert_eq!(FreeBalanceOf::get(*Alice), 69); - assert_eq!(ReservedBalanceOf::get(*Alice), 0); - }); - } - - #[test] - fn transferring_reserved_balance_should_work() { - with_externalities(&mut testing::externalities(1, 3, 1), || { - FreeBalanceOf::insert(*Alice, 111); - reserve_balance(&Alice, 111); - assert!(transfer_reserved_balance(&Alice, &Bob, 42)); - assert_eq!(ReservedBalanceOf::get(*Alice), 69); - assert_eq!(FreeBalanceOf::get(*Alice), 0); - assert_eq!(ReservedBalanceOf::get(*Bob), 0); - assert_eq!(FreeBalanceOf::get(*Bob), 42); - }); - } - - #[test] - fn transferring_incomplete_reserved_balance_should_work() { - with_externalities(&mut testing::externalities(1, 3, 1), || { - FreeBalanceOf::insert(*Alice, 111); - reserve_balance(&Alice, 42); - assert!(!transfer_reserved_balance(&Alice, &Bob, 69)); - assert_eq!(ReservedBalanceOf::get(*Alice), 0); - assert_eq!(FreeBalanceOf::get(*Alice), 69); - assert_eq!(ReservedBalanceOf::get(*Bob), 0); - assert_eq!(FreeBalanceOf::get(*Bob), 42); - }); - } -} diff --git a/substrate/demo/runtime/src/runtime/system.rs b/substrate/demo/runtime/src/runtime/system.rs deleted file mode 100644 index 8cd75b49ed..0000000000 --- a/substrate/demo/runtime/src/runtime/system.rs +++ /dev/null @@ -1,352 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Demo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Demo. If not, see . - -//! System manager: Handles all of the top-level stuff; executing block/transaction, setting code -//! and depositing logs. - -use rstd::prelude::*; -use rstd::mem; -use runtime_io::{print, storage_root, enumerated_trie_root}; -use codec::{KeyedVec, Slicable}; -use runtime_support::{Hashable, storage, StorageValue, StorageMap}; -use demo_primitives::{AccountId, Hash, TxOrder, BlockNumber, Header, Log}; -use block::{self, Block}; -use transaction::UncheckedTransaction; -use runtime::{staking, session}; -use runtime::democracy::PrivPass; -use dispatch; -use safe_mix::TripletMix; - -storage_items! { - pub Nonce get(nonce): b"sys:non" => default map [ AccountId => TxOrder ]; - pub BlockHashAt get(block_hash): b"sys:old" => required map [ BlockNumber => Hash ]; - RandomSeed get(random_seed): b"sys:rnd" => required Hash; - // The current block number being processed. Set by `execute_block`. - Number get(block_number): b"sys:num" => required BlockNumber; - ParentHash get(parent_hash): b"sys:pha" => required Hash; - TransactionsRoot get(transactions_root): b"sys:txr" => required Hash; - Digest: b"sys:dig" => default block::Digest; -} - -pub const CODE: &'static[u8] = b":code"; - -impl_dispatch! { - pub mod privileged; - fn set_code(new: Vec) = 0; -} - -impl privileged::Dispatch for PrivPass { - /// Set the new code. - fn set_code(self, new: Vec) { - storage::unhashed::put_raw(CODE, &new); - } -} - -pub mod internal { - use super::*; - - struct CheckedTransaction(UncheckedTransaction); - - /// Deposits a log and ensures it matches the blocks log data. - pub fn deposit_log(log: Log) { - let mut l = Digest::get(); - l.logs.push(log); - Digest::put(l); - } - - /// Actually execute all transitioning for `block`. - pub fn execute_block(mut block: Block) { - initialise_block(&block.header); - - // any initial checks - initial_checks(&block); - - // execute transactions - block.transactions.iter().cloned().for_each(super::execute_transaction); - - // post-transactional book-keeping. - staking::internal::check_new_era(); - session::internal::check_rotate_session(); - - // any final checks - final_checks(&block); - - // any stuff that we do after taking the storage root. - post_finalise(&block.header); - } - - /// Start the execution of a particular block. - pub fn initialise_block(mut header: &Header) { - // populate environment from header. - Number::put(header.number); - ParentHash::put(header.parent_hash); - TransactionsRoot::put(header.transaction_root); - RandomSeed::put(calculate_random()); - } - - /// Execute a transaction outside of the block execution function. - /// This doesn't attempt to validate anything regarding the block. - pub fn execute_transaction(utx: UncheckedTransaction) { - super::execute_transaction(utx); - } - - /// Finalise the block - it is up the caller to ensure that all header fields are valid - /// except state-root. - pub fn finalise_block() -> Header { - staking::internal::check_new_era(); - session::internal::check_rotate_session(); - - RandomSeed::kill(); - let header = Header { - number: Number::take(), - digest: Digest::take(), - parent_hash: ParentHash::take(), - transaction_root: TransactionsRoot::take(), - state_root: storage_root().into(), - }; - - post_finalise(&header); - - header - } -} - -fn execute_transaction(utx: UncheckedTransaction) { - use ::transaction; - - // Verify the signature is good. - let tx = match transaction::check(utx) { - Ok(tx) => tx, - Err(_) => panic!("All transactions should be properly signed"), - }; - - { - // check nonce - let expected_nonce: TxOrder = Nonce::get(&tx.signed); - assert!(tx.nonce == expected_nonce, "All transactions should have the correct nonce"); - - // increment nonce in storage - Nonce::insert(&tx.signed, &(expected_nonce + 1)); - } - - // decode parameters and dispatch - let tx = tx.drain().transaction; - tx.function.dispatch(staking::PublicPass::new(&tx.signed)); -} - -fn initial_checks(block: &Block) { - let ref header = block.header; - - // check parent_hash is correct. - assert!( - header.number > 0 && BlockHashAt::get(&(header.number - 1)) == header.parent_hash, - "Parent hash should be valid." - ); - - // check transaction trie root represents the transactions. - let txs = block.transactions.iter().map(Slicable::encode).collect::>(); - let txs = txs.iter().map(Vec::as_slice).collect::>(); - let txs_root = enumerated_trie_root(&txs).into(); - info_expect_equal_hash(&header.transaction_root, &txs_root); - assert!(header.transaction_root == txs_root, "Transaction trie root must be valid."); -} - -fn final_checks(block: &Block) { - let ref header = block.header; - - // check digest - assert!(header.digest == Digest::get()); - - // remove temporaries. - kill_temps(); - - // check storage root. - let storage_root = storage_root().into(); - info_expect_equal_hash(&header.state_root, &storage_root); - assert!(header.state_root == storage_root, "Storage root must match that calculated."); -} - -fn kill_temps() { - Number::kill(); - ParentHash::kill(); - RandomSeed::kill(); - Digest::kill(); - TransactionsRoot::kill(); -} - -fn post_finalise(header: &Header) { - // store the header hash in storage; we can't do it before otherwise there would be a - // cyclic dependency. - BlockHashAt::insert(&header.number, &header.blake2_256().into()); -} - -fn calculate_random() -> Hash { - let c = block_number() - 1; - (0..81) - .map(|i| if c >= i { block_hash(c - i) } else { Default::default() }) - .triplet_mix() -} - -#[cfg(feature = "std")] -fn info_expect_equal_hash(given: &Hash, expected: &Hash) { - use primitives::hexdisplay::HexDisplay; - if given != expected { - println!("Hash: given={}, expected={}", HexDisplay::from(&given.0), HexDisplay::from(&expected.0)); - } -} - -#[cfg(not(feature = "std"))] -fn info_expect_equal_hash(given: &Hash, expected: &Hash) { - if given != expected { - print("Hash not equal"); - print(&given.0[..]); - print(&expected.0[..]); - } -} - -#[cfg(any(feature = "std", test))] -pub mod testing { - use super::*; - use runtime_io::{twox_128, TestExternalities}; - use codec::Joiner; - - pub fn externalities() -> TestExternalities { - map![ - twox_128(&BlockHashAt::key_for(&0)).to_vec() => [69u8; 32].encode(), - twox_128(Number::key()).to_vec() => 1u64.encode(), - twox_128(ParentHash::key()).to_vec() => [69u8; 32].encode(), - twox_128(RandomSeed::key()).to_vec() => [0u8; 32].encode() - ] - } - - pub fn set_block_number(n: BlockNumber) { - Number::put(n); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use super::internal::*; - - use runtime_io::{with_externalities, twox_128, TestExternalities}; - use runtime_support::StorageValue; - use codec::{Joiner, KeyedVec, Slicable}; - use keyring::Keyring::*; - use primitives::hexdisplay::HexDisplay; - use demo_primitives::{Header, Digest}; - use transaction::{UncheckedTransaction, Transaction}; - use runtime::staking; - use dispatch::public::Call as PubCall; - use runtime::staking::public::Call as StakingCall; - - #[test] - fn staking_balance_transfer_dispatch_works() { - let mut t: TestExternalities = map![ - twox_128(&staking::FreeBalanceOf::key_for(*One)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(staking::TransactionFee::key()).to_vec() => vec![10u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(&BlockHashAt::key_for(&0)).to_vec() => [69u8; 32].encode() - ]; - - let tx = UncheckedTransaction { - transaction: Transaction { - signed: One.into(), - nonce: 0, - function: PubCall::Staking(StakingCall::transfer(Two.into(), 69)), - }, - signature: hex!("3a682213cb10e8e375fe0817fe4d220a4622d910088809ed7fc8b4ea3871531dbadb22acfedd28a100a0b7bd2d274e0ff873655b13c88f4640b5569db3222706").into(), - }; - - with_externalities(&mut t, || { - internal::initialise_block(&Header::from_block_number(1)); - internal::execute_transaction(tx); - assert_eq!(staking::balance(&One), 32); - assert_eq!(staking::balance(&Two), 69); - }); - } - - fn new_test_ext() -> TestExternalities { - staking::testing::externalities(2, 2, 0) - } - - #[test] - fn block_import_works() { - let mut t = new_test_ext(); - - let h = Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: hex!("cc3f1f5db826013193e502c76992b5e933b12367e37a269a9822b89218323e9f").into(), - transaction_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), - digest: Digest { logs: vec![], }, - }; - - let b = Block { - header: h, - transactions: vec![], - }; - - with_externalities(&mut t, || { - execute_block(b); - }); - } - - #[test] - #[should_panic] - fn block_import_of_bad_state_root_fails() { - let mut t = new_test_ext(); - - let h = Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: [0u8; 32].into(), - transaction_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), - digest: Digest { logs: vec![], }, - }; - - let b = Block { - header: h, - transactions: vec![], - }; - - with_externalities(&mut t, || { - execute_block(b); - }); - } - - #[test] - #[should_panic] - fn block_import_of_bad_transaction_root_fails() { - let mut t = new_test_ext(); - - let h = Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: hex!("1ab2dbb7d4868a670b181327b0b6a58dc64b10cfb9876f737a5aa014b8da31e0").into(), - transaction_root: [0u8; 32].into(), - digest: Digest { logs: vec![], }, - }; - - let b = Block { - header: h, - transactions: vec![], - }; - - with_externalities(&mut t, || { - execute_block(b); - }); - } -} diff --git a/substrate/demo/runtime/src/runtime/timestamp.rs b/substrate/demo/runtime/src/runtime/timestamp.rs deleted file mode 100644 index ed51ebabc7..0000000000 --- a/substrate/demo/runtime/src/runtime/timestamp.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Demo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Demo. If not, see . - -//! Timestamp manager: just handles the current timestamp. - -use runtime_support::storage::StorageValue; -use runtime::staking::PublicPass; - -pub type Timestamp = u64; - -storage_items! { - pub Now: b"tim:val" => required Timestamp; -} - -impl_dispatch! { - pub mod public; - fn set(now: Timestamp) = 0; -} - -impl<'a> public::Dispatch for PublicPass<'a> { - /// Set the current time. - fn set(self, now: Timestamp) { - Now::put(&now); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use super::public::*; - - use runtime_io::{with_externalities, twox_128, TestExternalities}; - use runtime_support::storage::StorageValue; - use runtime::timestamp; - use codec::{Joiner, KeyedVec}; - use demo_primitives::AccountId; - use runtime::staking::PublicPass; - - #[test] - fn timestamp_works() { - let mut t: TestExternalities = map![ - twox_128(Now::key()).to_vec() => vec![].and(&42u64) - ]; - - with_externalities(&mut t, || { - assert_eq!(Now::get(), 42); - PublicPass::nobody().set(69); - assert_eq!(Now::get(), 69); - }); - } -} diff --git a/substrate/demo/runtime/src/transaction.rs b/substrate/demo/runtime/src/transaction.rs deleted file mode 100644 index de769b5a16..0000000000 --- a/substrate/demo/runtime/src/transaction.rs +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Demo is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Demo. If not, see . - -//! Transaction type. - -use rstd::prelude::*; -use rstd::ops; -use codec::{Input, Slicable}; -use demo_primitives::{AccountId, TxOrder, Signature}; -use dispatch::PubCall; - -#[cfg(feature = "std")] -use std::fmt; - -/// A vetted and verified transaction from the external world. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub struct Transaction { - /// Who signed it (note this is not a signature). - pub signed: AccountId, - /// The number of transactions have come before from the same signer. - pub nonce: TxOrder, - /// The function that should be called. - pub function: PubCall, -} - -impl Slicable for Transaction { - fn decode(input: &mut I) -> Option { - Some(Transaction { - signed: Slicable::decode(input)?, - nonce: Slicable::decode(input)?, - function: Slicable::decode(input)?, - }) - } - - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - self.signed.using_encoded(|s| v.extend(s)); - self.nonce.using_encoded(|s| v.extend(s)); - self.function.using_encoded(|s| v.extend(s)); - - v - } -} - -impl ::codec::NonTrivialSlicable for Transaction {} - -/// A transactions right from the external world. Unchecked. -#[derive(Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct UncheckedTransaction { - /// The actual transaction information. - pub transaction: Transaction, - /// The signature; should be an Ed25519 signature applied to the serialised `transaction` field. - pub signature: Signature, -} - -impl Slicable for UncheckedTransaction { - fn decode(input: &mut I) -> Option { - // This is a little more complicated than usual since the binary format must be compatible - // with substrate's generic `Vec` type. Basically this just means accepting that there - // will be a prefix of u32, which has the total number of bytes following (we don't need - // to use this). - let _length_do_not_remove_me_see_above: u32 = Slicable::decode(input)?; - - Some(UncheckedTransaction { - transaction: Slicable::decode(input)?, - signature: Slicable::decode(input)?, - }) - } - - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - // need to prefix with the total length as u32 to ensure it's binary comptible with - // Vec. we'll make room for it here, then overwrite once we know the length. - v.extend(&[0u8; 4]); - - self.transaction.signed.using_encoded(|s| v.extend(s)); - self.transaction.nonce.using_encoded(|s| v.extend(s)); - self.transaction.function.using_encoded(|s| v.extend(s)); - self.signature.using_encoded(|s| v.extend(s)); - - let length = (v.len() - 4) as u32; - length.using_encoded(|s| v[0..4].copy_from_slice(s)); - - v - } -} - -impl ::codec::NonTrivialSlicable for UncheckedTransaction {} - -impl PartialEq for UncheckedTransaction { - fn eq(&self, other: &Self) -> bool { - self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction - } -} - -#[cfg(feature = "std")] -impl fmt::Debug for UncheckedTransaction { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "UncheckedTransaction({:?})", self.transaction) - } -} - -/// A type-safe indicator that a transaction has been checked. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug))] -pub struct CheckedTransaction(UncheckedTransaction); - -impl CheckedTransaction { - /// Get a reference to the checked signature. - pub fn signature(&self) -> &Signature { - &self.0.signature - } - - /// Get the inner object. - pub fn drain(self) -> UncheckedTransaction { - self.0 - } -} - -impl ops::Deref for CheckedTransaction { - type Target = Transaction; - - fn deref(&self) -> &Transaction { - &self.0.transaction - } -} - -/// Check the signature on a transaction. -/// -/// On failure, return the transaction back. -pub fn check(tx: UncheckedTransaction) -> Result { - let msg = ::codec::Slicable::encode(&tx.transaction); - if ::runtime_io::ed25519_verify(&tx.signature.0, &msg, &tx.transaction.signed) { - Ok(CheckedTransaction(tx)) - } else { - Err(tx) - } -} - - -#[cfg(test)] -mod tests { - use super::*; - use primitives; - use codec::Slicable; - use primitives::hexdisplay::HexDisplay; - use dispatch::public::Call; - use runtime::timestamp::public::Call as TimestampCall; - - #[test] - fn serialize_unchecked() { - let tx = UncheckedTransaction { - transaction: Transaction { - signed: [1; 32], - nonce: 999u64, - function: Call::Timestamp(TimestampCall::set(135135)), - }, - signature: primitives::hash::H512([0; 64]), - }; - // 71000000 - // 0101010101010101010101010101010101010101010101010101010101010101 - // e703000000000000 - // 00 - // df0f0200 - // 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - - let v = Slicable::encode(&tx); - println!("{}", HexDisplay::from(&v)); - assert_eq!(UncheckedTransaction::decode(&mut &v[..]).unwrap(), tx); - } -} diff --git a/substrate/demo/runtime/wasm/Cargo.lock b/substrate/demo/runtime/wasm/Cargo.lock index a415dd58eb..bc627b63e0 100644 --- a/substrate/demo/runtime/wasm/Cargo.lock +++ b/substrate/demo/runtime/wasm/Cargo.lock @@ -96,6 +96,7 @@ dependencies = [ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-primitives 0.1.0", "substrate-runtime-std 0.1.0", ] @@ -105,11 +106,21 @@ version = "0.1.0" dependencies = [ "demo-primitives 0.1.0", "integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)", + "safe-mix 0.1.0", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-council 0.1.0", + "substrate-runtime-democracy 0.1.0", + "substrate-runtime-executive 0.1.0", "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-staking 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", + "substrate-runtime-timestamp 0.1.0", ] [[package]] @@ -249,6 +260,11 @@ name = "integer-sqrt" version = "0.1.0" source = "git+https://github.com/paritytech/integer-sqrt-rs.git#f4cf61482096dc98c1273f46a10849d182b4c23c" +[[package]] +name = "integer-sqrt" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "isatty" version = "0.1.6" @@ -337,6 +353,11 @@ name = "nodrop" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num-traits" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "num_cpus" version = "1.8.0" @@ -546,6 +567,13 @@ dependencies = [ "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "safe-mix" +version = "0.1.0" +dependencies = [ + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "scopeguard" version = "0.3.3" @@ -605,6 +633,15 @@ dependencies = [ "substrate-runtime-std 0.1.0", ] +[[package]] +name = "substrate-keyring" +version = "0.1.0" +dependencies = [ + "ed25519 0.1.0", + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-primitives" version = "0.1.0" @@ -622,6 +659,74 @@ dependencies = [ "uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)", ] +[[package]] +name = "substrate-runtime-consensus" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", +] + +[[package]] +name = "substrate-runtime-council" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "integer-sqrt 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-democracy 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-staking 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + +[[package]] +name = "substrate-runtime-democracy" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-staking 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + +[[package]] +name = "substrate-runtime-executive" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + [[package]] name = "substrate-runtime-io" version = "0.1.0" @@ -636,6 +741,58 @@ dependencies = [ "triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "substrate-runtime-primitives" +version = "0.1.0" +dependencies = [ + "integer-sqrt 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", +] + +[[package]] +name = "substrate-runtime-session" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + +[[package]] +name = "substrate-runtime-staking" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", +] + [[package]] name = "substrate-runtime-std" version = "0.1.0" @@ -650,14 +807,42 @@ name = "substrate-runtime-support" version = "0.1.0" dependencies = [ "ed25519 0.1.0", - "environmental 0.1.0", "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-std 0.1.0", ] +[[package]] +name = "substrate-runtime-system" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 0.1.0", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", +] + +[[package]] +name = "substrate-runtime-timestamp" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", +] + [[package]] name = "substrate-state-machine" version = "0.1.0" @@ -837,6 +1022,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd546ef520ab3745f1aae5f2cdc6de9e6498e94d1ab138b9eb3ddfbf335847fb" "checksum hex-literal-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ea76da4c7f1a54d01d54985566d3fdd960b2bbd7b970da024821c883c2d9631" "checksum integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)" = "" +"checksum integer-sqrt 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7536fe7f78abedb82f609d87f46f0e0ca0ad31e84597deb8dabd8ed9ad047257" "checksum isatty 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f2a233726c7bb76995cec749d59582e5664823b7245d4970354408f1d79a7a2" "checksum keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f300c1f149cd9ca5214eed24f6e713a597517420fb8b15499824aa916259ec1" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" @@ -848,6 +1034,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum memorydb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "013b7e4c5e10c764936ebc6bd3662d8e3c92292d267bf6a42ef3f5cad9c793ee" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" +"checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" diff --git a/substrate/demo/runtime/wasm/Cargo.toml b/substrate/demo/runtime/wasm/Cargo.toml index 266b5e2d81..32af7412f4 100644 --- a/substrate/demo/runtime/wasm/Cargo.toml +++ b/substrate/demo/runtime/wasm/Cargo.toml @@ -7,22 +7,42 @@ authors = ["Parity Technologies "] crate-type = ["cdylib"] [dependencies] +integer-sqrt = { git = "https://github.com/paritytech/integer-sqrt-rs.git", branch = "master" } +safe-mix = { path = "../../../safe-mix", default-features = false } substrate-codec = { path = "../../../substrate/codec", default-features = false } +substrate-primitives = { path = "../../../substrate/primitives", default-features = false } substrate-runtime-std = { path = "../../../substrate/runtime-std", default-features = false } substrate-runtime-io = { path = "../../../substrate/runtime-io", default-features = false } substrate-runtime-support = { path = "../../../substrate/runtime-support", default-features = false } -substrate-primitives = { path = "../../../substrate/primitives", default-features = false } +substrate-runtime-consensus = { path = "../../../substrate/runtime/consensus", default-features = false } +substrate-runtime-council = { path = "../../../substrate/runtime/council", default-features = false } +substrate-runtime-democracy = { path = "../../../substrate/runtime/democracy", default-features = false } +substrate-runtime-executive = { path = "../../../substrate/runtime/executive", default-features = false } +substrate-runtime-primitives = { path = "../../../substrate/runtime/primitives", default-features = false } +substrate-runtime-session = { path = "../../../substrate/runtime/session", default-features = false } +substrate-runtime-staking = { path = "../../../substrate/runtime/staking", default-features = false } +substrate-runtime-system = { path = "../../../substrate/runtime/system", default-features = false } +substrate-runtime-timestamp = { path = "../../../substrate/runtime/timestamp", default-features = false } demo-primitives = { path = "../../primitives", default-features = false } -integer-sqrt = { git = "https://github.com/paritytech/integer-sqrt-rs.git", branch = "master" } [features] default = [] std = [ + "safe-mix/std", "substrate-codec/std", - "substrate-runtime-io/std", - "substrate-runtime-std/std", - "substrate-runtime-support/std", "substrate-primitives/std", + "substrate-runtime-std/std", + "substrate-runtime-io/std", + "substrate-runtime-support/std", + "substrate-runtime-consensus/std", + "substrate-runtime-council/std", + "substrate-runtime-democracy/std", + "substrate-runtime-executive/std", + "substrate-runtime-primitives/std", + "substrate-runtime-session/std", + "substrate-runtime-staking/std", + "substrate-runtime-system/std", + "substrate-runtime-timestamp/std", "demo-primitives/std", ] diff --git a/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm b/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm index 5cae06b23b4b116d128c34f74799f667a2edcea2..e380c8c8f16566cb541db8f57b732f27f7cc33f6 100644 GIT binary patch literal 236029 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 literal 136003 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 Hn5fLZIWoE1 diff --git a/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm b/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm old mode 100755 new mode 100644 index d1c274e15e41401c9b6f412489689b713888b9ae..528b6f61ec2d123d4d29bc7951f86463bfd25cdf GIT binary patch literal 236080 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

~%R6tGK0 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
k=)9j~H?F5*1)>sRDpaVy*B~&t?Q-Cm7vl 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 literal 145910 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%0A_W9bRRA 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 diff --git a/substrate/polkadot/cli/Cargo.toml b/substrate/polkadot/cli/Cargo.toml index 8fa34c3a02..c7c10f9e5d 100644 --- a/substrate/polkadot/cli/Cargo.toml +++ b/substrate/polkadot/cli/Cargo.toml @@ -12,7 +12,7 @@ log = "0.3" hex-literal = "0.1" triehash = "0.1" ed25519 = { path = "../../substrate/ed25519" } -app_dirs = "1.2" +app_dirs = "1.2.1" substrate-client = { path = "../../substrate/client" } substrate-codec = { path = "../../substrate/codec" } substrate-runtime-io = { path = "../../substrate/runtime-io" } diff --git a/substrate/polkadot/consensus/Cargo.toml b/substrate/polkadot/consensus/Cargo.toml index df49b2a1cf..103ae1a913 100644 --- a/substrate/polkadot/consensus/Cargo.toml +++ b/substrate/polkadot/consensus/Cargo.toml @@ -18,8 +18,8 @@ polkadot-transaction-pool = { path = "../transaction-pool" } substrate-bft = { path = "../../substrate/bft" } substrate-codec = { path = "../../substrate/codec" } substrate-primitives = { path = "../../substrate/primitives" } +substrate-runtime-support = { path = "../../substrate/runtime-support" } substrate-network = { path = "../../substrate/network" } - tokio-core = "0.1.12" substrate-keyring = { path = "../../substrate/keyring" } substrate-client = { path = "../../substrate/client" } diff --git a/substrate/polkadot/consensus/src/lib.rs b/substrate/polkadot/consensus/src/lib.rs index 8ee93bafa8..ba1e05b05e 100644 --- a/substrate/polkadot/consensus/src/lib.rs +++ b/substrate/polkadot/consensus/src/lib.rs @@ -41,6 +41,7 @@ extern crate polkadot_transaction_pool as transaction_pool; extern crate substrate_bft as bft; extern crate substrate_codec as codec; extern crate substrate_primitives as primitives; +extern crate substrate_runtime_support as runtime_support; extern crate substrate_network; extern crate tokio_core; @@ -58,6 +59,7 @@ use std::sync::Arc; use codec::Slicable; use table::{Table, Context as TableContextTrait}; use table::generic::Statement as GenericStatement; +use runtime_support::Hashable; use polkadot_api::{PolkadotApi, BlockBuilder}; use polkadot_primitives::{Hash, Timestamp}; use polkadot_primitives::block::Block as PolkadotBlock; @@ -480,7 +482,7 @@ impl bft::ProposerFactory for ProposerFactory type Error = Error; fn init(&self, parent_header: &SubstrateHeader, authorities: &[AuthorityId], sign_with: Arc) -> Result { - let parent_hash = parent_header.hash(); + let parent_hash = parent_header.blake2_256().into(); let checked_id = self.client.check_id(BlockId::Hash(parent_hash))?; let duty_roster = self.client.duty_roster(&checked_id)?; diff --git a/substrate/polkadot/consensus/src/service.rs b/substrate/polkadot/consensus/src/service.rs index 6ef1aa8389..db8c4ee7a5 100644 --- a/substrate/polkadot/consensus/src/service.rs +++ b/substrate/polkadot/consensus/src/service.rs @@ -26,6 +26,7 @@ use parking_lot::Mutex; use substrate_network as net; use tokio_core::reactor; use client::BlockchainEvents; +use runtime_support::Hashable; use primitives::{Hash, AuthorityId}; use primitives::block::{Id as BlockId, HeaderHash, Header}; use polkadot_primitives::parachain::{BlockData, Extrinsic, CandidateReceipt}; @@ -154,7 +155,7 @@ impl Service { }; let bft_service = BftService::new(client.clone(), key, factory); let build_bft = |header: &Header| -> Result<_, Error> { - let hash = header.hash(); + let hash = header.blake2_256().into(); let authorities = client.authorities(&BlockId::Hash(hash))?; let input = network.bft_messages() .filter_map(move |message| { diff --git a/substrate/polkadot/primitives/src/block.rs b/substrate/polkadot/primitives/src/block.rs index b2d90a19c0..e74dd19f4c 100644 --- a/substrate/polkadot/primitives/src/block.rs +++ b/substrate/polkadot/primitives/src/block.rs @@ -49,7 +49,7 @@ impl Slicable for Log { } } -impl ::codec::NonTrivialSlicable for Log { } + /// The digest of a block, useful for light-clients. #[derive(Clone, Default, PartialEq, Eq)] diff --git a/substrate/polkadot/primitives/src/parachain.rs b/substrate/polkadot/primitives/src/parachain.rs index 34a8b34733..e94ba03d28 100644 --- a/substrate/polkadot/primitives/src/parachain.rs +++ b/substrate/polkadot/primitives/src/parachain.rs @@ -19,7 +19,7 @@ #[cfg(feature = "std")] use primitives::bytes; use primitives; -use codec::{Input, Slicable, NonTrivialSlicable}; +use codec::{Input, Slicable}; use rstd::cmp::{PartialOrd, Ord, Ordering}; use rstd::vec::Vec; use ::Hash; @@ -59,7 +59,7 @@ pub enum Chain { impl Slicable for Chain { fn decode(input: &mut I) -> Option { - let disc = try_opt!(u8::decode(input)); + let disc = input.read_byte()?; match disc { 0 => Some(Chain::Relay), @@ -71,9 +71,9 @@ impl Slicable for Chain { fn encode(&self) -> Vec { let mut v = Vec::new(); match *self { - Chain::Relay => { 0u8.using_encoded(|s| v.extend(s)); } + Chain::Relay => { v.push(0); } Chain::Parachain(id) => { - 1u8.using_encoded(|s| v.extend(s)); + v.push(1u8); id.using_encoded(|s| v.extend(s)); } } @@ -86,7 +86,7 @@ impl Slicable for Chain { } } -impl NonTrivialSlicable for Chain { } + /// The duty roster specifying what jobs each validator must do. #[derive(Clone, PartialEq)] @@ -317,7 +317,7 @@ impl Slicable for Statement { } fn decode(value: &mut I) -> Option { - match u8::decode(value) { + match value.read_byte() { Some(x) if x == StatementKind::Candidate as u8 => { Slicable::decode(value).map(Statement::Candidate) } diff --git a/substrate/polkadot/primitives/src/transaction.rs b/substrate/polkadot/primitives/src/transaction.rs index f13cf223a9..f3637034b4 100644 --- a/substrate/polkadot/primitives/src/transaction.rs +++ b/substrate/polkadot/primitives/src/transaction.rs @@ -94,7 +94,7 @@ pub enum Proposal { impl Slicable for Proposal { fn decode(input: &mut I) -> Option { - let id = try_opt!(u8::decode(input).and_then(InternalFunctionId::from_u8)); + let id = InternalFunctionId::from_u8(input.read_byte()?)?; let function = match id { InternalFunctionId::SystemSetCode => Proposal::SystemSetCode(try_opt!(Slicable::decode(input))), @@ -119,33 +119,33 @@ impl Slicable for Proposal { let mut v = Vec::new(); match *self { Proposal::SystemSetCode(ref data) => { - (InternalFunctionId::SystemSetCode as u8).using_encoded(|s| v.extend(s)); + v.push(InternalFunctionId::SystemSetCode as u8); data.using_encoded(|s| v.extend(s)); } Proposal::SessionSetLength(ref data) => { - (InternalFunctionId::SessionSetLength as u8).using_encoded(|s| v.extend(s)); + v.push(InternalFunctionId::SessionSetLength as u8); data.using_encoded(|s| v.extend(s)); } Proposal::SessionForceNewSession => { - (InternalFunctionId::SessionForceNewSession as u8).using_encoded(|s| v.extend(s)); + v.push(InternalFunctionId::SessionForceNewSession as u8); } Proposal::StakingSetSessionsPerEra(ref data) => { - (InternalFunctionId::StakingSetSessionsPerEra as u8).using_encoded(|s| v.extend(s)); + v.push(InternalFunctionId::StakingSetSessionsPerEra as u8); data.using_encoded(|s| v.extend(s)); } Proposal::StakingSetBondingDuration(ref data) => { - (InternalFunctionId::StakingSetBondingDuration as u8).using_encoded(|s| v.extend(s)); + v.push(InternalFunctionId::StakingSetBondingDuration as u8); data.using_encoded(|s| v.extend(s)); } Proposal::StakingSetValidatorCount(ref data) => { - (InternalFunctionId::StakingSetValidatorCount as u8).using_encoded(|s| v.extend(s)); + v.push(InternalFunctionId::StakingSetValidatorCount as u8); data.using_encoded(|s| v.extend(s)); } Proposal::StakingForceNewEra => { - (InternalFunctionId::StakingForceNewEra as u8).using_encoded(|s| v.extend(s)); + v.push(InternalFunctionId::StakingForceNewEra as u8); } Proposal::GovernanceSetApprovalPpmRequired(ref data) => { - (InternalFunctionId::GovernanceSetApprovalPpmRequired as u8).using_encoded(|s| v.extend(s)); + v.push(InternalFunctionId::GovernanceSetApprovalPpmRequired as u8); data.using_encoded(|s| v.extend(s)); } } @@ -267,7 +267,7 @@ impl Function { impl Slicable for Function { fn decode(input: &mut I) -> Option { - let id = try_opt!(u8::decode(input).and_then(FunctionId::from_u8)); + let id = FunctionId::from_u8(input.read_byte()?)?; Some(match id { FunctionId::TimestampSet => Function::Inherent(InherentFunction::TimestampSet(try_opt!(Slicable::decode(input)))), @@ -293,34 +293,34 @@ impl Slicable for Function { let mut v = Vec::new(); match *self { Function::Inherent(InherentFunction::TimestampSet(ref data)) => { - (FunctionId::TimestampSet as u8).using_encoded(|s| v.extend(s)); + v.push(FunctionId::TimestampSet as u8); data.using_encoded(|s| v.extend(s)); } Function::SessionSetKey(ref data) => { - (FunctionId::SessionSetKey as u8).using_encoded(|s| v.extend(s)); + v.push(FunctionId::SessionSetKey as u8); data.using_encoded(|s| v.extend(s)); } Function::StakingStake => { - (FunctionId::StakingStake as u8).using_encoded(|s| v.extend(s)); + v.push(FunctionId::StakingStake as u8); } Function::StakingUnstake => { - (FunctionId::StakingUnstake as u8).using_encoded(|s| v.extend(s)); + v.push(FunctionId::StakingUnstake as u8); } Function::ReportMisbehavior(ref report) => { - (FunctionId::StakingReportMisbehavior as u8).using_encoded(|s| v.extend(s)); + v.push(FunctionId::StakingReportMisbehavior as u8); report.using_encoded(|s| v.extend(s)); } Function::StakingTransfer(ref to, ref amount) => { - (FunctionId::StakingTransfer as u8).using_encoded(|s| v.extend(s)); + v.push(FunctionId::StakingTransfer as u8); to.using_encoded(|s| v.extend(s)); amount.using_encoded(|s| v.extend(s)); } Function::GovernancePropose(ref data) => { - (FunctionId::GovernancePropose as u8).using_encoded(|s| v.extend(s)); + v.push(FunctionId::GovernancePropose as u8); data.using_encoded(|s| v.extend(s)); } Function::GovernanceApprove(ref data) => { - (FunctionId::GovernanceApprove as u8).using_encoded(|s| v.extend(s)); + v.push(FunctionId::GovernanceApprove as u8); data.using_encoded(|s| v.extend(s)); } } @@ -365,7 +365,7 @@ impl Slicable for Transaction { } } -impl ::codec::NonTrivialSlicable for Transaction {} + /// A transactions right from the external world. Unchecked. #[derive(Eq, Clone)] @@ -441,7 +441,7 @@ impl Slicable for UncheckedTransaction { } } -impl ::codec::NonTrivialSlicable for UncheckedTransaction {} + impl PartialEq for UncheckedTransaction { fn eq(&self, other: &Self) -> bool { diff --git a/substrate/polkadot/runtime/wasm/Cargo.lock b/substrate/polkadot/runtime/wasm/Cargo.lock index d2bf5b3e78..7c2e7ef05b 100644 --- a/substrate/polkadot/runtime/wasm/Cargo.lock +++ b/substrate/polkadot/runtime/wasm/Cargo.lock @@ -654,8 +654,9 @@ name = "substrate-runtime-support" version = "0.1.0" dependencies = [ "ed25519 0.1.0", - "environmental 0.1.0", "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", diff --git a/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm b/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm index a752fb6e219718c47f9bb6a40b636ddc8f7fb235..14e9b61cdb68d9492e000caea44b782b5387d502 100644 GIT binary patch literal 134951 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 v{#l#jluSxu99nit&>|%9 zf=>{nZ0xvD<2 zbmWGf%29v+?^|o1eJ(CQh>SeSR0M&u*V=op$M^oe^{us&2cCQ+O_C)2vC-k|#EIl^ zenS7IC(;vk$xlkTK`lQ`{pgmJb?=!(uW^;wlj$>ulZ5MMs13KC$^Kb3%8xwybnnQg zkKg~u0}ns^*vFGh6&+Q4;@FWRNkhefipPKIu}|NB!;QBjsj3!L^~od0?|<_6W5*u& zY+y;Os;MPq+Zi7WG*wud65>y{eKC(HMj~{#B(I+4H`0qp|5ui_Ph6Fh#nDN&Cn?ghv$~umgvVt=+6`zzF+x~AE@$a#0tC=0IDdc%e?X|GNiMY=ah_A`_Q zPue7^@<`>;YE@oRc`25e$KsfViY9Frxlb>#(u9`UR4wc%nnkC`nIQ8h8k$9Wl=f++ zSY;}$^6=`UHB9>bf*J44ll`=mXdG(Oz`%ohlKFm;^v|Ygc7j#_rQpn@(xXLo_s}3j zeOhFzldMSZq?5c%k58!JPkQIhNm?d%3{ydp=M0t!EiibXdHXOe8sluxWK;k&J2*@S zjc^T|c!EFaT{}k$V74)$Jj^wm^8C(n(`W}5U%zp*HL)3J#2Q|aa@FtmDA7PRYWM#_ z82fV8VO;b+m}G|-s7+P_O^*VL^6(R@Ojs{#qRW{=s14c%Mkun{(`(U|QwCI7qbO^@BZIBBDT19?T;7EBO;-7~=S8NDEFai~N zfm1^Rggo?;L4^v21^wxP0OSgy-To)C^hEv);MjL`lEQw;-fT3^^wR-R{1|@AMR?E0 z(b%6a6)8L^K$PDah-FeEXuqHD&kHKD{rR%h7ptRpB>k^9vw`<>Hm$+EQ)J?94UjpG zV0JJ&&IQ#X6`4~O88(lvibuqUORM8%nTT^Kzmx!?^4r&xozZqLLiM}?_;~Z4G3}S9 zQe)okN@5-9=Tr(i@rdq?pziW~qGyV(ct@iV7oB2Yhcyz$;!ljquilCXN=A8k;&ukt z3{7fSqt#lW6AP*vF~W3p+|r2dg)6dt7}V10q#a+Q&fzdUhh z*eLqt?ho;km9H@a8ibVM9IT2q2SsnD3PCo!aHfv~kA8TrR}8{cw;0BE1(L@Nbl%5g zPLT4(C-b`YRwt6S49G-gF)bhk?WtyAF9r~+mB)cMKQnNGb^1j|GLFeff+vtR6D*n< zj}>UpdO@r8xQgBtkqipR2Ef?nbaGGjP2sYUj=mwMX z1&>NB>{>0QUbxy*T>*@1sW^S3*#WvQJK#%u&9LCAgHBnNbSRg(D)?o>XKwtS3%D;| z@dE+(0|5t{eXj)EpER;LSI?*4ih4#JGsH3Gw-^IWjndQAXmyMYH11S7yHkE~ci9?k zkLnd&J?Xm5+be%{M#;8ZC03e}=GLj#j?^nGT~n`Xs8eafs9sf;Dy)~K2SZsuYiZFf zdW=`kx{mF+j_pMqD=UFkdzGRLig|T1S7}VIqV4%v)ww2XqUcw;cu>qqo|)R54_BrW z58F_@57(vM_+*nF_EskgbscMkc47BhLE}o9t)+VZF!G9@QBebvY1i%s+O?&TAXX*G z-IB1v#mKHx=~b|P8G7|}(5t6+xnBK`7jgZv1E>HTEm?rlGz=THQV zEchUmKbIfJGHe9P(8vT!+>LE>Aw_Iv;+LtcH`&)H4k%L&3rdxq%Jf$23*{z9@Mq|2 zR5^pZFuGF8ink^m-gYO@C~qWJv~2^GKi3|lC`z9Kdag{oS*B2L7F9~;1~?h|G;Zdu z^vtBAPFky)zTA(F9>B>1227%DfN>8H$fNYjPvehlO&pdPcJ9#P_N$qB?VNCV?e ztrhc%-n0{VwiBGdGuL0l3H-xmo?(KSMh}sKOvnZL=0W&?;=hjO6JV%p-Br1^`CL08 z7?ZZzGGiR+yziD^g>8|+Ncd7D0)8;ZgKMEjm`Sa1tTtH#JY`4&QSi;6UA2pMu|c~N zYZvztoMojGlr&YU0z!>?iwj15a*(hhnb->fFHlfx#Zq1J|m#B zxIs~CH!U~OE}oZl&O=Dr4Ia8m4+X}Rk-gyv_t^-)I}~0Jm)V#r|K~Jqo-nclmSZem z_k?GqVJ0DCGOw8((4T@>3-ZzAQIXwgVvJx>*}02Ig3Ne~@Uj7GVzrM`=7&T{pkmRv z{k>B`8G;Hp4lUCRLN_LRCgfqxdqlyEW$y>Bvrtm`S~sxmbNj@$|9T;B!lQXDnwMRi zM{VrsbxBfg#HWp{Im4%D<_*Zj_*9HkL{h96$>KkdpfM7FK!>GeH%8rHag{es%NCW} zUX>NkOU2UNiekGP4naf%^btidRA~`KbQjOli$q2kR1*PgBAkXy72rNu=&*b_jU9*Z z;rUvHjr7%8g$?z!sv;{3IVw?HDXzgQEhN^2`G=4tqfopGtc#1$RZ{czAfu{3$Pnuf zDzaI=UiB4*x0X%EYr{KPtFYmnswx!w1j`nS;n^lUSdFWT>1IN-{6%ayb@d+-S&eCV zgUm=FXxzgtvoVjmMd#qKRdmY*)LOw zYri>dUt{I@BKDW!iBevkmiMW=Z(6=ZE@{|6F51|4!*5alZ>+HsLlt1al)`8e9DsnoPBEPV6DRKfkQA2L5mCc0M zNaP7BHP(gZ0<%^^&#d~I(6fMAT2?|20JzWt5Kt7RkLC|`GPxi~H0z3zQSmmfH&W`R zGL1I$`e?V&nG6YC7;^?&0y9E2*wQlWOjNBmBNzu}L{Rr&NUdCGM%>^60>)YRGIPz-lKX}zX)%^c*h$aMJViX4@!h0HrLz%}?~VOS zXH))0GOe%y{#I47QRB8u7lxpf*uBZUwaNc}^=_E`E42!1{g0~(sb+Z%*z{v8A1wT? zD65Nbw25H|DfAGdCySZ;4(7n)O?0rf@^bL-xTp6a;KCw#eT&%17EVAJL0Y%Czh^^Ndtil@)N20+Xr4QQ81?ml$SbmzQERzjr3$PyGPzYwx zoF!X|eht3J_au%J*M?lqJhM81fVA zFJV1}S!2W-(Xxb&Dctn%fRZ#OM)NqH=7zLHo%Udxc~=j@hM_r{F{9M@EtxuS#&5~g zfs>64JStnJ$=bC$aIBhbGy#j^HCg)61Q5=efSIWwF(OWYkRsy>LYzV%fSKWg<7EI% zh_|3GO1F4vU&JNewU6(nDY^`QmHZ0mtK=Jt_$*Nc+!`wP)lhj8cip&=rw=zt#Nqkq z6692)ok}^zi|*>Ubm2;Zt~RZyptA=NbV*&d!B5GIY_q{nWm|y$H!E?Zk%T_fpvO#G zK$v!>VlBM(t?IRa)u~tuXrBr`7IQ@#=GP^_RHP;vOC~*;)jfz_6jk(Y&JF;uDDQq) z*%&#UyOb0@5O#fp-2kYCb&Da=&I&~faW|A8u~ZIVtYm^Y;}hph`eQlNf&*F(&CBz) z^r2J_V>PJ$(u z1VNfLh34h#04-RR&^@OXNnat0L=CWBptu5=8Ay~`wopqVuSLoLBCl`D;mg?%k6TL9 z*@!_Rhv(n-9R3CqXnfyK0Ch8q0alqJ_?s7w-q$TQ60mIvSQEqKja33xflt;&MC|Ga z&g`N^FAx{)Vo-m1AJJU+Y2X@;$Y4_Rj1rf#n@l)jA~;RcQ$f3CGE9uT=dc)@n%g34 z=U0f)S|LM0X;3FUdIR&02a$mZyj+Zdr_7g>YyRqY$Hk^eHsoS6TK4Jghq@oB&8q`p0?#Kry7Q1OI$`N+-eXSY{?)bCfyjfqg0b2 z$F(dMt?@uprVl1f4I+wqsdhwtGe4l$;17Dzed&J@B8otf$EKuWQ!8lJ&|-WnG!uFX zL>qeubogC&!Qh@X683?5Ga5{;q%D$F+6O(r?p{^tKVL}G2AP}j4~^JlCd894rj@Fh zdE%jEWhyYjIwv_qimQ^DDItK`k{*QRGA#sTDx;-%l0R9$2T_%1n7{R3v0!h(r|h%iStX-Nqn8k1>?zmwgaxYu})T zk(=#i1cguWgm^PA-{FL-H4c~@*k(_2@782ql-H3q<)L|ouxMBEGI6yun5D?>8~^mD=U}#AC zf0CDyP}(e!`iLd4g-Ho)NY8_Ld0-mCskbHrF%4j1T+|!GP+!4$$iT_3nKH~k3{ySt zh^fCY7hi}Z<}K9NWl+K{LX2LEh(XuadY!jYjc}`B#8&4-xE63>!0R$e`cQuxYHwu=&w3 zZUTe_F`FTSi}5@LO5L^r7hYw?4H~Q5(6~v8)}!3Rv?-ExJ@Uqd#tqNUjLV3qZrtdB z%DBPCbK?e6!i}4}{~P^u7`R6Y9*P)Am0$diQw~aA*@O)Yv>y7&6KL28fb2}zHY3(k zrLuIeXUY>#nzkZyQv5gWBJZTr#y#~@G_FMh5`eyg7W?IQ(kI4bjPf9MCV^ABkoMxa zUeOXK_n>3gkr-B^WY<<>++*5^k3rFrK4f#q6XRhqu!fAkdDWVwkMp*}3%}|RgA+rj zAzU)`)Em!Zi5A1Mb-WlHn;k=@lm56gw)$gS6sCyx2Rk1=wWW8DChgF|W7qI;Au1Inp^c7?=1$)KbC zaN=-)4=$pZM$|GK*)L$ZA+AQ|7O5Z)dOk2DTay{Lgb|1%b%_Z+d-AbX<1A!~Flz&2 z!|{=^n!r@s6Pcqm|jHDNW@AuTz@S=c6?Cfb;yd&4omkV@jD;ldZ|Li5n73{jU zB#4jz+?X0>Ia6nI@9o1}&H?ksK=LXaL6Ln@WZKOfYY88z*8FYx!nf3YYYOZN4UV?E z;FgFZb5wUi0mu8jy!wS3%)eIc9*SQXMn8KAUzg=F`MQ{y+>-Nqhh5#m6{}uq@5?vH z2QSlcDi-8PO&=G}G^MO~WbuTtXusAP+NUL7DY)XAx_k&1wh5XNgsCFPMmV}DO-Z7l znh}C4(XQ@D)*5%|lAx6^V(Pl~Z`o|N0|P+$4A8$1(UZFi21BN}{ylBZUKHzq||pE@Eu8>fQ9NYtK}jGJcJSUffv z!TKw>EKt;hej4gVvERU#lUxjVX{|3|&7LqrO?kPj(y9zW-rB6v7h za5$J;7S@XY-jBwk!3xy$#^e1P?qDJjSPOnSS3D+Vtu9Hbxu>$&5|a0M8c9Lqme&GCoppO)xJr@4G8GMOBBV11r<&UBk4P zy(3TEhW*4iD}Qe@Lq%ZP;AoKn#UZuJrQ_w&Q|x`w=1>};x1vo-kJvCce%G*r#os`rV&+G<{=wE+xM~U)hwC3OR^!AA;Ho<_aQ%~QZw{`?NMU&0 z@?Y-wF5rscxgM_na)*rw+@ckTK4Oz%l6A|!p00!Osc+xDTAuoLAL#+0|M2IJua@C!?)6*0`HNilI2}Pvl#pTtzV=SKU$D+^`~F`fy4=6f)=`>1c^CdID?{7 z^t8viY(F6`U?0O>Ln(`Nu9>tN%^VWyt$c_7{>tIcVc+ECpCQf>5M&Nm(k}zZ;ptGP zSRoReItAM8F$?2WP1xAaY3%jaOt;QHQ}`qQZ)`ae9Iw<^S*}L1PP6p$Yk{Xj45wDC+j8+l? z^kq_{7GUGK7tv#u(U4(Q#O5Ufh%-UVyCL9X{T6pN+3!-%o=fFF+F8y;diE$`|M|2!QYPJlOq%{NetnCia@kNPCgFe;<&E(Yy8y7jfNRM53!baW)p5^+3HB5vV24qk7 z`~Sy$TiaGMHrFdwJ5Ye}rG{lePl@D>t|V*hpe96)sXElnnw`W57ELzIF6NC)n`UYJ zw@C%iQYB`m5|gs>x2$5gdVP}Ima5{MRV-Ies4v!ZzlIFw&F<=Qf+T+ta^9OPO*$)` zlSJ&e9&s2Bs(YLko#!zIwDPbZi?4HQBH{N^!$_H{S2OLxr>U?j&E~91))dK~@ch@R zl4az)44da1IwY-HrDyf4PTij;dGl3d?sT+R0-k21aL4x5cPEJkT3)ewBUf5H-o1JQ zS42{-OO|8;>`nGz$^*}ldE%#Xb&Wsu>xr`RvXTm}Rr#kVq4S~k#WUK;(;=Qhtiz%INdYt`whtmZ1i4mQ5hJsc#D_Xa%k5p#=fLdc0kL z+3yOGgAEV~CXhCuV%(Zq0lH;wVac4zA zHC%$3HrhDf3cBaGlai+C3XvH({^6aR5;3h%BEE$|$HNu~rbomu=nC%=V3ne8A<;NJ z2i9I8;A%m&s_`}fGRfyuel&~gH)mf&dMgRxl%zOR{hWS}eOLd6f)2vi}3xm8@c%sypQ5>VP{DM5|)i60%ck3*7md@k{Jk2^wdhH*pPfd67WD zX>kqJU&B^A#Z~z#H11&dWzXO*N#Df}oNT807l2MS?Fb7;9Vx2us`VK=lI^2uZV7j4 z)6^ZnvNhacZ(z(YDXg(=+;Cp0-=HmJ1nEYtE#9ChogJnd)252-`s5e#+tLSpZm%-s z1Ah4;mxXk#4QpB!X{Q}Z+^fBiFhm)t2U9K#g?jskS(@Wr8N`@?;+0B%1KJws(a8(u~e0i zX2tfZB$Z?*ciDSVNAdI%_B2q6C!i!HG^rjE@8NYyxl|m+NVSJGDPObdeK9>g5$*6? zwNHx)T17E^;$^F-_K~86tpZZ;tzC%-fHq*9SV6bQ4lh*-D4Z?zPf~L6eBCwKBUpTu z_^wWAdY?>-&Ny`o1GfnDiNbUDH4^<4P!bPthr{PYJ3JsM<&$RPf&e^1M5eL~{E1Qd zcdKJ@+{HG3$le}#FDzVfG94)37zh#Ou^B6C%6rycS#8`IF(CMoWQEOQyw1O zd1fbDm>9dLL4nT^5qO`3`)#Fap}ekJUP@t-HGP= zzm{js6Ah&=DvXiC1v_wk@{CF@${|1`srxq=I! zB{dvF3bU>Ap7&dbUA5$F3-CH)O6Y-JP)JzEYJn^0#mA;Q=rA9euA)4(cbJ6s1Mm)4 z@d(H`U?5XX0%Iby$O>_6TNC4qD7NW{KG{AeXb>gTbywHqwCcL2YXAWlCVe3V^Bhyg zuTX(qze4HxMx&yygQsjujo7dV7*(FOBUR!nUUkA%^>`(qe$#!yc$yzBHWMQ4b@!+g z-DsiQ$cN^Q37n7v*aK5)KI;hCL<|$En9}fSEITUy#~IXyM*N<&Q+9+tN!yMPC$@&N zvneNAa=BApLGDmBnLkQBlvac-f9MR$5D|T0O#!Zzj*gr%v;tqGp^RkxW9J=bf%LV! ztDu+G<-j>~!2=SIhIO#1E9?u@j0sfJFWiQMsD$p=MP))0TBAZOq?PIet1fJXUx~fQ zZ{Uk^r8PrPs#2?xT*5T=^F@&MdhuT((tagt_yM3Z+0V)70QBYp$*B?0k~Aa;caYqf zgaJWG3=^R!9v7?HW!Q-4xML!X0Hi=3_z@KC&6jn~u7yu!x#LE5Ot8`PzycTuHc^|d zQ^p~$&TwU1VdG!`Zi*-oIA7_leWpH|z#cZnW%1Mc(M0yR=xEfujU|)hrC5J47z+`3Z^f%W2>Nj5e#eMsE3)P(S z%08t7aE4OOaI6Kbrnkz^%AH{=zzwp?NKEEjUZJK%&fG$7>aBH@^QH;>>infK zF(-s)WC9ftqWT7p!Dd> za6cuH!7kphhRdv{!rsY;(eeOyYJ-i!-Uf@X*I>2Ft^F`O|7!cuv2`rqZ8-Af>B#A@ zK5!(JDA;5WR}a<(z6^{;+iW^SFzvA+-TKC6^=b>Y?AMNa%J74lMSskxqby$YU=A!a zK`gxZ2?J4&VR~v9#46KAZab*T?F*?sEnE3pC$GmGurf2n3?XvLuh99Mn!+ zM?>gj{EH52gVDrsz;8^BJ>5`I*t8ekXf%oU&Mt1K3nH z0i{3UV*K)js+t?eg^XC8;W4l?9UN zEL+3=V9+1^aDQ~LHt~)k;+F>QIx&Aa=$r*^TL&M+@X@6%!Z$s1G)nbYIAqd}OOb0a zkrGRg4)#<2@fBb`tzq2`qpQgeGb!q1AE;oR%N8VWokHp^8(Ijxx{`jza^_dku|W+~ zl9_+WK{>hl5qY&y9cC1|737BqWp-XhZErBIw=k1Q@17x39&g%c_^(_BOy5-BZMRNf z?q0F!!w4SZxD7#A8$;lDwB25!tCt31GCCxj%);_paXy#RgbSY0dq+DZeM$Y+Hx=4t z@d&Doifhqs{49^>P;i`ei0McEe|CWM-`&T`_e&!-UszdwMyBV<=apgfJa1##vciVv zj$uj`?bu|qMesuNhslp&i(fH^Qt#TC)Io8woD zO?_fW96+=iZ4)CJRi2|$JK91q8V9W;ByHiR#u~$!0aZeu;7-X3!zkR1IP+Z#@_Ng%(Ez?f@+ra|Z3gLS+uIQ9^?HCRlUhKfkJOM#=R3=xOxU#jS z@q$_73@tA=#jhS|vKIewSODATQ5BSw55=K#fClBoEYBtiI^T?;ZU zCLKY51%osv4ZsfEsIVdqtQn0A7-E?5SCpWj`NO)V>=c=r4n**t8HgQLYXs!1csLU) zo;TC_BD`of4OBB&Gl{$G5|@!{^&YU903HmxDqX^=h+hr3@Rw(ETxQrRYp z%4S5Y|M(D=C9CRCBU(&%P7T$d3(Fj`os}U7IUTEJw+~_wpa3Z%P3K)qVKM{!00BFm z(!TJ;dcGpZwKbBmV)c0O(#X;QZG-M9K2ejf24wGvQR_jh$IF+OOXyNFO(BhE ze8rqgb9mY(L`;sDTWd{M;It$Bsqir~PP+lC}Ed0*Z;pYUfG5tq4e7DrW zrt}v#8pvCrjG38T9%TSJxgY#kPL4sW673N~%h}^@f_|FN>jonB9)vqm&B(2eBWw2_ zaD)J6<$`ZiwuJEI?6{PSNm~zf=4OO`TR~4y=~k#Hi&cD6q4)TggzQu>(bjTy-_#Oi zAr?ZB?a7uwvB*gXQ`;p!9f9b9l&`zNmm%+|06QYH2L9g-!Vb;CM9xI|0Mwb7L^&&;Nmamc-ZB*2OHvg~%gG1vDWg~k<-8_p zW+zF~N&RUiC-&4(M$&|u9uvuHiEGr*akold>s4R;GVt7^L@&!e1!vgk)i*b%ALO*> z3hzmS-heXoT{Jt1w6_su9#B+}!3l+R$~3AvFe^RGD10VknkqtT*f$qfg@B`8I~HHqa!{iR0uS{R3|Q5_L9Qc4IqpOVdjZ; z-4jvh1gDY*EwmC2jy$#QD`FS=1DC3a7R6VT4P?vtWMW`WI3<_#_4Qjx0R}a~cNDF{ zbQWkwv{k1gQU^Ki&QJLO2{L^e@tYEe0lkIKyh5hv60_ufA!AYSV0&z%yf%2+*r^RU zs^)`R0k_nw0&+NXav%Ji7FeptkJ3!6uiwf7o(w~sWjJBg)WST9SYa?q%Ggbuf(|cc zJ~B`Lkjrl0&&-$@Bk>)n1=B`=WnjWul@wD3f@G*HWR6k9gW?G-P*bV<>O$yK?v*{n zF^Wo7>sv#XYF%qaPud7bd$JMWfEo#isxaxA1no&v1op9rYd89lr2i*xYj@c{(c^Cm zteGA7Qg(FGaKzF57Uo^DZenPooU-hmoZ^SjM7)J)8QC0&oWkWd;y27YZK@%KHS!Aao{k_fC2{5lV`O zLFz;eck+GQIezp6fgU}}Lkdc=QlqFNyh=K8uYBo0PzTdaCDAPu9s|lldbh(^ml#?jIpJJgKf&bwm%b3JNSeSaIixU z?!>a&EuFkj%nKg7UJ0uITy87uc zILUmkm;R%kpBQBIded56NtT$JitQTHf`5N`b1_t@TkOyexCu`!RjPGMrPvmWP2nys9r^#n zPYpe64yOx)gK>k&>tb86^{C*;7Gr@Jju*4tHIyqF|M+g}tvb#EGovtcO_Zl#(vP#M zrXYnbG>cgf8Awe)$B|Va9q~M1sX%9_0cHf51iJW%?;wGh3{#-KL+25sf<*+Wfw}@I z;ad$RrpIq`kZyL6qNoL!#6h~H`qbxQ1=2wkX75zMt$|cJfiWoPFKq6r68)`)NnKGP z!fF`yl|?ntKqDRINo;-*^N;l|XcZaK4d+D|z;$$DAlE$(+n9>r_4NEU>iM~v@n}XB zY_Fl7VJy$oGm5>`^Yivt@7hhUt>f0f%VR=;ftRKX?0{F@8Q6Cy{9fmws~w!n4(hi% zsQK8q2G%R~gf0ig+rm|+xF%e6i@o9M;xK+kwbl_~d~GqEwuc6K1D5XAs4h# zR50~r<{_nnB!DUD^JB=E5FIZhc8VgL+Q+#I*#VfYu*geYkZ`AZoy-JYH@?ytH24U` zT^57mLfJ!hCPa=>X-g1|IaVqiZ)Ge>irT{80e=@&xs7KEJu`Xdc!}ow#nMr<+VZ1* zszc;PhSVybe<`_ZvK!9pmTM<;fHVYrC-Q!9=cIECJ%z9%`j*1pSZ6zFx>an|#n!$a z;>Z%IQRx!oZcX@{2QU*wd~B6F$b1(n0IgMQ zL(}4;Gmy}{wJ;bjdX*(WZk0%uW<k?28Y(=ht(EI`8 z-LT>l_=newf5VEnRe|AO846oyUajee)|QHGf|)^VaA@Zk zOBJxS41$S2(Z(F6swpJU>TtXWv0*69&hBFf{2E_4_M9dP1?SWII0^oyWD=<0t zJA)!zE&{I^0I<MKcIn}L3Kb2qU@l=O$7Q9RPS zhuX7To_ZIZ*g+iS>38W+FJ$diyiYFgRekqOravj6kC)hW8G8tb94agiYPIDZtS>`;)*H6rEfgf7r@n5A4<=)cAhTXDD1%7CBXu>G&9OB4u zhg9{zKns;>*i`9-&6QH97zo<1(Quq$O3LX~Isi0yxMR$6lKsh$heWzIeCUG%uB<0M z0IFHCS6^h3`%l)l0YfxRDzSpFXh*(OXyIC9^$Ct0Gr(< z(`P)$4n$aBzuf1BxB+7_l(%fwFtijzeZ*fhl37uoRXc7eE6)XrtE8wJBwa`fSR601 zGy9_hA%^m1pj0XG1qzjV2X&R=2NcGWjM|999PysTw{7&&Vg&=28Z)!x)3JSxlgh`Z zWiv@WH7%P#a=0o7jR>Kb1%UvNTdR_#>oX|HQ#+)(L)sTp3tnH}7}BWO=d6)LkKcw7 z4J837>Oh!THZR}VL46^GB)DacS|F zf)=w)%a<(tF(xi4JfW1+@~n5m_xA#(y^22E-WM@=6&(;5i%%)!$v5xvvy!cC?TsXM zt_~B3SOSblzsM)n7?H*-Cwqo2Ht~#4gBl+m&n=k9n~((+D|rq5jy5Fir|!eT)6cscnL|0bb9g zcMK6?=GaShUYENNV0STN-3oR>)?v(Z_sh$uGn+ykqeSC2!VC>LCL%q&@ z;Ay>qj3I6KAgll**a-qwfKyF(8P0gE*imnGtD4=WW|4Agb}|(9l0XSkZs-&z3n@N0 zEEZ@ONogcB=Rtgn>qBA-g(eKGvdq=1)^-dyXEi}VM+`G!F54`Pfv&%3hdC(;KRckI zJZmd&3kq%{!Zj$)&Vw%rW!QN=ZLtYQF~ToMH^u?Q%rM#;@Yi76$6P?WOWx48qL$*c zBJ;iArd_FX#_v6N)^e4hsRGN-5L_oY;-$5<0ghDGfN3N2AZP(;p`HCU%a zL4=-rk~k4E>kcO1zR^bj8%qT-UBZqfU=+L`0QXG;oYoJl!Cujqjfr(-5=26!HVqRp z3|n8jlf7osVf`RZCoC?;=`*|}Sr)^zwb_}K( zo2CXmG(;4MG;RZkL9LpgVTjtma5EDE3$qle2uYmBhQsHsQ7Cp2-A_SUG(a|#<>^~* zNELo;NCnL|NgQ!7{8k(BYeP!WV(U_UV#42l*Xho&vZHOb)4zVgMiy7+jOgUs(0uxI z$(fViX+JU1Dh_%NJDr?>a(KK*pCnak)6+#$zs=+NWg{W?PON_N=?QO;tBEva(f-bz zN6D4u&9umnACfSgLe>vD-nU4{IE&pz;EPrHi3X8Xn--DYoJf_3yRBNZ%G3Nr#m@ql zwXA^an5=ExQ)C4BsxM!f;Y4&xpT+dJ{#N8f)8t-gxL<5l`$Jbj^PVd#CZ&l+F|xi@ z*&$9B74I|>y}5EJH&wE(sgS$nbOXJ+&4L1itqnj}Tn6Ow|9?VGOK^b#TcW@V!S_bM z%PX=oTO!KcNOtlkA&MxyBH1Yr4c*KTDKtfepvrg z529d#x0sP4yLd`Z+sUr$WY>4HlS-FmFhh16S5LLmsC+A3O>IC9G!1pO(j&4%i(&m( z`X3Gq%qRz@$aR9{Z@r6gSowE5?O`PtWvDG<%#>lJwYk zD-vW#a8L$`f^W7Uf(6foOcS`C;c*$)5ARicn|JIv2$~sc}{OkhxRxbzjqItm!?Clw?KapY=Q0~xMYh4&exOQrv}fMhb^7hgE{( zk1Ih@+GW#%AirM)K}x&y+NqHFAG(b$LPb_bWoJNCc;g7;@+1pLnsvNm#0B~!J zg&=!k=%^Q2CsTmmBUoJU;Y*X!6CEvQP@eQ9bi0+;3urn-kQa;X3^fqbd}Zuxssb{b ztHpI(K&BBMB}sxwgu)z!YGEx?s8dnJIfgW})j+&ot^oFKer3I(nWJl9|3v_ zr4odS=BE}SDp=dvTmZMCp13G2W(L(AB?HJHF4=(!;%C`1Xuv2G9mO`)g7g-X7GZw# zRm@>i6?52J#T>TsXa(tQ6e=)478gL8HEqVTQ0B7tbAvTJ0`!5m&)$aOKxdW)>jxD-RvyyeI~;7FqQ@o(tR8sYBp9*^38Bm1$vJ>1!!ybxt2|?IbchpAJrUf} zdS{XnN2P6&mFlz%UZxvmG<0IeeI--d2|2gn)(1`>(T%tBuG9h<;B+q;iBOnL zh_ubViFIs4o9!E0W&~=j*$um8gzC~v)mpci1=z3*=@#vGVYj{);Xik`$X%#JANawh zduGzO$6`Bak$tvk{On3%+n%9bnXscDW>|iCsT|bbf47!_{!Y6oPghx}_6@&qxIUB9 zp;C_0;D%f3>B#rS>lRbYBuW556{4|on(zRFT8hXG53Yx^w-|4R{%WvhdO|U|?YM;> zK>=+%B0Irp-H2rR2DYlkRO@J;!i73Jjnr;UlrmACaP|wys<#k#=Vu=wtC`soo{|Y^ zli#2R2+BdS{n42(f(00nHMKVl^}&Y?FnQ``TgUr~ z{rL7vwQHxVczf}%N?KXeHdETuk!l=e4HZ$zS#E?T^syy&nz9Z7kz%JwZI4ZT!+gt)^=HFg@I@Y5~_cc2Fk-vtO~?>nFsWpFW<5V*Oqq7 z3$xbNSALRlHO?4?4D_fVq()mK@Quic4yO2=5)`4Xbu?3JZv&c%jg-G~Rhe3Jm%$kt z6qDpGsq5yMzG8qlnWlCI;koKiGqyJq(<@)K?>ozM)CrVeI|wie;XwF3)s^okE}z>k zqD*vOp0_?k&3<#Pbf(|3UHRv)RJTlB!7rFSvtJ*=y5K`df31}b+>U(>{ap)~xfrm( zBpLn$2ph6hQ{3Zp_2xuqc&!QLfEv&;`f!n5m%QFAyN7Tuvhr+4HZW&7^Q$tCGCmVe zw_q+%!}diX44cHiP!R}}^(;HYOfY=5#d0G$o7V~Hdn0SPABnEMt-kb{{5o=+hJ5M7 zz6snc*H{7^vHoV~KS10eHrnwJX$JZFRo8!dvAz@PjjEstIysk!=9{8TAA_xk(X{%s zQ+VuqOMcIC-bKM$&=4sou!~LI=f}c~*ef&e11#Lq!yonryU-%%jR^oGp}lV3i^8oU zk&Pwmp_US}@^!$e47IAnNMu@M5Us{mwwI=3_9{mE}aD62M19CfL%v8EUpl5}LW9687$sAHqq)xid zk=4TpCjVBP-$?akZ#K^$PQrcG>@*|XNIxQb&P`KT>(y}9HL}X~C+GvI@wjS4njJZ5 zCt(`|>Zf66B>)Ih*Eb58h0TE9*E+_demFzl`PS5*nd5wqigvFfOrC8%*ig4j8F)gV~q_I4Q+7}a&!_qu(0>02C~-!H?Oa( zXs<_Tdwu0M&=QH-2!B4bU`+6;c;Ho?`L88-{nb?CpoqN?FCZ4~!(!rLSY%w-u=eJ! zasVAoKzy~P@QiQwR`e-B8sJPPlP+qYr)!SPU@X`1k|fB=>3?|gmwxtV*Pgp!e{yc9 z&^9DSc7#L;gENwS33;Kxp655$hmryX!oqWoX(l~H?vN1yW^!=D)8{xpU4ss%F}BJZ zMZ@g>@DH?s5I>D^gByMt;{`W3kKw4!V?=!DJVww4{m}spi!}5h6!Qp(oKQ0}jOsx- zE;a(%z@Okzi3KH`Hhq8>nRcDr-pn=4KMom}V*(`tFCc2pO%n81{l7gKUPbLc5{x7> zM6mdc`U{O9qY|y}7R{ryIz!bx6nvy=)+vrU?x~d#!0S+SL3@AHf;_KF{0Y(xeB7X}O&Qu1CD;VI} zHWq@+sTxRBHwzNTSw&Z2fBTr}}nxHv%8G>bKM+bE?z@_bh)6T5c0e|ef)Yy6qxBbO5iqeDO_nowRtpFC8N`XdbpMW7lS(f&SL8X`~hL%kCkzr zeKQ1hX}|&sNdV*}87vMmE{RZB*xc_a+!^k18KW3}4^Z3pG$27PW4uHFHX#atp($FM z*b19(ES*>=-D67=+eKr*Rs&&IjhE>xgx$T&z}N@k*13_M8WpNkc}BxO*E1CmqyAoj z?61v-CxEtwR5i3l2O`bY}$z6GT(!@1=zRf2ajod-u!qm{S<1yZB-Js8ML znSq87nFmM;)5(N?ca&(#5-48Bt1M_Q9NGzXHgP;9!Mj64W$NXJghTnewZ_qtxNEX( ztOwa3APQJjh_Y_XB5BLAp^0T0FvGsis*~X*wE?IXA!r8BfSt9Z6fS7MnjQ}I`IkTd z0zn{vxZ33R#F^n9mlb{6dvDC71WE%(OhdlYCC99M&QO9wnU%lRjhQ$B!;V)Mr2F&d z7@?Go1mShbKUVZUdp8P+<)rLJ6xVoXk==kw8}Fj6^G;DL;@A1{InL}lA0_Yr{{xHq zTry=QDomxmKN^aX)B%WwBv$JM$$3|+Q%DZV_kU=p@8SrUw?H6Vim17)i45-TQ~tW& z<1&Wr{k>)7wD~~U5|Cmra@g#biLhz$djvdeT50V$sS!_Y1o~-P1n0ULGNl^(;<_k!)8${ zGbS>^r}r85ps;rQd1f{&tPd{(g}K7|_p$-c#^z<9yQQ#kN0C5b4G5@GqM>{ZcOQnI zE~1?Eii#>qRm{k7RbcE-(WVMw*^!Jf7pPdCelEu=_D#Rn;}y3|KiOlWJCB@sO<(1d zHb?WG4VsUw#)bY)sc<8^E)d~n9sYFG&GA8UVfI5}wcdO^1`+Wv>A?i-c7Y21M z&7H2Q6FakLwkE<4(dgEu=P zFF60sN4AwlVffo3?p0>0OMz`o;{cZJg$=+p5Nv%#umm({G%F(&O{fyKW)onT)UYCs zxr!!876^A+72h|j^)`p?Iad6pSUNcul3bZKfi+4~Ogu*^iq?va0b#`z=LP=LNCd=8 zlsBP&33JJcDgqz{p^7S0AXT7>YSGOJ8foM8)0IwBXb2szUyf^J{yehB>#MahuSW!V zeYM7B!+veBKR+EL(OIr5PI2Iz*H;kDi{lL0Y{o3YkdRqaS(h_*g*jG3b2ASP(Z#Zf zq@(NKZ2)qZP5NR(E1w1lWKo46LC?RfKu3p$cFub<1PL~{;X#7g8wD1wg$URdhE;`s z)WrRvdHWIsW}TdUK487hCfCF+!#!me2u_;fFO^+B*d-vj;lzc@UzP=2VyPbO;`N}t zUT*~BayQn?z>!yWraRd7y=j)M!T6nrhTCSqKMNxJMuk?Nv0^PavIM+Xn7wPbm9IgP z2EsQgw$A>Sc4o^&F`D%nk76*{A{{~WvSlZPpeCUko|2B`;9HgJ zf(Ej{-2Nh3WwLo7jL@ukN}Ex6l@5acC>2Emj%dLR);WF|^g7Ek0iXOVykK z&5^ula|Wh-wb2}L1JF0-1~gZiw8dI)iyvDRdDBhub;{6Wd#uyfI9Qp_dGH1D5j(y3 zmZwgCnHey<>AqX<1tIV~@m|u3;Y^J>6ILJLicD8Gcz)o$T-1Asu>iF154@MPA9yd7 zX;qm$-wW@>ViM-Pi0E8@+No;IWu_ z8$1^CUO0O|rf$t!p@C+!V1xJ4iWaQO4D9l}m+5YLx5yYZ+jWC|=vDOP_PALLQWoyL zDE19VF!s%Pxf~A$tr6pXH4lc`sRz@(EDvVZOTj+x`AFo!Ol@OfYuO{Xa!I(XEM>!_ z+?Mbjm+RdXV7T600XorL5h~Rv(AgWoCD>R*bx6*l#VpK&30{ji5LeV3RNso{9!&6B z48_4~F%M?1quxB2MfYGfy9cun@h`2y@RuU~Rc5N&*Lg5(0i2qA$j~b<<-tt%{LNKt zHeY!pQ~ze_%QP!r#;IK%%oI!VV5WGH2Q$TlJecS`R;+xP9*iOim-b+ykMsTK!N_ho z>G9s^phZFo!6_a%ZzMKTZ|1t{D=!U7gwkyRSoO83s@|M6)z_Rg)tj@X`kJ$*dUMuP zUvt(}Z_b+PXPvdvIA|wfKM}t|NNXW{6ZpfNHLkx5Ra!d2Ihv}LPuQzg1J>*oc2bjH? z3ZOomslcC{ixt4u9Lcr5c`x7JBQ&4LjrRa62rtfE^-ie31VXLXU)qBvP2qciaZ3{t zX8#;8K8s+$P$4)dN7PpUNDbrW5dJxha1i^q0bM3d>Qk4-I371M>%v9#R1yPVbiai= zL3~|uaR)=eqMl9?F+8j(V^vu2lRGu(r90?wGb*@Km(<)ro8zRLkgv;X?qKd{g=~#? z>e8A!Xn0%4;SLO6Tk<`L6pO(%h52n60)7s(80GcX5sN0TU2qeCu?(^pJ6EL8MR#o5 z?l5m#Au^trxx>7rto2T9-eGY~D@PK@H7M#1t!)o?Y8pUyXic$a7vixWrH6c(^pLLy zZM4RkfJN-3nbU1L)w3_AMw%*kWooCXf>$b2O#uFS@3!?wdb)mY`vS>@T#6yg029s9%CElp>^4|CFPqx>J0J{NE{?>{q-W02jgk^Okk=x7$_9 zQTd$JIQXmiovtctbbF?%tTDjXtkO|Yy?(B$tiAqXRXKfKpBnmtMz6%E_HD_}+4bK1 zWSc`5!u6{ymhxJ~rj^d;$;IN!k$lQ=6DI<-rfG6qDd1e5BaKj@ZW7;G(;2Fk<$qG! z__;m_xjSd6MgI9Fz&LWg0g@=tCqQ~S|5?HDMJSfULXlr_+46hRX zBWLq8S8DJq4W3eiu(6H48oSXUlaAYBY||SK9Lp4_2*%x$(sgs#I%hOzdyh8vvq!?@cAU#)7y&VJ13;w8M`!qg#%>zFwm%a+5l| zzXqEb!0q-~N(N#p!9Y%sR)Q-6V6Ax0i(1&x9K^0sD{vA&rKmKL@?}aSyo zqk&S?X?z8NQdD_K`8uVkMm!giazmDGs;t}6Qt7o3pCFM1&a2E_d%VAPMY};}wzjin z{O#AWvNJ8!*|{)m9AU$ZFFBlF=8`Ct%uV6PRumx(?Vd1|#J_w-{-eALE?(}~DFD=+ z_j8OShJN2K3H?b`SiI}hKyZHrE`LSqkX+NFG`Fk?HPk^=@-yJ5HunD8x`{tX?sfv( zY8dT8n_fB^b;t|nWSWjXf4(|N3T;)6?P-Lz!{TKQKvQ}$njBcVO0^9T8vb<&M;ie~ zU6*H&oz*4?9`CNkEe=>;@$&U*yMtLlMRnuV*&Czk2Ge6O;eGwsq!Hm^Fz47T5y$7U zdn|hf=zNAJ`1!PcZcUyAxm+y*fHmRyq-ojL`D(~L!sAANY=WG8!rCYcajb+|p4qc@ zz^rc^i1?(j(x9S$lS!MsSpa(qt?{}Z{hJHgksJFEj8i)b_<}a4Lo2$Hw-dJRKF^py zB5RSHgrrZ$bA23n)aFnB&Ydqz1}kg%Gn1h`-yZe~wm3Xrw0BOD@~7`+-$tU(f^u4q zj+RtIYx%N`?b7 z799FIun5=%aEN)WC-!RTc(t*oxThqR>s{mUwEVPon&?S>{Eg43#oe3EM=A=cHyc5#)ve1i}1)-;`{E}6xDox)-tJkTqB+RV*HkT%|GpUHz((FL^ zNQmZ*)J8u+$sUgtUro8}Wp3p&Ojdm5FDF0XoOzxRV1-I8VYFnxmYMs}&4KcRDZ*qNztfcS#ck{(+y@+VL#d{LoI!a;d{XSqpdzLhWE zXj@Ugxykl+ewJg3ATZ(#X5EZ)2$4D2_(3SG3!}fNYI;~Q zDd;FUG`vDE9=wZvf@OC5a6;`b&L{z}}^#lf}Q2;eF+ z4>|>iFsa4CJ9OLUg-#)H3aeo2U`xN4_bGvc<>c?p`99T`%-xA!Wa2$@awbv0T6r0f zrg4g@bYH$ry)2KWUX~YAFGF2RUY@TYJYPY0UT`wR#8Epov_Fgv{~n9A?o|WR2Hs7m zoBH2s`X%OUzfoFj2yMv^vHlrj0_ZAWVN>O>Hc^GB zj9u{V0yS7pQDEyES=-CaRI-CBS}#$sgVAwXE^-rYtl2T!%k9)b*U_BWUhbfRTsyaF zwwF68?$rHY+>~3W*rAG96KAp9%8l(B4^{&}I5^x^Zlj9h*W)M{^b$3ea%axaO3I-h zlGI!J2JA&01+>VnHe-BNfrwRsl!I;*B0gT=nCTe@k1uGq`(x_s8 z4Ks3VYdO(gf?VmO`@+iL8Jtes(;=y;&!Zr5FiAQ-h|S(KFS3cLhsZSJ8d~x%Bfg0W z)VLO{3wGS@;Rog_g4sdS%W$%Nt~n!WB~#SSCy29XbkL*LX)YRO8j!@a zYHN+qf~{LpJ8eO%eSoDjkfF=N`}4xD){q@og2H@<9}k8Kd;_RSjFRPc86Q3FV zB!$!1dFX`ua6$MvJbFKb&&5xOc%-aUw1)(;3A-`Xf?h&=5>PV*x=S>Y2wAWJ4RJV* zT~@wkN|kA>k$)JQr3TUOlJR3Ii?g8BQ%J9to2qGfl0rN-x?H0W4oFGM*K_D7KK3#T z5>Q32UKZ`t%TQSODsNh{cID=7TC%nkFVBWcM24KRe*=J0opU#}ebe&aTIFvia*|~B zr#da3iKwTSc}s1bX?giRUgx31Ofy|h?zlO5fC|74EejK$7F~J;g4nT3Omc}Q)?Eq8@NG>K z{+S7Xgv#^WMfel2QFKx9P%c=!8qdjOOULt|Lq`}8RvHhvp5wQ}E(c*rMJXG4KHU&M z=F(VkfRk<xV{hq#nRlp-Co}UIa>+j zEN$PhyBJTdx@LLr+uw1+O*ikq{-KI|);tjGo z3QNo){Lt{DhR?r(G$je-_Tl{mQrI4PJ_-%PW|K_OmcuwiOM@@yfr1Lc zEz3nlwB>O5jf5LN&yAJ~H^mYpt&D7AtVN%0@!R@tOT6lYD}@_)MNtKQ6inb}-hXnv zX%)HN3|G8qSCx=kfd7InHvxIy;3M_n|2R(G(%|Q2hp!OJj}vBE8l2Z$d3QPfF)aotk)apK#wn4M2F77Y$MU;A(z|_uq8L_*oUPjzrQ7@yG zuk`YkiX6983QT!j6_}dpWri$$9Mo@(G9|$w znV@>7hbnBXa*VcB-=LW<;sS3x{u zY4B63M4#S4C~0Z%w2Kt;OgadM9O*&ukI#pGu>2wJKLzf~!6TFA3kZZOaHbwE-%s^% zjOLa6^FgydjM+}*lPF48uAeM_T@}YfMW~^M5dfUk4CRBv4-jHm8a%ED4F{y5)aKAn zo2Yt>4xxS)-?T53&MUTIN2ja+_Bu)l>Og2-m8{b;;O$W70iE+$Mu*{H^fta;d-##ThrKhf#RBV~v==4=HTNzW_{)?T{SGdFLUIT0 z0Y>uQyMRVyj1j--_ThU6x5*CE9D4)|mj)jbjf!R9?GU8)GQ3?`?z&G4(Rde&BT@NK zx;{Cew?}jQx)tRfRAmjrOmTBh%YX;9H`#S<&PSxA+5~N_D-W>GAT!wQ8vufn>DHDXKldy%-By#JT-YtYU0rFwz8nB zzbMkP8hJ(ssU1^$Z@>H(Z!hOYvIL8fOh3t1uF45_QR=mKhPRe`s6P6+d1YEGvGz#BzWMzN@|T zw!X={J&GnT5y-a=C;jpkN@GQumx$0CN9W?#5KR6un*|yly18qiI`zeLJ^N56#1|CxSqDPGbqKE?m0 zUyPpL)-U1me{+|`m4}=+sY9J78B|0-slySuPgsDNrQ`j%(&OZ45(m)1klCB?MwH`n z#^P-$2U61>^7vKKW8`U{=XhQOJnU7N*JWoDt!B^w7^-kA_GP;42bkw28zA^EL&T*4@(`ANJ z$3IM-2S#HLz*z{4CoCwq%z=_uGHjwGYKRE3C1TjU^X&;nDo0gH{$}O5CeA^2K#dUo zL#^7X{xV~P+fhy$mDZ9+4Sa}N&+feAD&PKsWmno^#h$cs4~aSK5y2w*2!6J85fiXf zM98@r2GpjPSjMro(4u23+)`cbtFD&gl^!a>2sJkB55V6o#VJz1Tg^%Win3r1g^UUICpXtzAeN|A=5qnE#|U#%3K;eyL0g782@ zm%xK8Q{7j8=WNla{HBE&0JJS^tphTz5$D3aG^{!|yhTvcJA~00>4SNf`zMU}|Eum> zz}&d1G$oa!R=?b8zwN|vb*GcG6Q`|5>D7r7%ZZ$rgxKUw2o zQmMQB$cyirw!5q9KF>Y(oO91T_uPAxix+Q3%ZIP&_c^)s;F2z1D4@YVgXV8cT=3_w zwf4Fb>Jy>xmCi7c3!iU?A=i`k7n{r74KQ1dMe`)Nr@IvC9qGclpP-V`z*c&MUVvnB zxWswM&e3RuU^>YTiOF2i9@g+hsC%P2Se74;h5I*Pq(TCAmDs1`W&|!^5q-dchvN18 zbEA0@0v03K(XeMCN!#gLh?IWz77V}1jao8SfIewkk}o>WuR_QI^TXKD>CAyg{3E`{7=F2V=bmP zBVe*H<~6XNUfX}39>h2Y6_>u~qz>hAMJa?=iWpuN&%2i(uR)?==gvj>M7NIyc$XyV zJJyA}$)${W0#b+F0x3@0c*S5yNP3FqzvMQaPNhmPiZuxOyDcW2fk1>NCh(BPh~wjE z7#fpfJA$&sI3IjO0kHk19y~Wk_1*XBP#Pc$(2E{34%>*YzA@vl?>$xDXd+EiPIdI9 zS76)ub@t0}ls7cs#vCr)^6)Vd4ob$g;3z-HbE7H@|Sk{+8@CPavakxRjUom zX<*O+!!iZKG6#l33WoMYhVV{65MbzY-TYM$V8HcL4y0rQ!f;42KHD+i-UTGxjv|)3 zm*cc|z#~0&5p@y$oW`q4ti(YcAFk-qZJcEZoYavO#Y-rF$c(A|gP_}3 zXT+%5#({{@&ItN5xs$x8+q^;7SHJBQBw&CofptZ1ko4`2BZtJiTi+Nk+V=AAb$yB) z()D0V26-479pu^s+};#GoY}(LOQLckDzD9@#kJJYz@uHTIO5t4=$%Tq^s9C2ygs9j3P-t!1ARl^>X!@fmgu2j+ycy1Jg)m; zwhIFe6wg0E3h14@hz-38bycOoi=^Sn>XHVtTUuAnFbzC@RXKQ(a=N6PVgKWh6A-De zimK)kb@HHq2oGD{r5;yDwpyKGgT)^a+QK2S1R8`x$AWUJG--e>7IJTjc z^UqiVOF^;f;@SK!3{G&7`3=%Eu;z!36m=FIg!=!(dZlzc+NGQd4q+IxM_e))@_r(tAa=h3CmOY=z-@iaN-W za*eWFWI%zhu9%`p)eS}wwuC#AV0x@E{mG;f?o;4)8Nw;bk4RisDs{jE0mY*1E3lRB zgOQ&QV~B9v%fOgaAP6w#4&G4Uz6+rkCLD(|pS(d~lHuSHn3*HWN!2DC??eMunAWC6 z2nYP&?xpmMlpVBTE6!JmX1HxY^t<81^coh4+Hrr_sM3ga zu}9e5;+@SL$LIy>lva92fR6c$(q1@!@HA$T2@MKs_ZutoPH7-iWmXlo=QM(5nbHty zSgSZ|VJ5);$ohOZx)~J)Ss}C0F^rQlc>Nu5CljRo0B2H1!)OD?F$xrKrPvRN9ni4- zbWEg_WsH?U0`kmqdS~Td>f!{5>o|^J4s1m5MrZ(H1cTDRiw?tNHB7j`Iw8Se2=U7j_sVA9Z=LD=IzjGK8W_V8XzB zhZr1H77Tp|!dH|Ho02+p3Fk&WM0!bS5i3Su3u<_6V>3hz)oHNBsnnYMv5kwd=Nk(O zwj~HC&}&2)fU!#^kBcHlM`xqar^k(h89XVAVeTTfY@4o_W%0q`8z;cK!}ofwDqwRb zSVmSUsgJX7LC!zIlV@x$LJ5 z2W%YXaJ()WGZbfhU??VVeF()I#Tz=xXGaxz ztComXXzlI8=w+trnMKM3)tz^H557hWW@GJZhVc!CZO<6-4F+`flsnQ#lpc}*@`k)f zVHnx~XJS0uW-t`EzzhoyClv0eY^IRqF^D@5NtDYicxU1P2t2A-w#6q*ghesgRoD`_ zHK-gJfIJat_D#Y3B=sv>K!CTNDUF*G+2K`>b7zEdBG!Hsro_N5^DymxIMgBxF^J3K zL|XRi%g24|@wsYiuTBejo?3 zMO3y3z9albMivugYcW;B;-|V+4Ge{a0<4=03Y4W&p#ZFbnMW8#FV0_xNta{>UAu-l zxKfEwv;zhdfbd$Ht_BJSGO5YF<>^gB0@@2ZAdw&vo~Ln8>01L!TrWpO@ny#*Yg>B| zbATcbXEap9qr#UHCOrxhlCB2JBjJoYSVHNhPnb< zoPS_oeFir;%gtpNa!^cEhOj;{M?{r5BB(EJj(|58%2(zHrm?kn=pb!#1hl6!O%tLy zg5}^v%n^{%Fl#7t1h%+`K)Gt?Iyi=2`>17o$+CH%Hg$kuT_ho%sP z0EyiTD;2w(HZd5Wh(h!qiV+rqisXx40TeBxz=KmsuRd7lUnkykAXljD=g9uM$DxD* z!!YjCwn60wl1y&>b_OC*h#2OP>I?%*;1Q9@|GJpp1aeH%#0PcoDuB;)lh#=R3iW{f6;Xp=c7;Lp8es`|m8$x32 z<-j36a>G*q6hcOiVxAM=44oxIUmtJ{!|nT32o&+=0>#ZP3Xv{6IT4d*0t^SHA>1g^ z1_SgO9qC*WK?PniaC^;51_~skJSiEt>h1zEaOuiR1`Ip}83<7=Mh3w0n?ME~7+(rC;lX`5e6}5OpA2F7-zLR(>`?{77uDl8D(*4$I5w0|Ng?jbBjb{( z!^I3->rw9xDVmiVjsx6}2T~V~Ei4H_?m49HN%H2MG7 zVewHVFhUCGupIj(_Yl^87q9l|(^k8nLKI2Jp$sivr2=?3xKnQFhNyav9y~w?9zZsG ze`l*=h-d16Gu$(E0<0h)r{&~9^6E?-&=RWV9}N=^Xs0++2bJ1q4KX~-Gj*U$qu2BA zg}F^3R%8jx=s+0~L9;@zcs|*Np2}kv!<161oXUe*(I!^HaBSW4apY-tJijsf zw~e?ezRg}j09#bHC{Eu3I++_Kvg5#i5`z5bH*W|^2)R7yCpB#0 zAzz;i_`5vpq5EYOjr&kZ6etE5AEHAv91)@IoXdb)p|9hy6Mas8As%dlrF;Sjj;A?e zfdOH3pokn2Bh5;_Xg?m1VZelAKa_7EqrJgWWSqbxNG3jFN@xIr8%Yy5`wvoyMY}b? zpH9`l2LJ~Q3yRojM`8affq=&saEvm=XeVbv*of~#lp&#V!BnN=FFMM}qws^A z&Vg=3t}WHoxO%)zd2p%4hhtUe$uka#irjxLq9i-m$**I=Lg- z{-LX$i%_&jDB7KqGb0r3LeCfzB8wcC1`gBVCF+A{M@8;&X%R|RxuOihnxY*$cDQCD z?#YOxXpfMTLL~GEC<6ds0f)vi0l=Mq1;iv9frJ|NjrwS>24l$bi%hzp^n#@w6&SiV zzOWC@ZZ!yT*w0*aE0ohZqzyf)8Z@n2y@BT?8TQz!a}R(qTfA#ZylWz-1bn!N0|ZJE zG+roG1iO1ykBU@c8G@aOuoQ$|?4{}yX&<*1fv`X^Oeyts9=8@j_*T_4k{~)+B#uva zI{E2~^L>i+WF3VB2d08Z5#b@TPxPqvvZff7w7Wn{vdcm-603@vrz;6%z{yZW;;)yI z$;aK%n_Ob`12;(FfmVps-dqopGGc6v#A%19AwX&Xh!SG;wTV?JRS<|mtP-z-09<1A zkystoL(Wf-{p+MO600Bs#7U1w2sa2&QYnfd36WUYji4+1;l45q^pWkLOo$#*m_!P( zV&TT2D3FTKp%{IbiXGafo?aCMY88UQSfdEPO;9-V)(1N15`vN{M1dg?pcU+EgXnwH z2nw>TTl}q`v%B;4&=oq`r5fxV#2S<$5ok`1S%H)bE*Es-Ol(`cg6T!>LO7FH7L%qJ zn{j#cOF>+A#{nb-i7k$@vU>wNjesOQc-rGm+MI`Ry8ECy{hsV=uPEcZvk{EB*!1E| z7;Syx-X(z$Mo5g0hqT4UN1yVe=MlT0Ca%7Nws?XOP~u0UoKtmM(0<7f(on?UlnS*C zLsB7F1&~Ae&zAU#i5>+(IxL?*MCw#(K_HLQFC0}~n5e~##%lA5|5Y(j3&)d;Acsep z7ba?R)Iuim>!?GTy^x7Ck1`J=lNW@-u~94n?vvfD;N6#HOiQf4n3A*3b|Ck zv?-Pg_T)qz}?hUoMS5$qQdqvNGRott!hXaC&S~wg?eVxOB zeXtjfm7dSCCjxnUC_p5J0_daOG2jGF`(}#-O`Wr3gp#CAa7tvy<0(~m{H#RWo(RZF z@flR_^v9{7h+^+4C%*yvj64?0G1wt+exn;5XBq{PJDahAR-j_~qH1J6x9e1`r9^lA zhT3%EOh{ymbn){IoGUHD%T;J$lxH(SlGyF-l+y@T15zu%0SU_*sldyAu2hc(?(+{p!$LN62azL_ zsMj)s!ItoYT$MyoI9wS;apolg53M5AKQ#JSPU_BjkUyPojph~-uCYoQwWlTpgj8pY^UAF))*N8Q$ z)_4=L;ovSDfG;);;}8mf3dwWY2q+aowYbbd1CC2@PKS=-^C25QsFA`zSZe=|d_{rTRA7`h3*)IDR4#m@f#ssTj0Uhp zoFpdr2z&7GwBJDj%((#|OS;MHnkRir97h$ZS1<0GM~Ok3+k&nIb=X}iuqeF^z|$X( z(`p6zY8!G~iyZb40;;tQY_zcIgxpyV_~7zj1l<=^U3l0&$x_k&yeSH#_ixV6b19Qz zfSht%8DV62fUt801Z@(;91K8Cwg1_v7p3Z!--%UaFKm4aJ3Fabf`ZAtF>!lrGhkLR zU`$Lb_l)4MU%(zuAEZNa>l1}-G+Q!by8 zX)c+gi{(T^JzO2?-3muHSabDW;oqKvV$}wQfGnPn1ahR!nNx2#gU~sTYPHxh^vF{< z<7BwUK1Zy_-Z%&P9EH#v>LW;~-Ig^lF3Z{&4jhrbf;EJam3=1dvfC+RON8xHEkyn3 zt$u|BB2OIP&_27JGEI>B23#!z<0HU)+2_@a@ZofM{v~|CX21bhbfn4GV&aF6Jn5SF zor46$#P8UF#KdoFLv1+=23E5IG@MgwI`r6zIMEH`wKDO`3|S(@#81A0XovPj^ZKQ2 z7Xiw9`k94cf|B)rwjF`M+8_d<|J&XP_`n2#A51KoMcX>xp;;_yod?{UPJ*h~r)~X$ zAX4l>`w*87_vB0@3%9lQMXmFw749meM!#}azy)g56r#~~+SS0!<9kaN9NH~b7PcgY8c&CH}KmpD_wW@^UZFqVR+B&i0S1cRs?WP{bKJdd1!%!2)r{X|OGiuEQ#{^1p}`H_nW0AU%4gf)^?u2AY4v3mq4IW0?{k( zUQ7`>bpN!w%RZD#eIvJhD3{ZV_CT{jr!$SyOQcu{8I1K=*I_wW(c`*&cE_aGnerct!W$Bnkw74Qo6}WHf*bqk$}_5KZOzD5NMI&Qc&N6v-KdOjE>KVOzggz7}1q zY-H^yn}aOZm3t}EK}dELI6H_{(7K2IY8NdkGmsvBYUnIP;9Mw--t5R8{j7sBat|;F zZX+Ca5Ay_Oy$8zKZ!+|=Kwm72Zo-=0Ga2bnoE)_gU*E~FOXbyx=yxK}dwit}NK49a z?Ro8&zf}?Qj=SXK=@))E-_3oYY-z~ z#Sl!+6?HeX_{8PM!7jRBIKLWOeFE+TXf~jR=@H@$i-n^@J_t#MIH#^-;sloV!}=hu z_rr3&E9;_2fjJxxjKagRq9eh82Og3Di@{R6eQxE*}ByN5Kj>q?m*0*Fa?ZiaKz)9VS8pu{s)lR9FTe@qic7@YO@W>}X(%c%!mULG<%GbyD}C z3W*Xe*&g;fIu`O}r=UZ|w#B=45@j$iyI883-@lWtf_x?EpX!Blw=8}HXjMfU*xl|t z)$VS6*vD3k4pT=~-7VG_%;GsuJ;5b$-7o#^>zJq_QpYj~DF2{R9292T3c!4SAJn+EER1wm+0BvApKn1R z!F)t52n!+DgNqXqPZ!iGXFu(M*8hkcN>#Qp)0il2lEl-w0B~oe;c^%lo#E-~KN940A zLVR33FdT)7?`ZswNQ-~u2_S{!k9z_}8Ss)P06LDJ zMpzq-vN2swCAI^Cyv5J20~ye^G&QVhQ0CdE6adK0J`@ieHCXsB_C=fv(V{eVfgk8b zf;X}T?i}GO2M8P#N8{IkNOx$}(G9-dFZ=x>x0JLFY!NOJ)M2Wb4xCJAvIF3)@UE@D z{>ShBmtQ~lu`i4(UeW-W5}fE_>88~}`i?{g35fll+^CiUpeHj6TE{e^Pk?0rF`CLU zrP0hI<$y`-2K2s|(0n)?tM^kE(1-t2KfZZCC3Ds+O*QxFwY#i(Wx96vy!h#`#p1C{adQltxb*Tsgkv6rdCD=tEQ@Mc2H9{tGg_{QmgBdlGp-< zb~SecAKo7ot4e4z&3dz;n@xp93%KRSlcemkRXKea`kOv7J&kvIl1590&) z)$z-p#mZqg)A2`_zl*118vdRx&FSi68HD3>*Rg+KXB;mb^mS2z%|#7ZMyvS zcTW7pe?R!(haUc;CqMtyzx?L2&wu;xe)jX=;L;6oBQt)<=Iw8J=fMvl>Wg3f%V)p+ z!izuqxi8qiL}JG;DQw&RmOIMU!G}Ng@#kN7G1x!2p|JfHd_VZ`lSux}=YRUMpPxWz zVSCwX?LYX1XTJ9JAN=sdukN|`eIL00fkzKN_UR{{{Oni1_VsUm>xCD8@?Woh^sm1A z>vr6F+wFJ!;d}q$o8SMz-=6r@|E@P4YR-N5BhPP|IDc%@ z4buz$&l(6~0(6%IusH+KcPR`l-- zUZGvA`GbSufxhwJy7T(O*XlFDcb(UIE_C3Cwl;j=U$nP(t>|6Vy}WOE-@C#+;kDsg zBNv6X^=!nxbiWqw-56XO?$uhKMb!HIwZV(EX5>y@XFxo$fm)IH9a~s z(0U+v;3I2#SG@l=ZRMI^wDp_NrqCr_fhDWETc1fc`&xgqwlCCrCDi&-Xr%9B&-VQ1 zi&h+bP|I}hzkPY@=}7D8%TvLga5l0n(id*_o}=9se0z86p4DgftnA*_)B0fe&mQYr z6^wr}xc?{TclCurtxpZ^pNZ}ry)b-ju=QZD^)>A*ZJ^&5#t82Z20+Du9<4VJ^$!M@ zhL$Z|9#|1rtDPNM7aZ}wOWPB8Ch)z$_xpa({WpOh27cl{9(pP8OZ`OfSN{L&@4MiV z%dXq;&?i3e$KkH-^ybTM{`Il%1(&bB`If&*z3}4krSJd1hd$9sk=N}gTesc*r7s`6 z_v77}Lk~aE)pN;ZwTWN;!)?Wne(ZwLn?8Q{lYjcy<4-*G)n~pD?(JK#Zv67X+dlpH zcfNbLYt7o>^S=3PP(Sy)^GB1}@vGl*?amu+x|y^!S+Xj78hhXK-VZ+Zna>?LdTi6> zcMSiVkOtgaLI0+))`4|eeBkWhNcTCRi$Yfhmt5HTOn4+X5*&>fz5dpr{h98SJ(1R< zIjt1wj;#z0X=jD}Te87xLZd+~*d6Ka+M-_&?CVZz%BaGVfd0zPxx(Ne<-SjTKC^Ee08L!_31l?3%xzz{$<%n zPkOBeL9u`GhCcs(-_?;D*5&qhZR=U5U9~-T3{I6vPe*LNb{p;Vh|A7w#_k{Yj?yl&+ zooxM6Pa{%YwXOBlTe_FFKD7TT?cS{eEAHKS(ffbU`r(FaLOsF2!NZq^{lS|;XBmP0 zOEw0}eK+^?YqtkC=hpRa40eMG!>y0r^MhU%*zCLMqP`&D4v$98xxO#BSv!0A>QVo| zs`ssdpe#Wfvda48j@jl^tvWtFSG~J#&W>)F)N54;-O1}}Rclhe%bcFGM65dUv?l52 zYfnmEcW56Xk+;_B_1fKUoog2Gtb672>(#d!&3etmNNx`k)w${Ejnr@I7RGiaP|a=5GKlKCQYb&uOb9AZ{w{ zwn}?|(M^qdX_JF}rQI}Y_2&E@FdGf4&aTue<`jB%T%SR+FWpS-h6Q$(p!6fD$o_Mx z`kd6`=3H|(T1$ALO-s9-G8Wd~tW6-1SuI)mMT(I0%k*}jlhJ;%mG!x5b7}@UT+`e$ zRo&Im#D(P-Yt=F^KH7vz*Dy=K{|2_#2`*cWCM+e+&%*qbdTqvq@UqP|txMa$5LcL0 zsviUeL{`zw>AGc>_o;yLn9q)%tGX#fTbY;2som!jGBg1sRL5#rCnjt4spb@vm)+)F zmfkRDEWKpb%TrYlY!iykomRP>-B+tl?^Cp_3YjtY>2+%sl%Nu+cTt(xFt7qRqlgL5 z9_UX~Ri7P?z-Fzc*QUK?vjnr*v}R^8MW_La>C)V^32lt?g}OC^{AH`I-#rB_+0@HZ zcTIr;$=~m`>NP5e_-XfoPS6Ayv$J)~#*hWi*;>P#)|+=jJBRWHA!F$vd8lOekGKDK zaSm4{<+Mq_TYe{R6CVWIRMpuTUT1SUv#8tv@va&gj<4w{h)1wfwN|~j zG*_=%)utC>yL>cNdIq9~O>%3QMFk!0^Wc{Vgzj40C-_^W{j+A>lwND7_S+~vtq#s~ zx?P@jlBXT)%7ePqn41=9GOnZE@ltKBO{)|2+O#z>YfjZ09{67!eb^PAiF|2Tjd4)s zIG^B`4*6p3Em>9>U1AFfFrpH;&Om~CDC(Hkd4e_7ccZDE(<7d(z4xXK7ej3zoODag|hThm+o0~2x z<|m(F_FA_}P10Klm3jFA^@2GaNL7h9w#(vN)H~Ic1j2zNN2?COL2&~Do+^Q>%U7F? z-4boxIcHAW0D8-7)~CStHHbfF7!~Q&W>)0cX$nW|W?6Pqzys}cH`v|NE@sATmUcs= z09u!V%43dPEsCbl7I_Qh^=`;tt3Fnq+6Bq3Z{Dn1_Pey;WcZ>yuQt>e3u!20*Ij1m zwaYsjUmf*XjRyKuI*3wqytx-_RJA3u%5WX9X;o`;yMTgr*EJ|HTtchNO;@HsCs57M zq10s{b1HMy636vM2l`J+9~eN%JHBZXNaAP;1kB7r3ur*{?=~sV#5CrG-%W-VkbkOs zo8yqdzu_KK%FX#Ghe2V|Xsda}WX& zN#v)6u$6fGFrNK*I%!sU()?o=Ecl2!f&@(ar$|dVa2(;R=c!1$&67xT5yB4PNxbYp z!WDS($0^5$^ylOId_3{rH->|Y_Y{87Jo$+t4z_bQjxx-NJA(9aPuz?ru7!N- zJ#l+IafcCio+s{ocn6y0XD1LrTsW}&5#F7+7$Ur7e#{dWMci6XzCXr$AAb2Wi#QrC zoie|VclQ5bbg;A=@#GVxaq5~y997yAcH9-7xGjjg*b}$S6Bk9?g`T+Wp130@3nqED z%(r^tjv*gmIAK3o_c{2zlT41EI-clG-z1(W#`k%2fWeF;CpL z@y<5z=P(kJo}GL@#;X%Ii?|U_-2d>z9Yq}Z(aHBKPaKJt{1n5Ju>4Q_I{b<^0-ZH79IsYhtR}tOb`c z)G8-Zsdx@+DfOw!zR(he&DIe=G1shQ!~N~=>fB71s?3@x&F+i1?=!RAy-YS^&CEdM z?{Oj;R zp4pu&RkHD9GJ(I)d}GDJ((3`E(E*~fm^F62dAAMejU!hm5c2{Gip)UAx9WGX%u1pd zi)D>+CQ(eptxT@4EDYqMQzO~i=`5koRu^yrF5mR;!aePU096``&@Q@6=#YyU{qnPl*q-+Tr!(Y zCyM1vC0SSaQ!JIsrVT5VOq65Ul2Iw>2PiIcS!u>>ZF-Mcu8H)Yfko>s3-Z7-#~B;j328v{ z&nYSIv<)k!iaHIHivOoiUgw?hFLPrY%Fc23l|L5VQiczTDzvI6IddF znPpT)%$eB@UAEeCVOS|q7X_(6ZOjq~4l^lIw3Ud-1Bw&;GbUh}5`l=i%vdf9Pm2uv zC(>Cfn=V{TAuTzRShP+;X-OHvU{f=*igna@i%5*LQ;peabD#7C7ChuR*O+>@MRCpi z6u1e~Fw;gh8%vhqZ;>dB#he=2L!f$_P&v#}5v~@=axs$yWR+53)A+(1@vMxR6UxcN z>7m_Lu>|jsTq%_@l8Ka+D8yV$5T4w&S{)W34tj}MvrI+O+Eq8F0cWgOPMW2dk+D)( z9nZuH@td7mPn9zP@iUj9K88P~=~`p1Zs8r87yqE#c*?Tk$x6ADDVgzjE>}pnt+D$i z;q4o-3Ol`1j8&kv028HBGHYfMh2$Mxn51_Suda8}hNo|0@Onw*;s#7wDYKM|7mP7) z`E6_^fhDj83dj9f04FmlCss*rLA+$7Y>cv`i@;xe1l1~}7{i;&sSjo^DzNf**L zqK=eOYDTW#Ml~@rVhZhaXa$SVS(~b2z)T{SDkUug?m328$ZR9zN~fc*hLmS3z21_n z;@mC|29hz$f`d;i7fY0_T*fM7%P7ZIK~+A{EMY9$1ugS>KB!M^FYje3XIM)*4V9w= zAEaym#FjHST8INVkCSXsLlgUcD3}>XmSR$Spza4d?lR_SP^X5fX4|@< zET_coi_(hOl$kVR26TI9E1i?UZ!`)G_$`*p=?cc+BHC*d3TFzWT6$(bry*S| zNabSMie)lpVcX?r)J_aQSUEuf<#f_Cpx7oW$!s~1%@wXXLl~;o-4mc<6ak;jO4&># z%DG}GYbA}s)!R=4gIceM8}(X~1_{{wxqd-tGD&(?W^QY9O}f{-f5D@G}2rsCytuJBe@ zZBlB3z@Ei&)GQmp97zK`kSdmqY|aEB6s{u?%x`T1dJjA_%xUO8wy(y7T|lK0FJ{sJ z*r*iYA{#I4pg=x3+97&`Te8%muu?u9Pbv+$O%&y1F=v6Ufc{(znqXlk#o5V=jK|um z?&(?R!&9YBlPU0LxolYF zoRurw_zrCf>NS?cd`uG1??nmT7_G#J|%rQlERp(!bSil5Y&+0U`WDz3&xRL zF_BB8Vuf4ZdPXJXoThtlPEs|@Y!*PlYuqps>2l%ix1O@Nj4l0KUP{CiFD(#`C8!8c z^NfmVWg#Ath1({8Ylt&}o3SW_yP@Z>7R!aFzvJ~?YTs7u0#0(+V`2#L_F z6pLk;dy3GLjAAyOEZn|q5uChpiIYVU$sGf-N>BX70c*=}f6(dvl E|Is9^ng9R* diff --git a/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm b/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm old mode 100755 new mode 100644 index 2dd5cac8235c7f6c839e64afea12a2cbbfd97e8b..daf9b0468286b4a56660257bb2e1936d1ab9ddf4 GIT binary patch literal 135000 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 P(%F0}XD6LTwov(h*rLXU diff --git a/substrate/publish-wasm.sh b/substrate/publish-wasm.sh index 8424817c66..7ac79a99bf 100755 --- a/substrate/publish-wasm.sh +++ b/substrate/publish-wasm.sh @@ -4,7 +4,7 @@ set -e REPO="github.com/paritytech/polkadot-wasm-bin.git" REPO_AUTH="${GH_TOKEN}:@${REPO}" -SRCS=( "polkadot/runtime/wasm" "substrate/executor/wasm" "substrate/test-runtime/wasm" ) +SRCS=( "polkadot/runtime/wasm" "substrate/executor/wasm" "demo/runtime/wasm" "substrate/test-runtime/wasm" ) DST=".wasm-binaries" TARGET="wasm32-unknown-unknown" UTCDATE=`date -u "+%Y%m%d.%H%M%S.0"` diff --git a/substrate/safe-mix/Cargo.toml b/substrate/safe-mix/Cargo.toml new file mode 100644 index 0000000000..23a40f81ce --- /dev/null +++ b/substrate/safe-mix/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "safe-mix" +version = "0.1.0" +authors = ["Parity Technologies "] +build = "build.rs" + +[build-dependencies] +rustc_version = "0.2" + +[features] +default = ["std"] +std = [] +nightly = [] +strict = [] diff --git a/substrate/safe-mix/build.rs b/substrate/safe-mix/build.rs new file mode 100644 index 0000000000..55688bad9c --- /dev/null +++ b/substrate/safe-mix/build.rs @@ -0,0 +1,14 @@ +//! Set a nightly feature + +extern crate rustc_version; +use rustc_version::{version, version_meta, Channel}; + +fn main() { + // Assert we haven't travelled back in time + assert!(version().unwrap().major >= 1); + + // Set cfg flags depending on release channel + if let Channel::Nightly = version_meta().unwrap().channel { + println!("cargo:rustc-cfg=feature=\"nightly\""); + } +} diff --git a/substrate/demo/runtime/src/safe_mix.rs b/substrate/safe-mix/src/lib.rs similarity index 95% rename from substrate/demo/runtime/src/safe_mix.rs rename to substrate/safe-mix/src/lib.rs index 7512d8db81..05e8bad95a 100644 --- a/substrate/demo/runtime/src/safe_mix.rs +++ b/substrate/safe-mix/src/lib.rs @@ -18,7 +18,14 @@ //! //! Described in http://www.cs.huji.ac.il/~nati/PAPERS/coll_coin_fl.pdf -use rstd::ops::{BitAnd, BitOr}; +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(core_intrinsics))] + +#[cfg(feature = "std")] +use std::ops::{BitAnd, BitOr}; + +#[cfg(not(feature = "std"))] +use core::ops::{BitAnd, BitOr}; pub const MAX_DEPTH: usize = 17; diff --git a/substrate/substrate/bft/Cargo.toml b/substrate/substrate/bft/Cargo.toml index 5d9fa23c63..4c5978429f 100644 --- a/substrate/substrate/bft/Cargo.toml +++ b/substrate/substrate/bft/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Parity Technologies "] futures = "0.1.17" substrate-codec = { path = "../codec" } substrate-primitives = { path = "../primitives" } +substrate-runtime-support = { path = "../runtime-support" } ed25519 = { path = "../ed25519" } tokio-timer = "0.1.2" parking_lot = "0.4" diff --git a/substrate/substrate/bft/src/lib.rs b/substrate/substrate/bft/src/lib.rs index 110d14ee1b..46f8f8fb3f 100644 --- a/substrate/substrate/bft/src/lib.rs +++ b/substrate/substrate/bft/src/lib.rs @@ -21,6 +21,7 @@ pub mod generic; extern crate substrate_codec as codec; extern crate substrate_primitives as primitives; +extern crate substrate_runtime_support as runtime_support; extern crate ed25519; extern crate tokio_timer; extern crate parking_lot; @@ -37,6 +38,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use codec::Slicable; use ed25519::LocalizedSignature; +use runtime_support::Hashable; use primitives::bft::{Message as PrimitiveMessage, Action as PrimitiveAction, Justification as PrimitiveJustification}; use primitives::block::{Block, Id as BlockId, Header, HeaderHash}; use primitives::AuthorityId; @@ -176,7 +178,7 @@ impl generic::Context for BftInstance

{ } fn candidate_digest(&self, proposal: &Block) -> HeaderHash { - proposal.header.hash() + proposal.header.blake2_256().into() } fn sign_local(&self, message: Message) -> LocalizedMessage { @@ -334,7 +336,7 @@ impl BftService InStream: Stream::Proposer as Proposer>::Error>, OutSink: Sink::Proposer as Proposer>::Error>, { - let hash = header.hash(); + let hash = header.blake2_256().into(); let mut _preempted_consensus = None; // defers drop of live to the end. let authorities = self.client.authorities(&BlockId::Hash(hash))?; @@ -521,7 +523,7 @@ pub fn sign_message(message: Message, key: &ed25519::Pair, parent_hash: HeaderHa match message { ::generic::Message::Propose(r, proposal) => { - let header_hash = proposal.header.hash(); + let header_hash: HeaderHash = proposal.header.blake2_256().into(); let action_header = PrimitiveAction::ProposeHeader(r as u32, header_hash.clone()); let action_propose = PrimitiveAction::Propose(r as u32, proposal.clone()); @@ -664,11 +666,11 @@ mod tests { let service = make_service(client); let first = Header::from_block_number(2); - let first_hash = first.hash(); + let first_hash = first.blake2_256().into(); let mut second = Header::from_block_number(3); second.parent_hash = first_hash; - let second_hash = second.hash(); + let second_hash = second.blake2_256().into(); let bft = service.build_upon(&first, stream::empty(), Output(Default::default())).unwrap(); assert!(service.live_agreements.lock().contains_key(&first_hash)); diff --git a/substrate/substrate/client/src/client.rs b/substrate/substrate/client/src/client.rs index 4b803486c0..a0c54097fa 100644 --- a/substrate/substrate/client/src/client.rs +++ b/substrate/substrate/client/src/client.rs @@ -271,7 +271,7 @@ impl Client where ) -> error::Result { let authorities = self.authorities_at(&BlockId::Hash(header.parent_hash))?; let just = bft::check_justification(&authorities[..], header.parent_hash, justification) - .map_err(|_| error::ErrorKind::BadJustification(BlockId::Hash(header.hash())))?; + .map_err(|_| error::ErrorKind::BadJustification(BlockId::Hash(header.blake2_256().into())))?; Ok(JustifiedHeader { header, justification: just, @@ -453,7 +453,7 @@ mod tests { // TODO: remove this in favor of custom verification pipelines for the // client fn justify(header: &block::Header) -> bft::UncheckedJustification { - let hash = header.hash(); + let hash = header.blake2_256().into(); let authorities = vec![ Keyring::Alice.into(), Keyring::Bob.into(), diff --git a/substrate/substrate/codec/src/lib.rs b/substrate/substrate/codec/src/lib.rs index 15ff92b4f6..7a9f17baeb 100644 --- a/substrate/substrate/codec/src/lib.rs +++ b/substrate/substrate/codec/src/lib.rs @@ -27,6 +27,6 @@ mod slicable; mod joiner; mod keyedvec; -pub use self::slicable::{Input, Slicable, NonTrivialSlicable}; +pub use self::slicable::{Input, Slicable}; pub use self::joiner::Joiner; pub use self::keyedvec::KeyedVec; diff --git a/substrate/substrate/codec/src/slicable.rs b/substrate/substrate/codec/src/slicable.rs index 3a312df9ce..592a348c19 100644 --- a/substrate/substrate/codec/src/slicable.rs +++ b/substrate/substrate/codec/src/slicable.rs @@ -24,6 +24,16 @@ use super::joiner::Joiner; pub trait Input { /// Read into the provided input slice. Returns the number of bytes read. fn read(&mut self, into: &mut [u8]) -> usize; + + /// Read a single byte from the input. + fn read_byte(&mut self) -> Option { + let mut buf = [0u8]; + match self.read(&mut buf[..]) { + 0 => None, + 1 => Some(buf[0]), + _ => unreachable!(), + } + } } impl<'a> Input for &'a [u8] { @@ -51,29 +61,25 @@ pub trait Slicable: Sized { } } -/// Trait to mark that a type is not trivially (essentially "in place") serialisable. -// TODO: under specialization, remove this and simply specialize in place serializable types. -pub trait NonTrivialSlicable: Slicable {} - impl Slicable for Option { fn decode(input: &mut I) -> Option { - u8::decode(input).and_then(|v| match v { + match input.read_byte()? { 0 => Some(Some(false)), 1 => Some(Some(true)), 2 => Some(None), _ => None, - }) + } } fn using_encoded R>(&self, f: F) -> R { - match *self { + f(&[match *self { Some(false) => 0u8, Some(true) => 1u8, None => 2u8, - }.using_encoded(f) + }]) } } -impl NonTrivialSlicable for Option {} + impl Slicable for Box { fn decode(input: &mut I) -> Option { @@ -108,89 +114,7 @@ impl Slicable for Vec { } } -// TODO: implement for all primitives. -impl Slicable for Vec { - fn decode(input: &mut I) -> Option { - u32::decode(input).and_then(move |len| { - let len = len as usize; - let mut vec = Vec::with_capacity(len); - for _ in 0..len { - vec.push(u64::decode(input)?); - } - Some(vec) - }) - } - - fn encode(&self) -> Vec { - let len = self.len(); - assert!(len <= u32::max_value() as usize, "Attempted to serialize vec with too many elements."); - - // TODO: optimise - no need to create a new vec and copy - can just reserve and encode in place - let mut r: Vec = Vec::new().and(&(len as u32)); - for i in self.iter() { - r.extend(&i.encode()); - } - r - } -} - -// TODO: use a BitVec-like representation. -impl Slicable for Vec { - fn decode(input: &mut I) -> Option { - >::decode(input).map(|a| a.into_iter().map(|b| b != 0).collect()) - } - - fn encode(&self) -> Vec { - >::encode(&self.iter().map(|&b| if b {1} else {0}).collect()) - } -} - -macro_rules! impl_vec_simple_array { - ($($size:expr),*) => { - $( - impl Slicable for Vec<[T; $size]> - where [T; $size]: Slicable - { - fn decode(input: &mut I) -> Option { - u32::decode(input).and_then(move |len| { - let mut r = Vec::with_capacity(len as usize); - for _ in 0..len { - r.push(match Slicable::decode(input) { - Some(x) => x, - None => return None, - }); - } - - Some(r) - }) - } - - fn using_encoded R>(&self, f: F) -> R { - f(&self.encode()) - } - - fn encode(&self) -> Vec { - use rstd::iter::Extend; - - let len = self.len(); - assert!(len <= u32::max_value() as usize, "Attempted to serialize vec with too many elements."); - - let mut r: Vec = Vec::new().and(&(len as u32)); - for item in self { - r.extend(item.encode()); - } - r - } - } - )* - } -} - -impl_vec_simple_array!(1, 2, 4, 8, 16, 32, 64); - -impl NonTrivialSlicable for Vec where Vec: Slicable {} - -impl Slicable for Vec { +impl Slicable for Vec { fn decode(input: &mut I) -> Option { u32::decode(input).and_then(move |len| { let mut r = Vec::with_capacity(len as usize); @@ -219,6 +143,8 @@ impl Slicable for Vec { } } + + impl Slicable for () { fn decode(_: &mut I) -> Option<()> { Some(()) @@ -248,7 +174,7 @@ macro_rules! tuple_impl { } } - impl<$one: NonTrivialSlicable> NonTrivialSlicable for ($one,) { } + }; ($first:ident, $($rest:ident,)+) => { impl<$first: Slicable, $($rest: Slicable),+> @@ -284,11 +210,6 @@ macro_rules! tuple_impl { } } - impl<$first: Slicable, $($rest: Slicable),+> - NonTrivialSlicable - for ($first, $($rest),+) - { } - tuple_impl!($($rest,)+); } } @@ -297,7 +218,7 @@ macro_rules! tuple_impl { mod inner_tuple_impl { use rstd::vec::Vec; - use super::{Input, Slicable, NonTrivialSlicable}; + use super::{Input, Slicable}; tuple_impl!(A, B, C, D, E, F, G, H, I, J, K,); } @@ -399,7 +320,7 @@ macro_rules! impl_non_endians { } impl_endians!(u16, u32, u64, usize, i16, i32, i64, isize); -impl_non_endians!(u8, i8, [u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], +impl_non_endians!(i8, [u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], [u8; 10], [u8; 12], [u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40], [u8; 48], [u8; 56], [u8; 64], [u8; 80], [u8; 96], [u8; 112], [u8; 128], bool); diff --git a/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index 5be7858aaa1317913e799697cff9d2d4a4ebae24..cbc81694c0999d1af58aaad064d227df8200e417 100644 GIT binary patch literal 14298 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 C);o&; literal 14487 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 literal 15588 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 diff --git a/substrate/substrate/network/src/test/mod.rs b/substrate/substrate/network/src/test/mod.rs index 721640f988..52bb5d57ff 100644 --- a/substrate/substrate/network/src/test/mod.rs +++ b/substrate/substrate/network/src/test/mod.rs @@ -162,7 +162,7 @@ impl Peer { } fn justify(header: &primitives::block::Header) -> bft::UncheckedJustification { - let hash = header.hash(); + let hash = header.blake2_256().into(); let authorities = vec![ Keyring::Alice.into() ]; bft::UncheckedJustification { diff --git a/substrate/substrate/primitives/src/bft.rs b/substrate/substrate/primitives/src/bft.rs index 717ff8a424..43f8903aae 100644 --- a/substrate/substrate/primitives/src/bft.rs +++ b/substrate/substrate/primitives/src/bft.rs @@ -23,7 +23,7 @@ use ::{AuthorityId, Signature}; #[derive(Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug))] -#[repr(u8)] +#[repr(i8)] enum ActionKind { Propose = 1, ProposeHeader = 2, @@ -83,27 +83,27 @@ impl Slicable for Action { } fn decode(value: &mut I) -> Option { - match u8::decode(value) { - Some(x) if x == ActionKind::Propose as u8 => { + match i8::decode(value) { + Some(x) if x == ActionKind::Propose as i8 => { let (round, block) = try_opt!(Slicable::decode(value)); Some(Action::Propose(round, block)) } - Some(x) if x == ActionKind::ProposeHeader as u8 => { + Some(x) if x == ActionKind::ProposeHeader as i8 => { let (round, hash) = try_opt!(Slicable::decode(value)); Some(Action::ProposeHeader(round, hash)) } - Some(x) if x == ActionKind::Prepare as u8 => { + Some(x) if x == ActionKind::Prepare as i8 => { let (round, hash) = try_opt!(Slicable::decode(value)); Some(Action::Prepare(round, hash)) } - Some(x) if x == ActionKind::Commit as u8 => { + Some(x) if x == ActionKind::Commit as i8 => { let (round, hash) = try_opt!(Slicable::decode(value)); Some(Action::Commit(round, hash)) } - Some(x) if x == ActionKind::AdvanceRound as u8 => { + Some(x) if x == ActionKind::AdvanceRound as i8 => { Slicable::decode(value).map(Action::AdvanceRound) } _ => None, @@ -169,7 +169,7 @@ impl Slicable for Justification { } // single-byte code to represent misbehavior kind. -#[repr(u8)] +#[repr(i8)] enum MisbehaviorCode { /// BFT: double prepare. BftDoublePrepare = 0x11, @@ -178,7 +178,7 @@ enum MisbehaviorCode { } impl MisbehaviorCode { - fn from_u8(x: u8) -> Option { + fn from_i8(x: i8) -> Option { match x { 0x11 => Some(MisbehaviorCode::BftDoublePrepare), 0x12 => Some(MisbehaviorCode::BftDoubleCommit), @@ -220,7 +220,7 @@ impl Slicable for MisbehaviorReport { match self.misbehavior { MisbehaviorKind::BftDoublePrepare(ref round, (ref h_a, ref s_a), (ref h_b, ref s_b)) => { - (MisbehaviorCode::BftDoublePrepare as u8).using_encoded(|s| v.extend(s)); + (MisbehaviorCode::BftDoublePrepare as i8).using_encoded(|s| v.extend(s)); round.using_encoded(|s| v.extend(s)); h_a.using_encoded(|s| v.extend(s)); s_a.using_encoded(|s| v.extend(s)); @@ -228,7 +228,7 @@ impl Slicable for MisbehaviorReport { s_b.using_encoded(|s| v.extend(s)); } MisbehaviorKind::BftDoubleCommit(ref round, (ref h_a, ref s_a), (ref h_b, ref s_b)) => { - (MisbehaviorCode::BftDoubleCommit as u8).using_encoded(|s| v.extend(s)); + (MisbehaviorCode::BftDoubleCommit as i8).using_encoded(|s| v.extend(s)); round.using_encoded(|s| v.extend(s)); h_a.using_encoded(|s| v.extend(s)); s_a.using_encoded(|s| v.extend(s)); @@ -245,7 +245,7 @@ impl Slicable for MisbehaviorReport { let parent_number = ::block::Number::decode(input)?; let target = AuthorityId::decode(input)?; - let misbehavior = match u8::decode(input).and_then(MisbehaviorCode::from_u8)? { + let misbehavior = match i8::decode(input).and_then(MisbehaviorCode::from_i8)? { MisbehaviorCode::BftDoublePrepare => { MisbehaviorKind::BftDoublePrepare( u32::decode(input)?, diff --git a/substrate/substrate/primitives/src/block.rs b/substrate/substrate/primitives/src/block.rs index 0fd55bca40..6f1ec91ab7 100644 --- a/substrate/substrate/primitives/src/block.rs +++ b/substrate/substrate/primitives/src/block.rs @@ -21,7 +21,7 @@ use rstd::vec::Vec; #[cfg(feature = "std")] use bytes; use Hash; -use codec::{Input, Slicable, NonTrivialSlicable}; +use codec::{Input, Slicable}; /// Used to refer to a block number. pub type Number = u64; @@ -47,10 +47,6 @@ impl Slicable for Transaction { } } -impl NonTrivialSlicable for Transaction { } - - - /// Execution log (event) #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] @@ -66,10 +62,6 @@ impl Slicable for Log { } } -impl NonTrivialSlicable for Log { } - - - /// The digest of a block, useful for light-clients. #[derive(Clone, Default, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] @@ -88,11 +80,9 @@ impl Slicable for Digest { } } -impl NonTrivialSlicable for Digest { } - /// Generic types to be specialised later. pub mod generic { - use super::{Header, Slicable, Input, NonTrivialSlicable, Vec}; + use super::{Header, Slicable, Input, Vec}; /// A Block - this is generic for later specialisation in particular runtimes. #[derive(PartialEq, Eq, Clone)] @@ -107,8 +97,8 @@ pub mod generic { impl Slicable for Block where Vec: Slicable { fn decode(input: &mut I) -> Option { Some(Block { - header: try_opt!(Slicable::decode(input)), - transactions: try_opt!(Slicable::decode(input)), + header: Slicable::decode(input)?, + transactions: Slicable::decode(input)?, }) } @@ -119,8 +109,6 @@ pub mod generic { v } } - - impl NonTrivialSlicable for Block where Vec: Slicable { } } /// The body of a block is just a bunch of transactions. @@ -162,22 +150,16 @@ impl Header { digest: Default::default(), } } - - /// Get the blake2-256 hash of this header. - #[cfg(feature = "std")] - pub fn hash(&self) -> HeaderHash { - ::hashing::blake2_256(Slicable::encode(self).as_slice()).into() - } } impl Slicable for Header { fn decode(input: &mut I) -> Option { Some(Header { - parent_hash: try_opt!(Slicable::decode(input)), - number: try_opt!(Slicable::decode(input)), - state_root: try_opt!(Slicable::decode(input)), - transaction_root: try_opt!(Slicable::decode(input)), - digest: try_opt!(Slicable::decode(input)), + parent_hash: Slicable::decode(input)?, + number: Slicable::decode(input)?, + state_root: Slicable::decode(input)?, + transaction_root: Slicable::decode(input)?, + digest: Slicable::decode(input)?, }) } diff --git a/substrate/substrate/primitives/src/lib.rs b/substrate/substrate/primitives/src/lib.rs index ecf187cf91..626efbf787 100644 --- a/substrate/substrate/primitives/src/lib.rs +++ b/substrate/substrate/primitives/src/lib.rs @@ -91,7 +91,7 @@ mod tests; pub use self::hash::{H160, H256}; pub use self::uint::{U256, U512}; -pub use block::{Block, Header}; +pub use block::{Block, Header, Digest}; /// General hash type. pub type Hash = H256; diff --git a/substrate/substrate/runtime-io/src/lib.rs b/substrate/substrate/runtime-io/src/lib.rs index 5a165c62e5..a2eb13dafd 100644 --- a/substrate/substrate/runtime-io/src/lib.rs +++ b/substrate/substrate/runtime-io/src/lib.rs @@ -29,3 +29,37 @@ include!("../with_std.rs"); #[cfg(not(feature = "std"))] include!("../without_std.rs"); + +/// Abstraction around hashing +pub trait Hashing { + /// The hash type produced. + type Output; + + /// Produce the hash of some byte-slice. + fn hash(s: &[u8]) -> Self::Output; + /// Produce the hash of some codec-encodable value. + fn hash_of(s: &S) -> Self::Output { + codec::Slicable::using_encoded(s, Self::hash) + } + /// Produce the patricia-trie root of a mapping from indices to byte slices. + fn enumerated_trie_root(items: &[&[u8]]) -> Self::Output; + + /// Acquire the global storage root. + fn storage_root() -> Self::Output; +} + +/// Blake2-256 Hashing implementation. +pub struct BlakeTwo256; + +impl Hashing for BlakeTwo256 { + type Output = primitives::H256; + fn hash(s: &[u8]) -> Self::Output { + blake2_256(s).into() + } + fn enumerated_trie_root(items: &[&[u8]]) -> Self::Output { + enumerated_trie_root(items).into() + } + fn storage_root() -> Self::Output { + storage_root().into() + } +} diff --git a/substrate/substrate/runtime-io/with_std.rs b/substrate/substrate/runtime-io/with_std.rs index 8c1bad8d7f..5fda5181b0 100644 --- a/substrate/substrate/runtime-io/with_std.rs +++ b/substrate/substrate/runtime-io/with_std.rs @@ -17,8 +17,10 @@ #[macro_use] extern crate environmental; -extern crate substrate_state_machine; +#[cfg_attr(test, macro_use)] extern crate substrate_primitives as primitives; + +extern crate substrate_state_machine; extern crate triehash; extern crate ed25519; @@ -156,12 +158,6 @@ macro_rules! impl_stubs { mod std_tests { use super::*; - macro_rules! map { - ($( $name:expr => $value:expr ),*) => ( - vec![ $( ( $name, $value ) ),* ].into_iter().collect() - ) - } - #[test] fn storage_works() { let mut t = TestExternalities::new(); diff --git a/substrate/substrate/runtime-std/build.rs b/substrate/substrate/runtime-std/build.rs index 35eb154f3a..55688bad9c 100644 --- a/substrate/substrate/runtime-std/build.rs +++ b/substrate/substrate/runtime-std/build.rs @@ -4,11 +4,11 @@ extern crate rustc_version; use rustc_version::{version, version_meta, Channel}; fn main() { - // Assert we haven't travelled back in time - assert!(version().unwrap().major >= 1); + // Assert we haven't travelled back in time + assert!(version().unwrap().major >= 1); - // Set cfg flags depending on release channel - if let Channel::Nightly = version_meta().unwrap().channel { - println!("cargo:rustc-cfg=feature=\"nightly\""); - } + // Set cfg flags depending on release channel + if let Channel::Nightly = version_meta().unwrap().channel { + println!("cargo:rustc-cfg=feature=\"nightly\""); + } } diff --git a/substrate/substrate/runtime-std/src/lib.rs b/substrate/substrate/runtime-std/src/lib.rs index 0128ebd31a..b98bfb43c3 100644 --- a/substrate/substrate/runtime-std/src/lib.rs +++ b/substrate/substrate/runtime-std/src/lib.rs @@ -26,6 +26,13 @@ #![cfg_attr(feature = "std", doc = "Polkadot runtime standard library as compiled when linked with Rust's standard library.")] #![cfg_attr(not(feature = "std"), doc = "Polkadot's runtime standard library as compiled without Rust's standard library.")] +#[macro_export] +macro_rules! map { + ($( $name:expr => $value:expr ),*) => ( + vec![ $( ( $name, $value ) ),* ].into_iter().collect() + ) +} + #[cfg(feature = "std")] include!("../with_std.rs"); @@ -38,4 +45,6 @@ include!("../without_std.rs"); pub mod prelude { pub use ::vec::Vec; pub use ::boxed::Box; + pub use ::cmp::{Eq, PartialEq}; + pub use ::clone::Clone; } diff --git a/substrate/substrate/runtime-std/with_std.rs b/substrate/substrate/runtime-std/with_std.rs index 2cfd266f48..92f6654bbb 100644 --- a/substrate/substrate/runtime-std/with_std.rs +++ b/substrate/substrate/runtime-std/with_std.rs @@ -17,15 +17,19 @@ pub use std::borrow; pub use std::boxed; pub use std::cell; +pub use std::clone; pub use std::cmp; pub use std::fmt; pub use std::iter; +pub use std::marker; pub use std::mem; +pub use std::num; pub use std::ops; pub use std::ptr; pub use std::rc; pub use std::slice; pub use std::vec; + pub mod collections { pub use std::collections::btree_map; } diff --git a/substrate/substrate/runtime-std/without_std.rs b/substrate/substrate/runtime-std/without_std.rs index 5fc2d7526b..2d05e93887 100644 --- a/substrate/substrate/runtime-std/without_std.rs +++ b/substrate/substrate/runtime-std/without_std.rs @@ -25,16 +25,20 @@ extern crate pwasm_alloc; pub use alloc::boxed; pub use alloc::rc; pub use alloc::vec; -pub mod collections { - pub use alloc::btree_map; -} pub use core::borrow; pub use core::cell; +pub use core::clone; pub use core::cmp; +pub use core::fmt; pub use core::intrinsics; pub use core::iter; +pub use core::marker; pub use core::mem; +pub use core::num; pub use core::ops; pub use core::ptr; pub use core::slice; -pub use core::fmt; + +pub mod collections { + pub use alloc::btree_map; +} diff --git a/substrate/substrate/runtime-support/Cargo.toml b/substrate/substrate/runtime-support/Cargo.toml index 61a4b064c4..bef5065ef0 100644 --- a/substrate/substrate/runtime-support/Cargo.toml +++ b/substrate/substrate/runtime-support/Cargo.toml @@ -6,9 +6,10 @@ authors = ["Parity Technologies "] [dependencies] ed25519 = { path = "../ed25519", optional = true } hex-literal = { version = "0.1.0", optional = true } +serde = { version = "1.0", default_features = false } +serde_derive = { version = "1.0", optional = true } substrate-runtime-std = { path = "../runtime-std", default_features = false } substrate-runtime-io = { path = "../runtime-io", default_features = false } -environmental = { path = "../environmental", optional = true } substrate-primitives = { path = "../primitives", default_features = false } substrate-codec = { path = "../codec", default_features = false } @@ -17,7 +18,8 @@ default = ["std"] std = [ "ed25519", "hex-literal", - "environmental", + "serde/std", + "serde_derive", "substrate-primitives/std", "substrate-runtime-io/std", "substrate-codec/std", diff --git a/substrate/substrate/runtime-support/src/dispatch.rs b/substrate/substrate/runtime-support/src/dispatch.rs new file mode 100644 index 0000000000..d5d9c97f3b --- /dev/null +++ b/substrate/substrate/runtime-support/src/dispatch.rs @@ -0,0 +1,510 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Demo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Demo. If not, see . + +//! Dispatch system. Just dispatches calls. + +pub use rstd::prelude::{Vec, Clone, Eq, PartialEq}; +#[cfg(feature = "std")] +pub use std::fmt; +pub use rstd::marker::PhantomData; +#[cfg(feature = "std")] +use serde; +pub use codec::{Slicable, Input}; + +pub trait Dispatchable { + type Trait; + fn dispatch(self); +} + +pub trait AuxDispatchable { + type Aux; + type Trait; + fn dispatch(self, aux: &Self::Aux); +} + +#[cfg(feature = "std")] +pub trait AuxCallable { + type Call: AuxDispatchable + Slicable + ::serde::Serialize + Clone + PartialEq + Eq; +} +#[cfg(not(feature = "std"))] +pub trait AuxCallable { + type Call: AuxDispatchable + Slicable + Clone + PartialEq + Eq; +} + +#[cfg(feature = "std")] +pub trait Callable { + type Call: Dispatchable + Slicable + ::serde::Serialize + Clone + PartialEq + Eq; +} +#[cfg(not(feature = "std"))] +pub trait Callable { + type Call: Dispatchable + Slicable + Clone + PartialEq + Eq; +} + +#[cfg(feature = "std")] +pub trait Parameter: Slicable + serde::Serialize + Clone + Eq + fmt::Debug {} + +#[cfg(feature = "std")] +impl Parameter for T where T: Slicable + serde::Serialize + Clone + Eq + fmt::Debug {} + +#[cfg(not(feature = "std"))] +pub trait Parameter: Slicable + Clone + Eq {} + +#[cfg(not(feature = "std"))] +impl Parameter for T where T: Slicable + Clone + Eq {} + + +/// Declare a struct for this module, then implement dispatch logic to create a pairing of several +/// dispatch traits and enums. +#[macro_export] +macro_rules! decl_module { + ( + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>; + $($rest:tt)* + ) => { + pub struct $mod_type<$trait_instance: $trait_name>($crate::dispatch::PhantomData<$trait_instance>); + decl_dispatch! { + impl for $mod_type<$trait_instance: $trait_name>; + $($rest)* + } + }; + ( + struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>; + $($rest:tt)* + ) => { + struct $mod_type<$trait_instance: $trait_name>($crate::dispatch::PhantomData<$trait_instance>); + decl_dispatch! { + impl for $mod_type<$trait_instance: $trait_name>; + $($rest)* + } + } +} + +/// Implement several dispatch modules to create a pairing of a dispatch trait and enum. +#[macro_export] +macro_rules! decl_dispatch { + // WITHOUT AUX + ( + impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; + pub enum $call_type:ident { + $( + fn $fn_name:ident( + $( + $param_name:ident : $param:ty + ),* + ) + = $id:expr ; + )* + } + $($rest:tt)* + ) => { + __decl_dispatch_module_without_aux! { + impl for $mod_type<$trait_instance: $trait_name>; + pub enum $call_type; + $( + fn $fn_name( $( $param_name: $param ),* ) = $id; + )* + } + decl_dispatch! { + impl for $mod_type<$trait_instance: $trait_name>; + $($rest)* + } + }; + // WITH AUX + ( + impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; + pub enum $call_type:ident where aux: $aux_type:ty { + $( + fn $fn_name:ident(aux + $( + , $param_name:ident : $param:ty + )* + ) + = $id:expr ; + )* + } + $($rest:tt)* + ) => { + __decl_dispatch_module_with_aux! { + impl for $mod_type<$trait_instance: $trait_name>; + pub enum $call_type where aux: $aux_type; + $( + fn $fn_name(aux $(, $param_name: $param )*)= $id; + )* + } + decl_dispatch! { + impl for $mod_type<$trait_instance: $trait_name>; + $($rest)* + } + }; + // BASE CASE + ( + impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; + ) => { + impl<$trait_instance: $trait_name> $mod_type<$trait_instance> { + pub fn aux_dispatch>(d: D, aux: &D::Aux) { + d.dispatch(aux); + } + pub fn dispatch>(d: D) { + d.dispatch(); + } + } + } +} + +#[macro_export] +/// Implement a single dispatch modules to create a pairing of a dispatch trait and enum. +macro_rules! __decl_dispatch_module_without_aux { + ( + impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; + pub enum $call_type:ident; + $( + fn $fn_name:ident( + $( + $param_name:ident : $param:ty + ),* + ) + = $id:expr ; + )* + ) => { + __decl_dispatch_module_common! { + impl for $mod_type<$trait_instance: $trait_name>; + pub enum $call_type; + $( fn $fn_name( $( $param_name : $param ),* ) = $id ; )* + } + impl<$trait_instance: $trait_name> $crate::dispatch::Dispatchable + for $call_type<$trait_instance> + { + type Trait = $trait_instance; + fn dispatch(self) { + match self { + $( + $call_type::$fn_name( $( $param_name ),* ) => + <$mod_type<$trait_instance>>::$fn_name( $( $param_name ),* ), + )* + $call_type::__PhantomItem(_) => { panic!("__PhantomItem should never be used.") }, + } + } + } + impl<$trait_instance: $trait_name> $crate::dispatch::Callable + for $mod_type<$trait_instance> + { + type Call = $call_type<$trait_instance>; + } + } +} + +#[macro_export] +/// Implement a single dispatch modules to create a pairing of a dispatch trait and enum. +macro_rules! __decl_dispatch_module_with_aux { + ( + impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; + pub enum $call_type:ident where aux: $aux_type:ty; + $( + fn $fn_name:ident(aux + $( + , $param_name:ident : $param:ty + )* + ) + = $id:expr ; + )* + ) => { + __decl_dispatch_module_common! { + impl for $mod_type<$trait_instance: $trait_name>; + pub enum $call_type; + $( fn $fn_name( $( $param_name : $param ),* ) = $id ; )* + } + impl<$trait_instance: $trait_name> $crate::dispatch::AuxDispatchable + for $call_type<$trait_instance> + { + type Trait = $trait_instance; + type Aux = $aux_type; + fn dispatch(self, aux: &Self::Aux) { + match self { + $( + $call_type::$fn_name( $( $param_name ),* ) => + <$mod_type<$trait_instance>>::$fn_name( aux $(, $param_name )* ), + )* + $call_type::__PhantomItem(_) => { panic!("__PhantomItem should never be used.") }, + } + } + } + impl<$trait_instance: $trait_name> $crate::dispatch::AuxCallable + for $mod_type<$trait_instance> + { + type Call = $call_type<$trait_instance>; + } + }; +} + +#[macro_export] +/// Implement a single dispatch modules to create a pairing of a dispatch trait and enum. +macro_rules! __decl_dispatch_module_common { + ( + impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; + pub enum $call_type:ident; + $( + fn $fn_name:ident( + $( + $param_name:ident : $param:ty + ),* + ) + = $id:expr ; + )* + ) => { + #[cfg_attr(feature = "std", derive(Serialize))] + #[allow(missing_docs)] + pub enum $call_type<$trait_instance: $trait_name> { + __PhantomItem($crate::dispatch::PhantomData<$trait_instance>), + $( + #[allow(non_camel_case_types)] + $fn_name ( $( $param ),* ), + )* + } + + // manual implementation of clone/eq/partialeq because using derive erroneously requires + // clone/eq/partialeq from T. + impl<$trait_instance: $trait_name> $crate::dispatch::Clone + for $call_type<$trait_instance> + { + fn clone(&self) -> Self { + match *self { + $( + $call_type::$fn_name( $( ref $param_name ),* ) => + $call_type::$fn_name( $( $param_name.clone() ),* ) + ,)* + $call_type::__PhantomItem(_) => unreachable!(), + } + } + } + impl<$trait_instance: $trait_name> $crate::dispatch::PartialEq + for $call_type<$trait_instance> + { + fn eq(&self, other: &Self) -> bool { + match *self { + $( + $call_type::$fn_name( $( ref $param_name ),* ) => { + let self_params = ( $( $param_name, )* ); + if let $call_type::$fn_name( $( ref $param_name ),* ) = *other { + self_params == ( $( $param_name, )* ) + } else { + if let $call_type::__PhantomItem(_) = *other { + unreachable!() + } else { + false + } + } + } + )* + $call_type::__PhantomItem(_) => unreachable!(), + } + } + } + impl<$trait_instance: $trait_name> $crate::dispatch::Eq + for $call_type<$trait_instance> + {} + + #[cfg(feature = "std")] + impl<$trait_instance: $trait_name> $crate::dispatch::fmt::Debug + for $call_type<$trait_instance> + { + fn fmt(&self, f: &mut $crate::dispatch::fmt::Formatter) -> Result<(), $crate::dispatch::fmt::Error> { + match *self { + $( + $call_type::$fn_name( $( ref $param_name ),* ) => + write!(f, "{}{:?}", + stringify!($fn_name), + ( $( $param_name.clone(), )* ) + ) + ,)* + $call_type::__PhantomItem(_) => unreachable!(), + } + } + } + + impl<$trait_instance: $trait_name> $crate::dispatch::Slicable for $call_type<$trait_instance> { + fn decode(input: &mut I) -> Option { + match input.read_byte()? { + $( + $id => { + $( + let $param_name = $crate::dispatch::Slicable::decode(input)?; + )* + Some($call_type:: $fn_name( $( $param_name ),* )) + } + )* + _ => None, + } + } + + fn encode(&self) -> $crate::dispatch::Vec { + let mut v = $crate::dispatch::Vec::new(); + match *self { + $( + $call_type::$fn_name( + $( + ref $param_name + ),* + ) => { + v.push($id as u8); + $( + $param_name.using_encoded(|s| v.extend(s)); + )* + } + )* + $call_type::__PhantomItem(_) => unreachable!(), + } + v + } + + fn using_encoded R>(&self, f: F) -> R { + f(self.encode().as_slice()) + } + } + + } +} + +pub trait IsSubType { + fn is_sub_type(&self) -> Option<&::Call>; +} +pub trait IsAuxSubType { + fn is_aux_sub_type(&self) -> Option<&::Call>; +} + +/// Implement a meta-dispatch module to dispatch to other dispatchers. +#[macro_export] +macro_rules! impl_outer_dispatch { + () => (); + ( + pub enum $call_type:ident where aux: $aux:ty { + $( + $camelcase:ident = $id:expr, + )* + } + $( $rest:tt )* + ) => { + #[derive(Clone, PartialEq, Eq)] + #[cfg_attr(feature = "std", derive(Serialize, Debug))] + #[allow(missing_docs)] + pub enum $call_type { + $( + $camelcase ( <$camelcase as $crate::dispatch::AuxCallable>::Call ) + ,)* + } + impl_outer_dispatch_common! { $call_type, $($camelcase = $id,)* } + impl $crate::dispatch::AuxDispatchable for $call_type { + type Aux = $aux; + type Trait = $call_type; + fn dispatch(self, aux: &$aux) { + match self { + $( + $call_type::$camelcase(call) => call.dispatch(&aux), + )* + } + } + } + $( + impl $crate::dispatch::IsAuxSubType<$camelcase> for $call_type { + fn is_aux_sub_type(&self) -> Option<&<$camelcase as $crate::dispatch::AuxCallable>::Call> { + if let $call_type::$camelcase ( ref r ) = *self { + Some(r) + } else { + None + } + } + } + )* + impl_outer_dispatch!{ $($rest)* } + }; + ( + pub enum $call_type:ident { + $( + $camelcase:ident = $id:expr, + )* + } + $( $rest:tt )* + ) => { + #[derive(Clone, PartialEq, Eq)] + #[cfg_attr(feature = "std", derive(Serialize, Debug))] + #[allow(missing_docs)] + pub enum $call_type { + $( + $camelcase ( <$camelcase as $crate::dispatch::Callable>::Call ) + ,)* + } + impl_outer_dispatch_common! { $call_type, $($camelcase = $id,)* } + impl $crate::dispatch::Dispatchable for $call_type { + type Trait = $call_type; + fn dispatch(self) { + match self { + $( + $call_type::$camelcase(call) => call.dispatch(), + )* + } + } + } + $( + impl $crate::dispatch::IsSubType<$camelcase> for $call_type { + fn is_sub_type(&self) -> Option<&<$camelcase as $crate::dispatch::Callable>::Call> { + if let $call_type::$camelcase ( ref r ) = *self { + Some(r) + } else { + None + } + } + } + )* + impl_outer_dispatch!{ $($rest)* } + } +} + +/// Implement a meta-dispatch module to dispatch to other dispatchers. +#[macro_export] +macro_rules! impl_outer_dispatch_common { + ( + $call_type:ident, $( $camelcase:ident = $id:expr, )* + ) => { + impl $crate::dispatch::Slicable for $call_type { + fn decode(input: &mut I) -> Option { + match input.read_byte()? { + $( + $id => + Some($call_type::$camelcase( $crate::dispatch::Slicable::decode(input)? )), + )* + _ => None, + } + } + + fn encode(&self) -> $crate::dispatch::Vec { + let mut v = $crate::dispatch::Vec::new(); + match *self { + $( + $call_type::$camelcase( ref sub ) => { + v.push($id as u8); + sub.using_encoded(|s| v.extend(s)); + } + )* + } + v + } + + fn using_encoded R>(&self, f: F) -> R { + f(self.encode().as_slice()) + } + } + + } +} diff --git a/substrate/substrate/runtime-support/src/lib.rs b/substrate/substrate/runtime-support/src/lib.rs index b3aea78cbc..12894aa808 100644 --- a/substrate/substrate/runtime-support/src/lib.rs +++ b/substrate/substrate/runtime-support/src/lib.rs @@ -18,6 +18,16 @@ #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(feature = "std")] +extern crate serde; + +#[cfg(feature = "std")] +#[allow(unused_imports)] #[macro_use] // can be removed when fixed: https://github.com/rust-lang/rust/issues/43497 +extern crate serde_derive; + +#[cfg(feature = "std")] +pub use serde_derive::*; + extern crate substrate_runtime_std as rstd; extern crate substrate_runtime_io as runtime_io; extern crate substrate_primitives as primitives; @@ -26,8 +36,10 @@ extern crate substrate_primitives as primitives; pub extern crate substrate_codec as codec; pub use self::storage::generator::Storage as GenericStorage; +pub mod dispatch; pub mod storage; mod hashable; pub use self::storage::{StorageVec, StorageList, StorageValue, StorageMap}; pub use self::hashable::Hashable; +pub use self::dispatch::{Parameter, Dispatchable, Callable, AuxDispatchable, AuxCallable, IsSubType, IsAuxSubType}; diff --git a/substrate/substrate/runtime-support/src/storage/generator.rs b/substrate/substrate/runtime-support/src/storage/generator.rs index b77b58d418..d91e860f9e 100644 --- a/substrate/substrate/runtime-support/src/storage/generator.rs +++ b/substrate/substrate/runtime-support/src/storage/generator.rs @@ -50,6 +50,8 @@ use codec; use rstd::vec::Vec; #[doc(hidden)] pub use rstd::borrow::Borrow; +#[doc(hidden)] +pub use rstd::marker::PhantomData; /// Abstraction around storage. pub trait Storage { @@ -384,52 +386,52 @@ macro_rules! storage_items { }; // maps - ($name:ident : $prefix:expr => map [$kty: ty => $ty:ty]; $($t:tt)*) => { + ($name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { __storage_items_internal!(() () (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; - (pub $name:ident : $prefix:expr => map [$kty: ty => $ty:ty]; $($t:tt)*) => { + (pub $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { __storage_items_internal!((pub) () (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; - ($name:ident : $prefix:expr => default map [$kty: ty => $ty:ty]; $($t:tt)*) => { + ($name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { __storage_items_internal!(() () ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; - (pub $name:ident : $prefix:expr => default map [$kty: ty => $ty:ty]; $($t:tt)*) => { + (pub $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { __storage_items_internal!((pub) () ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; - ($name:ident : $prefix:expr => required map [$kty: ty => $ty:ty]; $($t:tt)*) => { + ($name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { __storage_items_internal!(() () ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; - (pub $name:ident : $prefix:expr => required map [$kty: ty => $ty:ty]; $($t:tt)*) => { + (pub $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { __storage_items_internal!((pub) () ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; - ($name:ident get($getfn:ident) : $prefix:expr => map [$kty: ty => $ty:ty]; $($t:tt)*) => { + ($name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { __storage_items_internal!(() ($getfn) (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; - (pub $name:ident get($getfn:ident) : $prefix:expr => map [$kty: ty => $ty:ty]; $($t:tt)*) => { + (pub $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { __storage_items_internal!((pub) ($getfn) (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; - ($name:ident get($getfn:ident) : $prefix:expr => default map [$kty: ty => $ty:ty]; $($t:tt)*) => { + ($name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { __storage_items_internal!(() ($getfn) ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; - (pub $name:ident get($getfn:ident) : $prefix:expr => default map [$kty: ty => $ty:ty]; $($t:tt)*) => { + (pub $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { __storage_items_internal!((pub) ($getfn) ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; - ($name:ident get($getfn:ident) : $prefix:expr => required map [$kty: ty => $ty:ty]; $($t:tt)*) => { + ($name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { __storage_items_internal!(() ($getfn) ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; - (pub $name:ident get($getfn:ident) : $prefix:expr => required map [$kty: ty => $ty:ty]; $($t:tt)*) => { + (pub $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { __storage_items_internal!((pub) ($getfn) ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; @@ -447,6 +449,544 @@ macro_rules! storage_items { () => () } +#[macro_export] +#[doc(hidden)] +macro_rules! __decl_storage_item { + // generator for values. + (($($vis:tt)*) ($traittype:ident as $traitinstance:ident) ($get_fn:ident) ($gettype:ty) ($getter:ident) ($taker:ident) $name:ident : $key:expr => $ty:ty) => { + __decl_storage_item!{ ($($vis)*) ($traittype as $traitinstance) () ($gettype) ($getter) ($taker) $name : $key => $ty } + }; + (($($vis:tt)*) ($traittype:ident as $traitinstance:ident) () ($gettype:ty) ($getter:ident) ($taker:ident) $name:ident : $key:expr => $ty:ty) => { + $($vis)* struct $name<$traitinstance: $traittype>($crate::storage::generator::PhantomData<$traitinstance>); + + impl<$traitinstance: $traittype> $crate::storage::generator::StorageValue<$ty> for $name<$traitinstance> { + type Query = $gettype; + + /// Get the storage key. + fn key() -> &'static [u8] { + $key + } + + /// Load the value from the provided storage instance. + fn get(storage: &S) -> Self::Query { + storage.$getter($key) + } + + /// Take a value from storage, removing it afterwards. + fn take(storage: &S) -> Self::Query { + storage.$taker($key) + } + } + }; + // generator for maps. + (($($vis:tt)*) ($traittype:ident as $traitinstance:ident) ($get_fn:ident) ($gettype:ty) ($getter:ident) ($taker:ident) $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]) => { + __decl_storage_item!{ ($($vis)*) ($traittype as $traitinstance) () ($gettype) ($getter) ($taker) $name : $prefix => map [$kty => $ty] } + }; + (($($vis:tt)*) ($traittype:ident as $traitinstance:ident) () ($gettype:ty) ($getter:ident) ($taker:ident) $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]) => { + $($vis)* struct $name<$traitinstance: $traittype>($crate::storage::generator::PhantomData<$traitinstance>); + + impl<$traitinstance: $traittype> $crate::storage::generator::StorageMap<$kty, $ty> for $name<$traitinstance> { + type Query = $gettype; + + /// Get the prefix key in storage. + fn prefix() -> &'static [u8] { + $prefix + } + + /// Get the storage key used to fetch a value corresponding to a specific key. + fn key_for(x: &$kty) -> Vec { + let mut key = $prefix.to_vec(); + key.extend($crate::codec::Slicable::encode(x)); + key + } + + /// Load the value associated with the given key from the map. + fn get(key: &$kty, storage: &S) -> Self::Query { + let key = <$name<$traitinstance> as $crate::storage::generator::StorageMap<$kty, $ty>>::key_for(key); + storage.$getter(&key[..]) + } + + /// Take the value, reading and removing it. + fn take(key: &$kty, storage: &S) -> Self::Query { + let key = <$name<$traitinstance> as $crate::storage::generator::StorageMap<$kty, $ty>>::key_for(key); + storage.$taker(&key[..]) + } + } + }; +} + +// TODO: revisit this idiom once we get `type`s in `impl`s. +/*impl Module { + type Now = super::Now; +}*/ + +/// Declares strongly-typed wrappers around codec-compatible types in storage. +/// +/// For now we implement a convenience trait with pre-specialised associated types, one for each +/// storage item. This allows you to gain access to publicly visisible storage items from a +/// module type. Currently you must disambiguate by using `::Item` rather than +/// the simpler `Module::Item`. Hopefully the rust guys with fix this soon. +#[macro_export] +macro_rules! decl_storage { + ( + trait $storetype:ident for $modulename:ident<$traitinstance:ident: $traittype:ident>; + $($t:tt)* + ) => { + __decl_storage_items!($traittype $traitinstance $($t)*); + trait $storetype { + __decl_store_items!($($t)*); + } + impl<$traitinstance: $traittype> $storetype for $modulename<$traitinstance> { + __impl_store_items!($traitinstance $($t)*); + } + impl<$traitinstance: $traittype> $modulename<$traitinstance> { + __impl_store_fns!($traitinstance $($t)*); + } + }; + ( + pub trait $storetype:ident for $modulename:ident<$traitinstance:ident: $traittype:ident>; + $($t:tt)* + ) => { + __decl_storage_items!($traittype $traitinstance $($t)*); + pub trait $storetype { + __decl_store_items!($($t)*); + } + impl<$traitinstance: $traittype> $storetype for $modulename<$traitinstance> { + __impl_store_items!($traitinstance $($t)*); + } + impl<$traitinstance: $traittype> $modulename<$traitinstance> { + __impl_store_fns!($traitinstance $($t)*); + } + } +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __decl_store_item { + ($name:ident) => { type $name; } +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __decl_store_items { + // simple values + ($name:ident : $key:expr => $ty:ty; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + (pub $name:ident : $key:expr => $ty:ty; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + ($name:ident : $key:expr => default $ty:ty; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + (pub $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + ($name:ident : $key:expr => required $ty:ty; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + (pub $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + + ($name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + (pub $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + ($name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + (pub $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + ($name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + (pub $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + + // maps + ($name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + (pub $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + ($name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + (pub $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + ($name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + (pub $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + + ($name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + (pub $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + ($name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + (pub $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + ($name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + (pub $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_store_item!($name); __decl_store_items!($($t)*); + }; + + // exit + () => () +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __impl_store_fn { + ($traitinstance:ident $name:ident $get_fn:ident ($gettype:ty) $key:expr => $ty:ty) => { + pub fn $get_fn() -> $gettype { + <$name<$traitinstance> as $crate::storage::generator::StorageValue<$ty>> :: get(&$crate::storage::RuntimeStorage) + } + }; + ($traitinstance:ident $name:ident $get_fn:ident ($gettype:ty) $prefix:expr => map [$kty:ty => $ty:ty]) => { + pub fn $get_fn>(key: K) -> $gettype { + <$name<$traitinstance> as $crate::storage::generator::StorageMap<$kty, $ty>> :: get(key.borrow(), &$crate::storage::RuntimeStorage) + } + } +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __impl_store_fns { + // simple values + ($traitinstance:ident $name:ident : $key:expr => $ty:ty; $($t:tt)*) => { + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident : $key:expr => $ty:ty; $($t:tt)*) => { + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => { + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => { + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => { + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => { + __impl_store_fns!($traitinstance $($t)*); + }; + + ($traitinstance:ident $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => { + __impl_store_fn!($traitinstance $name $getfn (Option<$ty>) $gettype $key => $ty); + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => { + __impl_store_fn!($traitinstance $name $getfn (Option<$ty>) $key => $ty); + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => { + __impl_store_fn!($traitinstance $name $getfn ($ty) $key => $ty); + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => { + __impl_store_fn!($traitinstance $name $getfn ($ty) $key => $ty); + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => { + __impl_store_fn!($traitinstance $name $getfn ($ty) $key => $ty); + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => { + __impl_store_fn!($traitinstance $name $getfn ($ty) $key => $ty); + __impl_store_fns!($traitinstance $($t)*); + }; + + // maps + ($traitinstance:ident $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_fns!($traitinstance $($t)*); + }; + + ($traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_fn!($traitinstance $name $getfn (Option<$ty>) $prefix:expr => map [$kty => $ty]); + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_fn!($traitinstance $name $getfn (Option<$ty>) $prefix:expr => map [$kty => $ty]); + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_fn!($traitinstance $name $getfn ($ty) $prefix:expr => map [$kty => $ty]); + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_fn!($traitinstance $name $getfn ($ty) $prefix:expr => map [$kty => $ty]); + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_fn!($traitinstance $name $getfn ($ty) $prefix:expr => map [$kty => $ty]); + __impl_store_fns!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_fn!($traitinstance $name $getfn ($ty) $prefix:expr => map [$kty => $ty]); + __impl_store_fns!($traitinstance $($t)*); + }; + + // exit + ($traitinstance:ident) => () +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __impl_store_item { + ($name:ident $traitinstance:ident) => { type $name = $name<$traitinstance>; } +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __impl_store_items { + // simple values + ($traitinstance:ident $name:ident : $key:expr => $ty:ty; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident : $key:expr => $ty:ty; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + + ($traitinstance:ident $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + + // maps + ($traitinstance:ident $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + + ($traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + ($traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __impl_store_item!($name $traitinstance); + __impl_store_items!($traitinstance $($t)*); + }; + + // exit + ($traitinstance:ident) => () +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __decl_storage_items { + // simple values + ($traittype:ident $traitinstance:ident $name:ident : $key:expr => $ty:ty; $($t:tt)*) => { + __decl_storage_item!(() ($traittype as $traitinstance) () (Option<$ty>) (get) (take) $name: $key => $ty); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident pub $name:ident : $key:expr => $ty:ty; $($t:tt)*) => { + __decl_storage_item!((pub) ($traittype as $traitinstance) () (Option<$ty>) (get) (take) $name: $key => $ty); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => { + __decl_storage_item!(() ($traittype as $traitinstance) () ($ty) (get_or_default) (take_or_default) $name: $key => $ty); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident pub $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => { + __decl_storage_item!((pub) ($traittype as $traitinstance) () ($ty) (get_or_default) (take_or_default) $name: $key => $ty); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => { + __decl_storage_item!(() ($traittype as $traitinstance) () ($ty) (require) (take_or_panic) $name: $key => $ty); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident pub $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => { + __decl_storage_item!((pub) ($traittype as $traitinstance) () ($ty) (require) (take_or_panic) $name: $key => $ty); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + + ($traittype:ident $traitinstance:ident $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => { + __decl_storage_item!(() ($traittype as $traitinstance) ($getfn) (Option<$ty>) (get) (take) $name: $key => $ty); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => { + __decl_storage_item!((pub) ($traittype as $traitinstance) ($getfn) (Option<$ty>) (get) (take) $name: $key => $ty); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => { + __decl_storage_item!(() ($traittype as $traitinstance) ($getfn) ($ty) (get_or_default) (take_or_default) $name: $key => $ty); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => { + __decl_storage_item!((pub) ($traittype as $traitinstance) ($getfn) ($ty) (get_or_default) (take_or_default) $name: $key => $ty); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => { + __decl_storage_item!(() ($traittype as $traitinstance) ($getfn) ($ty) (require) (take_or_panic) $name: $key => $ty); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => { + __decl_storage_item!((pub) ($traittype as $traitinstance) ($getfn) ($ty) (require) (take_or_panic) $name: $key => $ty); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + + // maps + ($traittype:ident $traitinstance:ident $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_storage_item!(() ($traittype as $traitinstance) () (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident pub $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_storage_item!((pub) ($traittype as $traitinstance) () (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_storage_item!(() ($traittype as $traitinstance) () ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident pub $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_storage_item!((pub) ($traittype as $traitinstance) () ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_storage_item!(() ($traittype as $traitinstance) () ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident pub $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_storage_item!((pub) ($traittype as $traitinstance) () ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + + ($traittype:ident $traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_storage_item!(() ($traittype as $traitinstance) ($getfn) (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_storage_item!((pub) ($traittype as $traitinstance) ($getfn) (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_storage_item!(() ($traittype as $traitinstance) ($getfn) ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_storage_item!((pub) ($traittype as $traitinstance) ($getfn) ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_storage_item!(() ($traittype as $traitinstance) ($getfn) ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + ($traittype:ident $traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { + __decl_storage_item!((pub) ($traittype as $traitinstance) ($getfn) ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); + __decl_storage_items!($traittype $traitinstance $($t)*); + }; + + // exit + ($traittype:ident $traitinstance:ident) => () +} + #[cfg(test)] mod tests { use std::collections::HashMap; diff --git a/substrate/substrate/runtime/consensus/Cargo.toml b/substrate/substrate/runtime/consensus/Cargo.toml new file mode 100644 index 0000000000..c2de219535 --- /dev/null +++ b/substrate/substrate/runtime/consensus/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "substrate-runtime-consensus" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +hex-literal = "0.1.0" +serde = { version = "1.0", default_features = false } +substrate-codec = { path = "../../codec", default_features = false } +substrate-runtime-std = { path = "../../runtime-std", default_features = false } +substrate-runtime-io = { path = "../../runtime-io", default_features = false } +substrate-runtime-support = { path = "../../runtime-support", default_features = false } +substrate-runtime-primitives = { path = "../primitives", default_features = false } + +[features] +default = ["std"] +std = [ + "serde/std", + "substrate-codec/std", + "substrate-runtime-std/std", + "substrate-runtime-io/std", + "substrate-runtime-support/std", + "substrate-runtime-primitives/std", +] diff --git a/substrate/substrate/runtime/consensus/src/lib.rs b/substrate/substrate/runtime/consensus/src/lib.rs new file mode 100644 index 0000000000..7826c689e7 --- /dev/null +++ b/substrate/substrate/runtime/consensus/src/lib.rs @@ -0,0 +1,111 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Demo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Demo. If not, see . + +//! Conensus module for runtime; manages the authority set ready for the native code. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[allow(unused_imports)] +#[macro_use] +extern crate substrate_runtime_std as rstd; + +#[macro_use] +extern crate substrate_runtime_support as runtime_support; + +extern crate substrate_runtime_io as runtime_io; +extern crate substrate_runtime_primitives as primitives; +extern crate substrate_codec as codec; + +use rstd::prelude::*; +use runtime_support::{storage, Parameter}; +use runtime_support::storage::unhashed::StorageVec; + +pub const AUTHORITY_AT: &'static[u8] = b":auth:"; +pub const AUTHORITY_COUNT: &'static[u8] = b":auth:len"; + +struct AuthorityStorageVec(rstd::marker::PhantomData); +impl StorageVec for AuthorityStorageVec { + type Item = S; + const PREFIX: &'static [u8] = AUTHORITY_AT; +} + +pub const CODE: &'static [u8] = b":code"; + +pub trait Trait { + type SessionKey: Parameter + Default; +} + +decl_module! { + pub struct Module; + pub enum PrivCall { + fn set_code(new: Vec) = 0; + fn dummy() = 1; + } +} + +impl Module { + /// Get the current set of authorities. These are the session keys. + pub fn authorities() -> Vec { + AuthorityStorageVec::::items() + } + + /// Set the new code. + fn set_code(new: Vec) { + storage::unhashed::put_raw(CODE, &new); + } + + fn dummy() {} + + /// Set the current set of authorities' session keys. + /// + /// Called by `next_session` only. + pub fn set_authorities(authorities: &[T::SessionKey]) { + AuthorityStorageVec::::set_items(authorities); + } + + /// Set a single authority by index. + pub fn set_authority(index: u32, key: &T::SessionKey) { + AuthorityStorageVec::::set_item(index, key); + } +} + +#[cfg(any(feature = "std", test))] +pub struct GenesisConfig { + pub authorities: Vec, +} + +#[cfg(any(feature = "std", test))] +impl Default for GenesisConfig { + fn default() -> Self { + GenesisConfig { + authorities: vec![], + } + } +} + +#[cfg(any(feature = "std", test))] +impl primitives::BuildExternalities for GenesisConfig +{ + fn build_externalities(self) -> runtime_io::TestExternalities { + use codec::{Slicable, KeyedVec}; + let auth_count = self.authorities.len() as u32; + let mut r: runtime_io::TestExternalities = self.authorities.into_iter().enumerate().map(|(i, v)| + ((i as u32).to_keyed_vec(b":auth:"), v.encode()) + ).collect(); + r.insert(b":auth:len".to_vec(), auth_count.encode()); + r + } +} diff --git a/substrate/substrate/runtime/council/Cargo.toml b/substrate/substrate/runtime/council/Cargo.toml new file mode 100644 index 0000000000..e3a5fe93e1 --- /dev/null +++ b/substrate/substrate/runtime/council/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "substrate-runtime-council" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +hex-literal = "0.1.0" +integer-sqrt = "0.1.0" +serde = { version = "1.0", default_features = false } +safe-mix = { path = "../../../safe-mix", default_features = false} +substrate-keyring = { path = "../../keyring", optional = true } +substrate-codec = { path = "../../codec", default_features = false } +substrate-primitives = { path = "../../primitives", default_features = false } +substrate-runtime-std = { path = "../../runtime-std", default_features = false } +substrate-runtime-io = { path = "../../runtime-io", default_features = false } +substrate-runtime-support = { path = "../../runtime-support", default_features = false } +substrate-runtime-primitives = { path = "../primitives", default_features = false } +substrate-runtime-consensus = { path = "../consensus", default_features = false } +substrate-runtime-democracy = { path = "../democracy", default_features = false } +substrate-runtime-session = { path = "../session", default_features = false } +substrate-runtime-staking = { path = "../staking", default_features = false } +substrate-runtime-system = { path = "../system", default_features = false } + +[features] +default = ["std"] +std = [ + "serde/std", + "safe-mix/std", + "substrate-keyring", + "substrate-codec/std", + "substrate-primitives/std", + "substrate-runtime-std/std", + "substrate-runtime-io/std", + "substrate-runtime-support/std", + "substrate-runtime-primitives/std", + "substrate-runtime-consensus/std", + "substrate-runtime-democracy/std", + "substrate-runtime-session/std", + "substrate-runtime-staking/std", + "substrate-runtime-system/std", +] diff --git a/substrate/substrate/runtime/council/src/lib.rs b/substrate/substrate/runtime/council/src/lib.rs new file mode 100644 index 0000000000..9f7f4b21bb --- /dev/null +++ b/substrate/substrate/runtime/council/src/lib.rs @@ -0,0 +1,1453 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Demo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Demo. If not, see . + +//! Council system: Handles the voting in and maintenance of council members. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] extern crate serde; + +extern crate integer_sqrt; +extern crate substrate_codec as codec; +extern crate substrate_primitives; +#[cfg(any(feature = "std", test))] extern crate substrate_keyring as keyring; +#[macro_use] extern crate substrate_runtime_std as rstd; +extern crate substrate_runtime_io as runtime_io; +#[macro_use] extern crate substrate_runtime_support as runtime_support; +extern crate substrate_runtime_primitives as primitives; +extern crate substrate_runtime_consensus as consensus; +extern crate substrate_runtime_democracy as democracy; +extern crate substrate_runtime_session as session; +extern crate substrate_runtime_staking as staking; +extern crate substrate_runtime_system as system; + +use rstd::prelude::*; +use primitives::traits::{Zero, One, RefInto, As}; +use runtime_support::{StorageValue, StorageMap}; + +pub mod voting; + +// no polynomial attacks: +// +// all unbonded public operations should be constant time. +// all other public operations must be linear time in terms of prior public operations and: +// - those "valid" ones that cost nothing be limited to a constant number per single protected operation +// - the rest costing the same order as the computational complexity +// all protected operations must complete in at most O(public operations) +// +// we assume "beneficial" transactions will have the same access as attack transactions. +// +// any storage requirements should be bonded by the same order as the volume. + +// public operations: +// - express approvals (you pay in a "voter" bond the first time you do this; O(1); one extra DB entry, one DB change) +// - remove active voter (you get your "voter" bond back; O(1); one fewer DB entry, one DB change) +// - remove inactive voter (either you or the target is removed; if the target, you get their "voter" bond back; O(1); one fewer DB entry, one DB change) +// - submit candidacy (you pay a "candidate" bond; O(1); one extra DB entry, two DB changes) +// - present winner/runner-up (you may pay a "presentation" bond of O(voters) if the presentation is invalid; O(voters) compute; ) +// protected operations: +// - remove candidacy (remove all votes for a candidate) (one fewer DB entry, two DB changes) + +// to avoid a potentially problematic case of not-enough approvals prior to voting causing a +// back-to-back votes that have no way of ending, then there's a forced grace period between votes. +// to keep the system as stateless as possible (making it a bit easier to reason about), we just +// restrict when votes can begin to blocks that lie on boundaries (`voting_period`). + +// for an approval vote of C councilers: + +// top K runners-up are maintained between votes. all others are discarded. +// - candidate removed & bond returned when elected. +// - candidate removed & bond burned when discarded. + +// at the point that the vote ends (), all voters' balances are snapshotted. + +// for B blocks following, there's a counting period whereby each of the candidates that believe +// they fall in the top K+C voted can present themselves. they get the total stake +// recorded (based on the snapshot); an ordered list is maintained (the leaderboard). Noone may +// present themselves that, if elected, would result in being included twice on the council +// (important since existing councilers will will have their approval votes as it may be that they +// don't get removed), nor if existing presenters would mean they're not in the top K+C. + +// following B blocks, the top C candidates are elected and have their bond returned. the top C +// candidates and all other candidates beyond the top C+K are cleared. + +// vote-clearing happens lazily; for an approval to count, the most recent vote at the time of the +// voter's most recent vote must be no later than the most recent vote at the time that the +// candidate in the approval position was registered there. as candidates are removed from the +// register and others join in their place, this prevent an approval meant for an earlier candidate +// being used to elect a new candidate. + +// the candidate list increases as needed, but the contents (though not really the capacity) reduce +// after each vote as all but K entries are cleared. newly registering candidates must use cleared +// entries before they increase the capacity. + +pub type VoteIndex = u32; + +pub trait Trait: democracy::Trait {} + +decl_module! { + pub struct Module; + pub enum Call where aux: T::PublicAux { + fn set_approvals(aux, votes: Vec, index: VoteIndex) = 0; + fn reap_inactive_voter(aux, signed_index: u32, who: T::AccountId, who_index: u32, assumed_vote_index: VoteIndex) = 1; + fn retract_voter(aux, index: u32) = 2; + fn submit_candidacy(aux, slot: u32) = 3; + fn present_winner(aux, candidate: T::AccountId, total: T::Balance, index: VoteIndex) = 4; + } + pub enum PrivCall { + fn set_desired_seats(count: u32) = 0; + fn remove_member(who: T::AccountId) = 1; + fn set_presentation_duration(count: T::BlockNumber) = 2; + fn set_term_duration(count: T::BlockNumber) = 3; + } +} + +decl_storage! { + trait Store for Module; + + // parameters + // How much should be locked up in order to submit one's candidacy. + pub CandidacyBond get(candidacy_bond): b"cou:cbo" => required T::Balance; + // How much should be locked up in order to be able to submit votes. + pub VotingBond get(voting_bond): b"cou:vbo" => required T::Balance; + // The punishment, per voter, if you provide an invalid presentation. + pub PresentSlashPerVoter get(present_slash_per_voter): b"cou:pss" => required T::Balance; + // How many runners-up should have their approvals persist until the next vote. + pub CarryCount get(carry_count): b"cou:cco" => required u32; + // How long to give each top candidate to present themselves after the vote ends. + pub PresentationDuration get(presentation_duration): b"cou:pdu" => required T::BlockNumber; + // How many votes need to go by after a voter's last vote before they can be reaped if their + // approvals are moot. + pub InactiveGracePeriod get(inactivity_grace_period): b"cou:vgp" => required VoteIndex; + // How often (in blocks) to check for new votes. + pub VotingPeriod get(voting_period): b"cou:per" => required T::BlockNumber; + // How long each position is active for. + pub TermDuration get(term_duration): b"cou:trm" => required T::BlockNumber; + // Number of accounts that should be sitting on the council. + pub DesiredSeats get(desired_seats): b"cou:sts" => required u32; + + // permanent state (always relevant, changes only at the finalisation of voting) + // The current council. When there's a vote going on, this should still be used for executive + // matters. + pub ActiveCouncil get(active_council): b"cou:act" => default Vec<(T::AccountId, T::BlockNumber)>; + // The total number of votes that have happened or are in progress. + pub VoteCount get(vote_index): b"cou:vco" => default VoteIndex; + + // persistent state (always relevant, changes constantly) + // The last cleared vote index that this voter was last active at. + pub ApprovalsOf get(approvals_of): b"cou:apr" => default map [ T::AccountId => Vec ]; + // The vote index and list slot that the candidate `who` was registered or `None` if they are not + // currently registered. + pub RegisterInfoOf get(candidate_reg_info): b"cou:reg" => map [ T::AccountId => (VoteIndex, u32) ]; + // The last cleared vote index that this voter was last active at. + pub LastActiveOf get(voter_last_active): b"cou:lac" => map [ T::AccountId => VoteIndex ]; + // The present voter list. + pub Voters get(voters): b"cou:vrs" => default Vec; + // The present candidate list. + pub Candidates get(candidates): b"cou:can" => default Vec; // has holes + pub CandidateCount get(candidate_count): b"cou:cnc" => default u32; + + // temporary state (only relevant during finalisation/presentation) + // The accounts holding the seats that will become free on the next tally. + pub NextFinalise get(next_finalise): b"cou:nxt" => (T::BlockNumber, u32, Vec); + // The stakes as they were at the point that the vote ended. + pub SnapshotedStakes get(snapshoted_stakes): b"cou:sss" => required Vec; + // Get the leaderboard if we;re in the presentation phase. + pub Leaderboard get(leaderboard): b"cou:win" => Vec<(T::Balance, T::AccountId)>; // ORDERED low -> high +} + +impl Module { + + // exposed immutables. + + /// True if we're currently in a presentation period. + pub fn presentation_active() -> bool { + >::exists() + } + + /// If `who` a candidate at the moment? + pub fn is_a_candidate(who: &T::AccountId) -> bool { + >::exists(who) + } + + /// Determine the block that a vote can happen on which is no less than `n`. + pub fn next_vote_from(n: T::BlockNumber) -> T::BlockNumber { + let voting_period = Self::voting_period(); + (n + voting_period - One::one()) / voting_period * voting_period + } + + /// The block number on which the tally for the next election will happen. `None` only if the + /// desired seats of the council is zero. + pub fn next_tally() -> Option { + let desired_seats = Self::desired_seats(); + if desired_seats == 0 { + None + } else { + let c = Self::active_council(); + let (next_possible, count, coming) = + if let Some((tally_end, comers, leavers)) = Self::next_finalise() { + // if there's a tally in progress, then next tally can begin immediately afterwards + (tally_end, c.len() - leavers.len() + comers as usize, comers) + } else { + (>::block_number(), c.len(), 0) + }; + if count < desired_seats as usize { + Some(next_possible) + } else { + // next tally begins once enough council members expire to bring members below desired. + if desired_seats <= coming { + // the entire amount of desired seats is less than those new members - we'll have + // to wait until they expire. + Some(next_possible + Self::term_duration()) + } else { + Some(c[c.len() - (desired_seats - coming) as usize].1) + } + }.map(Self::next_vote_from) + } + } + + // dispatch + + /// Set candidate approvals. Approval slots stay valid as long as candidates in those slots + /// are registered. + fn set_approvals(aux: &T::PublicAux, votes: Vec, index: VoteIndex) { + assert!(!Self::presentation_active()); + assert_eq!(index, Self::vote_index()); + if !>::exists(aux.ref_into()) { + // not yet a voter - deduct bond. + >::reserve_balance(aux.ref_into(), Self::voting_bond()); + >::put({ + let mut v = Self::voters(); + v.push(aux.ref_into().clone()); + v + }); + } + >::insert(aux.ref_into().clone(), votes); + >::insert(aux.ref_into(), index); + } + + /// Remove a voter. For it not to be a bond-consuming no-op, all approved candidate indices + /// must now be either unregistered or registered to a candidate that registered the slot after + /// the voter gave their last approval set. + /// + /// May be called by anyone. Returns the voter deposit to `signed`. + fn reap_inactive_voter(aux: &T::PublicAux, signed_index: u32, who: T::AccountId, who_index: u32, assumed_vote_index: VoteIndex) { + assert!(!Self::presentation_active(), "cannot reap during presentation period"); + assert!(Self::voter_last_active(aux.ref_into()).is_some(), "reaper must be a voter"); + let last_active = Self::voter_last_active(&who).expect("target for inactivity cleanup must be active"); + assert!(assumed_vote_index == Self::vote_index(), "vote index not current"); + assert!(last_active < assumed_vote_index - Self::inactivity_grace_period(), "cannot reap during grace perid"); + let voters = Self::voters(); + let signed_index = signed_index as usize; + let who_index = who_index as usize; + assert!(signed_index < voters.len() && &voters[signed_index] == aux.ref_into(), "bad reporter index"); + assert!(who_index < voters.len() && voters[who_index] == who, "bad target index"); + + // will definitely kill one of signed or who now. + + let valid = !Self::approvals_of(&who).iter() + .zip(Self::candidates().iter()) + .any(|(&appr, addr)| + appr && + *addr != T::AccountId::default() && + Self::candidate_reg_info(addr) + .expect("all items in candidates list are registered").0 <= last_active); + + Self::remove_voter( + if valid { &who } else { aux.ref_into() }, + if valid { who_index } else { signed_index }, + voters + ); + if valid { + >::transfer_reserved_balance(&who, aux.ref_into(), Self::voting_bond()); + } else { + >::slash_reserved(aux.ref_into(), Self::voting_bond()); + } + } + + /// Remove a voter. All votes are cancelled and the voter deposit is returned. + fn retract_voter(aux: &T::PublicAux, index: u32) { + assert!(!Self::presentation_active(), "cannot retract when presenting"); + assert!(>::exists(aux.ref_into()), "cannot retract non-voter"); + let voters = Self::voters(); + let index = index as usize; + assert!(index < voters.len(), "retraction index invalid"); + assert!(&voters[index] == aux.ref_into(), "retraction index mismatch"); + Self::remove_voter(aux.ref_into(), index, voters); + >::unreserve_balance(aux.ref_into(), Self::voting_bond()); + } + + /// Submit oneself for candidacy. + /// + /// Account must have enough transferrable funds in it to pay the bond. + fn submit_candidacy(aux: &T::PublicAux, slot: u32) { + assert!(!Self::is_a_candidate(aux.ref_into()), "duplicate candidate submission"); + assert!(>::deduct_unbonded(aux.ref_into(), Self::candidacy_bond()), "candidate has not enough funds"); + + let slot = slot as usize; + let count = Self::candidate_count() as usize; + let candidates = Self::candidates(); + assert!( + (slot == count && count == candidates.len()) || + (slot < candidates.len() && candidates[slot] == T::AccountId::default()), + "invalid candidate slot" + ); + + let mut candidates = candidates; + if slot == candidates.len() { + candidates.push(aux.ref_into().clone()); + } else { + candidates[slot] = aux.ref_into().clone(); + } + >::put(candidates); + >::put(count as u32 + 1); + >::insert(aux.ref_into(), (Self::vote_index(), slot as u32)); + } + + /// Claim that `signed` is one of the top Self::carry_count() + current_vote().1 candidates. + /// Only works if the `block_number >= current_vote().0` and `< current_vote().0 + presentation_duration()`` + /// `signed` should have at least + fn present_winner(aux: &T::PublicAux, candidate: T::AccountId, total: T::Balance, index: VoteIndex) { + assert_eq!(index, Self::vote_index(), "index not current"); + let (_, _, expiring) = Self::next_finalise() + .expect("cannot present outside of presentation period"); + let stakes = Self::snapshoted_stakes(); + let voters = Self::voters(); + let bad_presentation_punishment = Self::present_slash_per_voter() * T::Balance::sa(voters.len()); + assert!(>::can_slash(aux.ref_into(), bad_presentation_punishment), "presenter must have sufficient slashable funds"); + + let mut leaderboard = Self::leaderboard().expect("leaderboard must exist while present phase active"); + assert!(total > leaderboard[0].0, "candidate not worthy of leaderboard"); + + if let Some(p) = Self::active_council().iter().position(|&(ref c, _)| c == &candidate) { + assert!(p < expiring.len(), "candidate must not form a duplicated member if elected"); + } + + let (registered_since, candidate_index): (VoteIndex, u32) = + Self::candidate_reg_info(&candidate).expect("presented candidate must be current"); + let actual_total = voters.iter() + .zip(stakes.iter()) + .filter_map(|(voter, stake)| + match Self::voter_last_active(voter) { + Some(b) if b >= registered_since => + Self::approvals_of(voter).get(candidate_index as usize) + .and_then(|approved| if *approved { Some(*stake) } else { None }), + _ => None, + }) + .fold(Zero::zero(), |acc, n| acc + n); + let dupe = leaderboard.iter().find(|&&(_, ref c)| c == &candidate).is_some(); + if total == actual_total && !dupe { + // insert into leaderboard + leaderboard[0] = (total, candidate); + leaderboard.sort_by_key(|&(t, _)| t); + >::put(leaderboard); + } else { + >::slash(aux.ref_into(), bad_presentation_punishment); + } + } + + /// Set the desired member count; if lower than the current count, then seats will not be up + /// election when they expire. If more, then a new vote will be started if one is not already + /// in progress. + fn set_desired_seats(count: u32) { + >::put(count); + } + + /// Remove a particular member. A tally will happen instantly (if not already in a presentation + /// period) to fill the seat if removal means that the desired members are not met. + /// This is effective immediately. + fn remove_member(who: T::AccountId) { + let new_council: Vec<(T::AccountId, T::BlockNumber)> = Self::active_council() + .into_iter() + .filter(|i| i.0 != who) + .collect(); + >::put(new_council); + } + + /// Set the presentation duration. If there is current a vote being presented for, will + /// invoke `finalise_vote`. + fn set_presentation_duration(count: T::BlockNumber) { + >::put(count); + } + + /// Set the presentation duration. If there is current a vote being presented for, will + /// invoke `finalise_vote`. + fn set_term_duration(count: T::BlockNumber) { + >::put(count); + } + + // private + + /// Check there's nothing to do this block + fn end_block(block_number: T::BlockNumber) { + if (block_number % Self::voting_period()).is_zero() { + if let Some(number) = Self::next_tally() { + if block_number == number { + Self::start_tally(); + } + } + } + if let Some((number, _, _)) = Self::next_finalise() { + if block_number == number { + Self::finalise_tally(); + } + } + } + + /// Remove a voter from the system. Trusts that Self::voters()[index] != voter. + fn remove_voter(voter: &T::AccountId, index: usize, mut voters: Vec) { + >::put({ voters.swap_remove(index); voters }); + >::remove(voter); + >::remove(voter); + } + + /// Close the voting, snapshot the staking and the number of seats that are actually up for grabs. + fn start_tally() { + let active_council = Self::active_council(); + let desired_seats = Self::desired_seats() as usize; + let number = >::block_number(); + let expiring = active_council.iter().take_while(|i| i.1 == number).map(|i| i.0.clone()).collect::>(); + if active_council.len() - expiring.len() < desired_seats { + let empty_seats = desired_seats - (active_council.len() - expiring.len()); + >::put((number + Self::presentation_duration(), empty_seats as u32, expiring)); + + let voters = Self::voters(); + let votes = voters.iter().map(>::balance).collect::>(); + >::put(votes); + + // initialise leaderboard. + let leaderboard_size = empty_seats + Self::carry_count() as usize; + >::put(vec![(T::Balance::zero(), T::AccountId::default()); leaderboard_size]); + } + } + + /// Finalise the vote, removing each of the `removals` and inserting `seats` of the most approved + /// candidates in their place. If the total council members is less than the desired membership + /// a new vote is started. + /// Clears all presented candidates, returning the bond of the elected ones. + fn finalise_tally() { + >::kill(); + let (_, coming, expiring): (T::BlockNumber, u32, Vec) = >::take() + .expect("finalise can only be called after a tally is started."); + let leaderboard: Vec<(T::Balance, T::AccountId)> = >::take().unwrap_or_default(); + let new_expiry = >::block_number() + Self::term_duration(); + + // return bond to winners. + let candidacy_bond = Self::candidacy_bond(); + for &(_, ref w) in leaderboard.iter() + .rev() + .take_while(|&&(b, _)| !b.is_zero()) + .take(coming as usize) + { + >::refund(w, candidacy_bond); + } + + // set the new council. + let mut new_council: Vec<_> = Self::active_council() + .into_iter() + .skip(expiring.len()) + .chain(leaderboard.iter() + .rev() + .take_while(|&&(b, _)| !b.is_zero()) + .take(coming as usize) + .cloned() + .map(|(_, a)| (a, new_expiry))) + .collect(); + new_council.sort_by_key(|&(_, expiry)| expiry); + >::put(new_council); + + // clear all except runners-up from candidate list. + let candidates = Self::candidates(); + let mut new_candidates = vec![T::AccountId::default(); candidates.len()]; // shrink later. + let runners_up = leaderboard.into_iter() + .rev() + .take_while(|&(b, _)| !b.is_zero()) + .skip(coming as usize) + .map(|(_, a)| { let i = Self::candidate_reg_info(&a).expect("runner up must be registered").1; (a, i) }); + let mut count = 0u32; + for (address, slot) in runners_up { + new_candidates[slot as usize] = address; + count += 1; + } + for (old, new) in candidates.iter().zip(new_candidates.iter()) { + if old != new { + // removed - kill it + >::remove(old); + } + } + // discard any superfluous slots. + if let Some(last_index) = new_candidates.iter().rposition(|c| *c != T::AccountId::default()) { + new_candidates.truncate(last_index + 1); + } + >::put(new_candidates); + >::put(count); + >::put(Self::vote_index() + 1); + } +} + +#[cfg(any(feature = "std", test))] +pub struct GenesisConfig { + // for the voting onto the council + pub candidacy_bond: T::Balance, + pub voter_bond: T::Balance, + pub present_slash_per_voter: T::Balance, + pub carry_count: u32, + pub active_council: Vec<(T::AccountId, T::BlockNumber)>, + pub approval_voting_period: T::BlockNumber, + pub presentation_duration: T::BlockNumber, + pub desired_seats: u32, + pub term_duration: T::BlockNumber, + pub inactive_grace_period: T::BlockNumber, + + + // for the council's votes. + pub cooloff_period: T::BlockNumber, + pub voting_period: T::BlockNumber, +} + +#[cfg(any(feature = "std", test))] +impl Default for GenesisConfig { + fn default() -> Self { + GenesisConfig { + candidacy_bond: T::Balance::sa(9), + voter_bond: T::Balance::sa(0), + present_slash_per_voter: T::Balance::sa(1), + carry_count: 2, + inactive_grace_period: T::BlockNumber::sa(1), + active_council: vec![], + approval_voting_period: T::BlockNumber::sa(1000), + presentation_duration: T::BlockNumber::sa(1000), + desired_seats: 0, + term_duration: T::BlockNumber::sa(5), + cooloff_period: T::BlockNumber::sa(1000), + voting_period: T::BlockNumber::sa(3), + } + } +} + +#[cfg(any(feature = "std", test))] +impl primitives::BuildExternalities for GenesisConfig +{ + fn build_externalities(self) -> runtime_io::TestExternalities { + use codec::Slicable; + use runtime_io::twox_128; + + map![ + twox_128(>::key()).to_vec() => self.candidacy_bond.encode(), + twox_128(>::key()).to_vec() => self.voter_bond.encode(), + twox_128(>::key()).to_vec() => self.present_slash_per_voter.encode(), + twox_128(>::key()).to_vec() => self.carry_count.encode(), + twox_128(>::key()).to_vec() => self.presentation_duration.encode(), + twox_128(>::key()).to_vec() => self.approval_voting_period.encode(), + twox_128(>::key()).to_vec() => self.term_duration.encode(), + twox_128(>::key()).to_vec() => self.desired_seats.encode(), + twox_128(>::key()).to_vec() => self.inactive_grace_period.encode(), + twox_128(>::key()).to_vec() => self.active_council.encode(), + + twox_128(>::key()).to_vec() => self.cooloff_period.encode(), + twox_128(>::key()).to_vec() => self.voting_period.encode() + ] + } +} + +#[cfg(test)] +mod tests { + pub use super::*; + pub use runtime_io::with_externalities; + pub use substrate_primitives::H256; + use primitives::BuildExternalities; + use primitives::traits::{HasPublicAux, Identity}; + use primitives::testing::{Digest, Header}; + + impl_outer_dispatch! { + pub enum Proposal { + Staking = 0, + Democracy = 1, + } + } + + pub struct Test; + impl HasPublicAux for Test { + type PublicAux = u64; + } + impl consensus::Trait for Test { + type SessionKey = u64; + } + impl system::Trait for Test { + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = runtime_io::BlakeTwo256; + type Digest = Digest; + type AccountId = u64; + type Header = Header; + } + impl session::Trait for Test { + type PublicAux = ::PublicAux; + type ConvertAccountIdToSessionKey = Identity; + } + impl staking::Trait for Test { + type Balance = u64; + type DetermineContractAddress = staking::DummyContractAddressFor; + } + impl democracy::Trait for Test { + type Proposal = Proposal; + } + impl Trait for Test {} + + pub fn new_test_ext(with_council: bool) -> runtime_io::TestExternalities { + let mut t = system::GenesisConfig::::default().build_externalities(); + t.extend(consensus::GenesisConfig::{ + authorities: vec![], + }.build_externalities()); + t.extend(session::GenesisConfig::{ + session_length: 1, //??? or 2? + validators: vec![10, 20], + }.build_externalities()); + t.extend(staking::GenesisConfig::{ + sessions_per_era: 1, + current_era: 0, + balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], + intentions: vec![], + validator_count: 2, + bonding_duration: 0, + transaction_fee: 0, + }.build_externalities()); + t.extend(democracy::GenesisConfig::{ + launch_period: 1, + voting_period: 3, + minimum_deposit: 1, + }.build_externalities()); + t.extend(GenesisConfig::{ + candidacy_bond: 9, + voter_bond: 3, + present_slash_per_voter: 1, + carry_count: 2, + inactive_grace_period: 1, + active_council: if with_council { vec![ + (1, 10), + (2, 10), + (3, 10) + ] } else { vec![] }, + approval_voting_period: 4, + presentation_duration: 2, + desired_seats: 2, + term_duration: 5, + cooloff_period: 2, + voting_period: 1, + }.build_externalities()); + t + } + + pub type System = system::Module; + pub type Staking = staking::Module; + pub type Democracy = democracy::Module; + pub type Council = Module; + + #[test] + fn params_should_work() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(1); + assert_eq!(Council::next_vote_from(1), 4); + assert_eq!(Council::next_vote_from(4), 4); + assert_eq!(Council::next_vote_from(5), 8); + assert_eq!(Council::vote_index(), 0); + assert_eq!(Council::candidacy_bond(), 9); + assert_eq!(Council::voting_bond(), 3); + assert_eq!(Council::present_slash_per_voter(), 1); + assert_eq!(Council::presentation_duration(), 2); + assert_eq!(Council::voting_period(), 4); + assert_eq!(Council::term_duration(), 5); + assert_eq!(Council::desired_seats(), 2); + assert_eq!(Council::carry_count(), 2); + + assert_eq!(Council::active_council(), vec![]); + assert_eq!(Council::next_tally(), Some(4)); + assert_eq!(Council::presentation_active(), false); + assert_eq!(Council::next_finalise(), None); + + assert_eq!(Council::candidates(), Vec::::new()); + assert_eq!(Council::is_a_candidate(&1), false); + assert_eq!(Council::candidate_reg_info(1), None); + + assert_eq!(Council::voters(), Vec::::new()); + assert_eq!(Council::voter_last_active(1), None); + assert_eq!(Council::approvals_of(1), vec![]); + }); + } + + #[test] + fn simple_candidate_submission_should_work() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(1); + assert_eq!(Council::candidates(), Vec::::new()); + assert_eq!(Council::candidate_reg_info(1), None); + assert_eq!(Council::candidate_reg_info(2), None); + assert_eq!(Council::is_a_candidate(&1), false); + assert_eq!(Council::is_a_candidate(&2), false); + + Council::submit_candidacy(&1, 0); + assert_eq!(Council::candidates(), vec![1]); + assert_eq!(Council::candidate_reg_info(1), Some((0, 0))); + assert_eq!(Council::candidate_reg_info(2), None); + assert_eq!(Council::is_a_candidate(&1), true); + assert_eq!(Council::is_a_candidate(&2), false); + + Council::submit_candidacy(&2, 1); + assert_eq!(Council::candidates(), vec![1, 2]); + assert_eq!(Council::candidate_reg_info(1), Some((0, 0))); + assert_eq!(Council::candidate_reg_info(2), Some((0, 1))); + assert_eq!(Council::is_a_candidate(&1), true); + assert_eq!(Council::is_a_candidate(&2), true); + }); + } + + fn new_test_ext_with_candidate_holes() -> runtime_io::TestExternalities { + let mut t = new_test_ext(false); + with_externalities(&mut t, || { + >::put(vec![0, 0, 1]); + >::put(1); + >::insert(1, (0, 2)); + }); + t + } + + #[test] + fn candidate_submission_using_free_slot_should_work() { + let mut t = new_test_ext_with_candidate_holes(); + + with_externalities(&mut t, || { + System::set_block_number(1); + assert_eq!(Council::candidates(), vec![0, 0, 1]); + + Council::submit_candidacy(&2, 1); + assert_eq!(Council::candidates(), vec![0, 2, 1]); + + Council::submit_candidacy(&3, 0); + assert_eq!(Council::candidates(), vec![3, 2, 1]); + }); + } + + #[test] + fn candidate_submission_using_alternative_free_slot_should_work() { + let mut t = new_test_ext_with_candidate_holes(); + + with_externalities(&mut t, || { + System::set_block_number(1); + assert_eq!(Council::candidates(), vec![0, 0, 1]); + + Council::submit_candidacy(&2, 0); + assert_eq!(Council::candidates(), vec![2, 0, 1]); + + Council::submit_candidacy(&3, 1); + assert_eq!(Council::candidates(), vec![2, 3, 1]); + }); + } + + #[test] + #[should_panic(expected = "invalid candidate slot")] + fn candidate_submission_not_using_free_slot_should_panic() { + let mut t = new_test_ext_with_candidate_holes(); + + with_externalities(&mut t, || { + System::set_block_number(1); + Council::submit_candidacy(&4, 3); + }); + } + + #[test] + #[should_panic(expected = "invalid candidate slot")] + fn bad_candidate_slot_submission_should_panic() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(1); + assert_eq!(Council::candidates(), Vec::::new()); + Council::submit_candidacy(&1, 1); + }); + } + + #[test] + #[should_panic(expected = "invalid candidate slot")] + fn non_free_candidate_slot_submission_should_panic() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(1); + assert_eq!(Council::candidates(), Vec::::new()); + Council::submit_candidacy(&1, 0); + Council::submit_candidacy(&2, 0); + }); + } + + #[test] + #[should_panic(expected = "duplicate candidate submission")] + fn dupe_candidate_submission_should_panic() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(1); + assert_eq!(Council::candidates(), Vec::::new()); + Council::submit_candidacy(&1, 0); + Council::submit_candidacy(&1, 1); + }); + } + + #[test] + #[should_panic(expected = "candidate has not enough funds")] + fn poor_candidate_submission_should_panic() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(1); + assert_eq!(Council::candidates(), Vec::::new()); + Council::submit_candidacy(&7, 0); + }); + } + + #[test] + fn voting_should_work() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(1); + + Council::submit_candidacy(&5, 0); + + Council::set_approvals(&1, vec![true], 0); + Council::set_approvals(&4, vec![true], 0); + + assert_eq!(Council::approvals_of(1), vec![true]); + assert_eq!(Council::approvals_of(4), vec![true]); + assert_eq!(Council::voters(), vec![1, 4]); + + Council::submit_candidacy(&2, 1); + Council::submit_candidacy(&3, 2); + + Council::set_approvals(&2, vec![false, true, true], 0); + Council::set_approvals(&3, vec![false, true, true], 0); + + assert_eq!(Council::approvals_of(1), vec![true]); + assert_eq!(Council::approvals_of(4), vec![true]); + assert_eq!(Council::approvals_of(2), vec![false, true, true]); + assert_eq!(Council::approvals_of(3), vec![false, true, true]); + + assert_eq!(Council::voters(), vec![1, 4, 2, 3]); + }); + } + + #[test] + fn resubmitting_voting_should_work() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(1); + + Council::submit_candidacy(&5, 0); + Council::set_approvals(&4, vec![true], 0); + + assert_eq!(Council::approvals_of(4), vec![true]); + + Council::submit_candidacy(&2, 1); + Council::submit_candidacy(&3, 2); + Council::set_approvals(&4, vec![true, false, true], 0); + + assert_eq!(Council::approvals_of(4), vec![true, false, true]); + }); + } + + #[test] + fn retracting_voter_should_work() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(1); + + Council::submit_candidacy(&5, 0); + Council::submit_candidacy(&2, 1); + Council::submit_candidacy(&3, 2); + + Council::set_approvals(&1, vec![true], 0); + Council::set_approvals(&2, vec![false, true, true], 0); + Council::set_approvals(&3, vec![false, true, true], 0); + Council::set_approvals(&4, vec![true, false, true], 0); + + assert_eq!(Council::voters(), vec![1, 2, 3, 4]); + assert_eq!(Council::approvals_of(1), vec![true]); + assert_eq!(Council::approvals_of(2), vec![false, true, true]); + assert_eq!(Council::approvals_of(3), vec![false, true, true]); + assert_eq!(Council::approvals_of(4), vec![true, false, true]); + + Council::retract_voter(&1, 0); + + assert_eq!(Council::voters(), vec![4, 2, 3]); + assert_eq!(Council::approvals_of(1), Vec::::new()); + assert_eq!(Council::approvals_of(2), vec![false, true, true]); + assert_eq!(Council::approvals_of(3), vec![false, true, true]); + assert_eq!(Council::approvals_of(4), vec![true, false, true]); + + Council::retract_voter(&2, 1); + + assert_eq!(Council::voters(), vec![4, 3]); + assert_eq!(Council::approvals_of(1), Vec::::new()); + assert_eq!(Council::approvals_of(2), Vec::::new()); + assert_eq!(Council::approvals_of(3), vec![false, true, true]); + assert_eq!(Council::approvals_of(4), vec![true, false, true]); + + Council::retract_voter(&3, 1); + + assert_eq!(Council::voters(), vec![4]); + assert_eq!(Council::approvals_of(1), Vec::::new()); + assert_eq!(Council::approvals_of(2), Vec::::new()); + assert_eq!(Council::approvals_of(3), Vec::::new()); + assert_eq!(Council::approvals_of(4), vec![true, false, true]); + }); + } + + #[test] + #[should_panic(expected = "retraction index mismatch")] + fn invalid_retraction_index_should_panic() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(1); + Council::submit_candidacy(&3, 0); + Council::set_approvals(&1, vec![true], 0); + Council::set_approvals(&2, vec![true], 0); + Council::retract_voter(&1, 1); + }); + } + + #[test] + #[should_panic(expected = "retraction index invalid")] + fn overflow_retraction_index_should_panic() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(1); + Council::submit_candidacy(&3, 0); + Council::set_approvals(&1, vec![true], 0); + Council::retract_voter(&1, 1); + }); + } + + #[test] + #[should_panic(expected = "cannot retract non-voter")] + fn non_voter_retraction_should_panic() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(1); + Council::submit_candidacy(&3, 0); + Council::set_approvals(&1, vec![true], 0); + Council::retract_voter(&2, 0); + }); + } + + #[test] + fn simple_tally_should_work() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + assert!(!Council::presentation_active()); + + Council::submit_candidacy(&2, 0); + Council::submit_candidacy(&5, 1); + Council::set_approvals(&2, vec![true, false], 0); + Council::set_approvals(&5, vec![false, true], 0); + Council::end_block(System::block_number()); + + System::set_block_number(6); + assert!(Council::presentation_active()); + Council::present_winner(&4, 2, 11, 0); + Council::present_winner(&4, 5, 41, 0); + assert_eq!(Council::leaderboard(), Some(vec![(0, 0), (0, 0), (11, 2), (41, 5)])); + + Council::end_block(System::block_number()); + + assert!(!Council::presentation_active()); + assert_eq!(Council::active_council(), vec![(5, 11), (2, 11)]); + + assert!(!Council::is_a_candidate(&2)); + assert!(!Council::is_a_candidate(&5)); + assert_eq!(Council::vote_index(), 1); + assert_eq!(Council::voter_last_active(2), Some(0)); + assert_eq!(Council::voter_last_active(5), Some(0)); + }); + } + + #[test] + fn double_presentations_should_be_punished() { + with_externalities(&mut new_test_ext(false), || { + assert!(Staking::can_slash(&4, 10)); + + System::set_block_number(4); + Council::submit_candidacy(&2, 0); + Council::submit_candidacy(&5, 1); + Council::set_approvals(&2, vec![true, false], 0); + Council::set_approvals(&5, vec![false, true], 0); + Council::end_block(System::block_number()); + + System::set_block_number(6); + Council::present_winner(&4, 2, 11, 0); + Council::present_winner(&4, 5, 41, 0); + Council::present_winner(&4, 5, 41, 0); + Council::end_block(System::block_number()); + + assert_eq!(Council::active_council(), vec![(5, 11), (2, 11)]); + assert_eq!(Staking::balance(&4), 38); + }); + } + + #[test] + fn retracting_inactive_voter_should_work() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + Council::submit_candidacy(&2, 0); + Council::set_approvals(&2, vec![true], 0); + Council::end_block(System::block_number()); + + System::set_block_number(6); + Council::present_winner(&4, 2, 11, 0); + Council::end_block(System::block_number()); + + System::set_block_number(8); + Council::submit_candidacy(&5, 0); + Council::set_approvals(&5, vec![true], 1); + Council::end_block(System::block_number()); + + System::set_block_number(10); + Council::present_winner(&4, 5, 41, 1); + Council::end_block(System::block_number()); + + Council::reap_inactive_voter(&5, + Council::voters().iter().position(|&i| i == 5).unwrap() as u32, + 2, Council::voters().iter().position(|&i| i == 2).unwrap() as u32, + 2 + ); + + assert_eq!(Council::voters(), vec![5]); + assert_eq!(Council::approvals_of(2).len(), 0); + assert_eq!(Staking::balance(&2), 17); + assert_eq!(Staking::balance(&5), 53); + }); + } + + #[test] + #[should_panic(expected = "candidate must not form a duplicated member if elected")] + fn presenting_for_double_election_should_panic() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + Council::submit_candidacy(&2, 0); + Council::set_approvals(&2, vec![true], 0); + Council::end_block(System::block_number()); + + System::set_block_number(6); + Council::present_winner(&4, 2, 11, 0); + Council::end_block(System::block_number()); + + System::set_block_number(8); + Council::submit_candidacy(&2, 0); + Council::set_approvals(&2, vec![true], 1); + Council::end_block(System::block_number()); + + System::set_block_number(10); + Council::present_winner(&4, 2, 11, 1); + }); + } + + #[test] + fn retracting_inactive_voter_with_other_candidates_in_slots_should_work() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + Council::submit_candidacy(&2, 0); + Council::set_approvals(&2, vec![true], 0); + Council::end_block(System::block_number()); + + System::set_block_number(6); + Council::present_winner(&4, 2, 11, 0); + Council::end_block(System::block_number()); + + System::set_block_number(8); + Council::submit_candidacy(&5, 0); + Council::set_approvals(&5, vec![true], 1); + Council::end_block(System::block_number()); + + System::set_block_number(10); + Council::present_winner(&4, 5, 41, 1); + Council::end_block(System::block_number()); + + System::set_block_number(11); + Council::submit_candidacy(&1, 0); + + Council::reap_inactive_voter(&5, + Council::voters().iter().position(|&i| i == 5).unwrap() as u32, + 2, Council::voters().iter().position(|&i| i == 2).unwrap() as u32, + 2 + ); + + assert_eq!(Council::voters(), vec![5]); + assert_eq!(Council::approvals_of(2).len(), 0); + assert_eq!(Staking::balance(&2), 17); + assert_eq!(Staking::balance(&5), 53); + }); + } + + #[test] + #[should_panic(expected = "bad reporter index")] + fn retracting_inactive_voter_with_bad_reporter_index_should_panic() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + Council::submit_candidacy(&2, 0); + Council::set_approvals(&2, vec![true], 0); + Council::end_block(System::block_number()); + + System::set_block_number(6); + Council::present_winner(&4, 2, 8, 0); + Council::end_block(System::block_number()); + + System::set_block_number(8); + Council::submit_candidacy(&5, 0); + Council::set_approvals(&5, vec![true], 1); + Council::end_block(System::block_number()); + + System::set_block_number(10); + Council::present_winner(&4, 5, 38, 1); + Council::end_block(System::block_number()); + + Council::reap_inactive_voter(&2, + 42, + 2, Council::voters().iter().position(|&i| i == 2).unwrap() as u32, + 2 + ); + }); + } + + #[test] + #[should_panic(expected = "bad target index")] + fn retracting_inactive_voter_with_bad_target_index_should_panic() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + Council::submit_candidacy(&2, 0); + Council::set_approvals(&2, vec![true], 0); + Council::end_block(System::block_number()); + + System::set_block_number(6); + Council::present_winner(&4, 2, 8, 0); + Council::end_block(System::block_number()); + + System::set_block_number(8); + Council::submit_candidacy(&5, 0); + Council::set_approvals(&5, vec![true], 1); + Council::end_block(System::block_number()); + + System::set_block_number(10); + Council::present_winner(&4, 5, 38, 1); + Council::end_block(System::block_number()); + + Council::reap_inactive_voter(&2, + Council::voters().iter().position(|&i| i == 2).unwrap() as u32, + 2, 42, + 2 + ); + }); + } + + #[test] + fn attempting_to_retract_active_voter_should_slash_reporter() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + Council::submit_candidacy(&2, 0); + Council::submit_candidacy(&3, 1); + Council::submit_candidacy(&4, 2); + Council::submit_candidacy(&5, 3); + Council::set_approvals(&2, vec![true, false, false, false], 0); + Council::set_approvals(&3, vec![false, true, false, false], 0); + Council::set_approvals(&4, vec![false, false, true, false], 0); + Council::set_approvals(&5, vec![false, false, false, true], 0); + Council::end_block(System::block_number()); + + System::set_block_number(6); + Council::present_winner(&4, 2, 11, 0); + Council::present_winner(&4, 3, 21, 0); + Council::present_winner(&4, 4, 31, 0); + Council::present_winner(&4, 5, 41, 0); + Council::end_block(System::block_number()); + + System::set_block_number(8); + Council::set_desired_seats(3); + Council::end_block(System::block_number()); + + System::set_block_number(10); + Council::present_winner(&4, 2, 11, 1); + Council::present_winner(&4, 3, 21, 1); + Council::end_block(System::block_number()); + + Council::reap_inactive_voter(&4, + Council::voters().iter().position(|&i| i == 4).unwrap() as u32, + 2, Council::voters().iter().position(|&i| i == 2).unwrap() as u32, + 2 + ); + + assert_eq!(Council::voters(), vec![2, 3, 5]); + assert_eq!(Council::approvals_of(4).len(), 0); + assert_eq!(Staking::balance(&4), 37); + }); + } + + #[test] + #[should_panic(expected = "reaper must be a voter")] + fn attempting_to_retract_inactive_voter_by_nonvoter_should_panic() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + Council::submit_candidacy(&2, 0); + Council::set_approvals(&2, vec![true], 0); + Council::end_block(System::block_number()); + + System::set_block_number(6); + Council::present_winner(&4, 2, 11, 0); + Council::end_block(System::block_number()); + + System::set_block_number(8); + Council::submit_candidacy(&5, 0); + Council::set_approvals(&5, vec![true], 1); + Council::end_block(System::block_number()); + + System::set_block_number(10); + Council::present_winner(&4, 5, 41, 1); + Council::end_block(System::block_number()); + + Council::reap_inactive_voter(&4, + 0, + 2, Council::voters().iter().position(|&i| i == 2).unwrap() as u32, + 2 + ); + }); + } + + #[test] + #[should_panic(expected = "candidate not worthy of leaderboard")] + fn presenting_loser_should_panic() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + Council::submit_candidacy(&1, 0); + Council::set_approvals(&6, vec![true], 0); + Council::submit_candidacy(&2, 1); + Council::set_approvals(&2, vec![false, true], 0); + Council::submit_candidacy(&3, 2); + Council::set_approvals(&3, vec![false, false, true], 0); + Council::submit_candidacy(&4, 3); + Council::set_approvals(&4, vec![false, false, false, true], 0); + Council::submit_candidacy(&5, 4); + Council::set_approvals(&5, vec![false, false, false, false, true], 0); + Council::end_block(System::block_number()); + + System::set_block_number(6); + Council::present_winner(&4, 1, 60, 0); + Council::present_winner(&4, 3, 21, 0); + Council::present_winner(&4, 4, 31, 0); + Council::present_winner(&4, 5, 41, 0); + Council::present_winner(&4, 2, 11, 0); + }); + } + + #[test] + fn presenting_loser_first_should_not_matter() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + Council::submit_candidacy(&1, 0); + Council::set_approvals(&6, vec![true], 0); + Council::submit_candidacy(&2, 1); + Council::set_approvals(&2, vec![false, true], 0); + Council::submit_candidacy(&3, 2); + Council::set_approvals(&3, vec![false, false, true], 0); + Council::submit_candidacy(&4, 3); + Council::set_approvals(&4, vec![false, false, false, true], 0); + Council::submit_candidacy(&5, 4); + Council::set_approvals(&5, vec![false, false, false, false, true], 0); + Council::end_block(System::block_number()); + + System::set_block_number(6); + Council::present_winner(&4, 2, 11, 0); + Council::present_winner(&4, 1, 60, 0); + Council::present_winner(&4, 3, 21, 0); + Council::present_winner(&4, 4, 31, 0); + Council::present_winner(&4, 5, 41, 0); + + assert_eq!(Council::leaderboard(), Some(vec![ + (21, 3), + (31, 4), + (41, 5), + (60, 1) + ])); + }); + } + + #[test] + #[should_panic(expected = "cannot present outside of presentation period")] + fn present_panics_outside_of_presentation_period() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + assert!(!Council::presentation_active()); + Council::present_winner(&5, 5, 1, 0); + }); + } + + #[test] + #[should_panic(expected = "index not current")] + fn present_panics_with_invalid_vote_index() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + Council::submit_candidacy(&2, 0); + Council::submit_candidacy(&5, 1); + Council::set_approvals(&2, vec![true, false], 0); + Council::set_approvals(&5, vec![false, true], 0); + Council::end_block(System::block_number()); + + System::set_block_number(6); + Council::present_winner(&4, 2, 11, 1); + }); + } + + #[test] + #[should_panic(expected = "presenter must have sufficient slashable funds")] + fn present_panics_when_presenter_is_poor() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + assert!(!Council::presentation_active()); + + Council::submit_candidacy(&1, 0); + Council::submit_candidacy(&5, 1); + Council::set_approvals(&2, vec![true, false], 0); + Council::set_approvals(&5, vec![false, true], 0); + Council::end_block(System::block_number()); + + System::set_block_number(6); + assert_eq!(Staking::balance(&1), 1); + Council::present_winner(&1, 1, 30, 0); + }); + } + + #[test] + fn invalid_present_tally_should_slash() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + assert!(!Council::presentation_active()); + assert_eq!(Staking::balance(&4), 40); + + Council::submit_candidacy(&2, 0); + Council::submit_candidacy(&5, 1); + Council::set_approvals(&2, vec![true, false], 0); + Council::set_approvals(&5, vec![false, true], 0); + Council::end_block(System::block_number()); + + System::set_block_number(6); + Council::present_winner(&4, 2, 80, 0); + + assert_eq!(Staking::balance(&4), 38); + }); + } + + #[test] + fn runners_up_should_be_kept() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + assert!(!Council::presentation_active()); + + Council::submit_candidacy(&1, 0); + Council::set_approvals(&6, vec![true], 0); + Council::submit_candidacy(&2, 1); + Council::set_approvals(&2, vec![false, true], 0); + Council::submit_candidacy(&3, 2); + Council::set_approvals(&3, vec![false, false, true], 0); + Council::submit_candidacy(&4, 3); + Council::set_approvals(&4, vec![false, false, false, true], 0); + Council::submit_candidacy(&5, 4); + Council::set_approvals(&5, vec![false, false, false, false, true], 0); + + Council::end_block(System::block_number()); + + System::set_block_number(6); + assert!(Council::presentation_active()); + Council::present_winner(&4, 1, 60, 0); + assert_eq!(Council::leaderboard(), Some(vec![ + (0, 0), + (0, 0), + (0, 0), + (60, 1) + ])); + Council::present_winner(&4, 3, 21, 0); + Council::present_winner(&4, 4, 31, 0); + Council::present_winner(&4, 5, 41, 0); + assert_eq!(Council::leaderboard(), Some(vec![ + (21, 3), + (31, 4), + (41, 5), + (60, 1) + ])); + + Council::end_block(System::block_number()); + + assert!(!Council::presentation_active()); + assert_eq!(Council::active_council(), vec![(1, 11), (5, 11)]); + + assert!(!Council::is_a_candidate(&1)); + assert!(!Council::is_a_candidate(&5)); + assert!(!Council::is_a_candidate(&2)); + assert!(Council::is_a_candidate(&3)); + assert!(Council::is_a_candidate(&4)); + assert_eq!(Council::vote_index(), 1); + assert_eq!(Council::voter_last_active(2), Some(0)); + assert_eq!(Council::voter_last_active(3), Some(0)); + assert_eq!(Council::voter_last_active(4), Some(0)); + assert_eq!(Council::voter_last_active(5), Some(0)); + assert_eq!(Council::voter_last_active(6), Some(0)); + assert_eq!(Council::candidate_reg_info(3), Some((0, 2))); + assert_eq!(Council::candidate_reg_info(4), Some((0, 3))); + }); + } + + #[test] + fn second_tally_should_use_runners_up() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + Council::submit_candidacy(&1, 0); + Council::set_approvals(&6, vec![true], 0); + Council::submit_candidacy(&2, 1); + Council::set_approvals(&2, vec![false, true], 0); + Council::submit_candidacy(&3, 2); + Council::set_approvals(&3, vec![false, false, true], 0); + Council::submit_candidacy(&4, 3); + Council::set_approvals(&4, vec![false, false, false, true], 0); + Council::submit_candidacy(&5, 4); + Council::set_approvals(&5, vec![false, false, false, false, true], 0); + Council::end_block(System::block_number()); + + System::set_block_number(6); + Council::present_winner(&4, 1, 60, 0); + Council::present_winner(&4, 3, 21, 0); + Council::present_winner(&4, 4, 31, 0); + Council::present_winner(&4, 5, 41, 0); + Council::end_block(System::block_number()); + + System::set_block_number(8); + Council::set_approvals(&6, vec![false, false, true, false], 1); + Council::set_desired_seats(3); + Council::end_block(System::block_number()); + + System::set_block_number(10); + Council::present_winner(&4, 3, 81, 1); + Council::present_winner(&4, 4, 31, 1); + Council::end_block(System::block_number()); + + assert!(!Council::presentation_active()); + assert_eq!(Council::active_council(), vec![(1, 11), (5, 11), (3, 15)]); + + assert!(!Council::is_a_candidate(&1)); + assert!(!Council::is_a_candidate(&2)); + assert!(!Council::is_a_candidate(&3)); + assert!(!Council::is_a_candidate(&5)); + assert!(Council::is_a_candidate(&4)); + assert_eq!(Council::vote_index(), 2); + assert_eq!(Council::voter_last_active(2), Some(0)); + assert_eq!(Council::voter_last_active(3), Some(0)); + assert_eq!(Council::voter_last_active(4), Some(0)); + assert_eq!(Council::voter_last_active(5), Some(0)); + assert_eq!(Council::voter_last_active(6), Some(1)); + + assert_eq!(Council::candidate_reg_info(4), Some((0, 3))); + }); + } +} diff --git a/substrate/substrate/runtime/council/src/voting.rs b/substrate/substrate/runtime/council/src/voting.rs new file mode 100644 index 0000000000..13cce3f915 --- /dev/null +++ b/substrate/substrate/runtime/council/src/voting.rs @@ -0,0 +1,457 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Demo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Demo. If not, see . + +//! Council voting system. + +use rstd::prelude::*; +use rstd::borrow::Borrow; +use primitives::traits::{Executable, RefInto}; +use runtime_io::Hashing; +use runtime_support::{StorageValue, StorageMap, IsSubType}; +use {system, democracy}; +use super::{Trait, Module as Council}; + +decl_module! { + pub struct Module; + pub enum Call where aux: T::PublicAux { + fn propose(aux, proposal: Box) = 0; + fn vote(aux, proposal: T::Hash, approve: bool) = 1; + fn veto(aux, proposal_hash: T::Hash) = 2; + } + pub enum PrivCall { + fn set_cooloff_period(blocks: T::BlockNumber) = 0; + fn set_voting_period(blocks: T::BlockNumber) = 1; + } +} + +decl_storage! { + trait Store for Module; + + pub CooloffPeriod get(cooloff_period): b"cov:cooloff" => required T::BlockNumber; + pub VotingPeriod get(voting_period): b"cov:period" => required T::BlockNumber; + pub Proposals get(proposals): b"cov:prs" => default Vec<(T::BlockNumber, T::Hash)>; // ordered by expiry. + pub ProposalOf get(proposal_of): b"cov:pro" => map [ T::Hash => T::Proposal ]; + pub ProposalVoters get(proposal_voters): b"cov:voters:" => default map [ T::Hash => Vec ]; + pub CouncilVoteOf get(vote_of): b"cov:vote:" => map [ (T::Hash, T::AccountId) => bool ]; + pub VetoedProposal get(veto_of): b"cov:veto:" => map [ T::Hash => (T::BlockNumber, Vec) ]; +} + +impl Module { + pub fn is_vetoed>(proposal: B) -> bool { + Self::veto_of(proposal.borrow()) + .map(|(expiry, _): (T::BlockNumber, Vec)| >::block_number() < expiry) + .unwrap_or(false) + } + + pub fn will_still_be_councillor_at(who: &T::AccountId, n: T::BlockNumber) -> bool { + >::active_council().iter() + .find(|&&(ref a, _)| a == who) + .map(|&(_, expires)| expires > n) + .unwrap_or(false) + } + + pub fn is_councillor(who: &T::AccountId) -> bool { + >::active_council().iter() + .any(|&(ref a, _)| a == who) + } + + pub fn tally(proposal_hash: &T::Hash) -> (u32, u32, u32) { + Self::generic_tally(proposal_hash, |w: &T::AccountId, p: &T::Hash| Self::vote_of((*p, w.clone()))) + } + + // Dispatch + fn propose(aux: &T::PublicAux, proposal: Box) { + let expiry = >::block_number() + Self::voting_period(); + assert!(Self::will_still_be_councillor_at(aux.ref_into(), expiry)); + + let proposal_hash = T::Hashing::hash_of(&proposal); + + assert!(!Self::is_vetoed(&proposal_hash)); + + let mut proposals = Self::proposals(); + proposals.push((expiry, proposal_hash)); + proposals.sort_by_key(|&(expiry, _)| expiry); + Self::set_proposals(&proposals); + + >::insert(proposal_hash, *proposal); + >::insert(proposal_hash, vec![aux.ref_into().clone()]); + >::insert((proposal_hash, aux.ref_into().clone()), true); + } + + fn vote(aux: &T::PublicAux, proposal: T::Hash, approve: bool) { + if Self::vote_of((proposal, aux.ref_into().clone())).is_none() { + let mut voters = Self::proposal_voters(&proposal); + voters.push(aux.ref_into().clone()); + >::insert(proposal, voters); + } + >::insert((proposal, aux.ref_into().clone()), approve); + } + + fn veto(aux: &T::PublicAux, proposal_hash: T::Hash) { + assert!(Self::is_councillor(aux.ref_into()), "only councillors may veto council proposals"); + assert!(>::exists(&proposal_hash), "proposal must exist to be vetoed"); + + let mut existing_vetoers = Self::veto_of(&proposal_hash) + .map(|pair| pair.1) + .unwrap_or_else(Vec::new); + let insert_position = existing_vetoers.binary_search(aux.ref_into()) + .expect_err("a councillor may not veto a proposal twice"); + existing_vetoers.insert(insert_position, aux.ref_into().clone()); + Self::set_veto_of(&proposal_hash, >::block_number() + Self::cooloff_period(), existing_vetoers); + + Self::set_proposals(&Self::proposals().into_iter().filter(|&(_, h)| h != proposal_hash).collect::>()); + >::remove(proposal_hash); + >::remove(proposal_hash); + for (c, _) in >::active_council() { + >::remove((proposal_hash, c)); + } + } + + fn set_cooloff_period(blocks: T::BlockNumber) { + >::put(blocks); + } + + fn set_voting_period(blocks: T::BlockNumber) { + >::put(blocks); + } + + // private + + + fn set_veto_of(proposal: &T::Hash, expiry: T::BlockNumber, vetoers: Vec) { + >::insert(proposal, (expiry, vetoers)); + } + + fn kill_veto_of(proposal: &T::Hash) { + >::remove(proposal); + } + + fn take_tally(proposal_hash: &T::Hash) -> (u32, u32, u32) { + Self::generic_tally(proposal_hash, |w: &T::AccountId, p: &T::Hash| >::take((*p, w.clone()))) + } + + fn generic_tally Option>(proposal_hash: &T::Hash, vote_of: F) -> (u32, u32, u32) { + let c = >::active_council(); + let (approve, reject) = c.iter() + .filter_map(|&(ref a, _)| vote_of(a, proposal_hash)) + .map(|approve| if approve { (1, 0) } else { (0, 1) }) + .fold((0, 0), |(a, b), (c, d)| (a + c, b + d)); + (approve, reject, c.len() as u32 - approve - reject) + } + + fn set_proposals(p: &Vec<(T::BlockNumber, T::Hash)>) { + >::put(p); + } + + fn take_proposal_if_expiring_at(n: T::BlockNumber) -> Option<(T::Proposal, T::Hash)> { + let proposals = Self::proposals(); + match proposals.first() { + Some(&(expiry, hash)) if expiry == n => { + // yes this is horrible, but fixing it will need substantial work in storage. + Self::set_proposals(&proposals[1..].to_vec()); + let proposal = >::take(hash).expect("all queued proposal hashes must have associated proposals"); + Some((proposal, hash)) + } + _ => None, + } + } + + fn end_block(now: T::BlockNumber) { + while let Some((proposal, proposal_hash)) = Self::take_proposal_if_expiring_at(now) { + let tally = Self::take_tally(&proposal_hash); + if let Some(&democracy::PrivCall::cancel_referendum(ref_index)) = IsSubType::>::is_sub_type(&proposal) { + if let (_, 0, 0) = tally { + >::internal_cancel_referendum(ref_index); + } + } else { + if tally.0 > tally.1 + tally.2 { + Self::kill_veto_of(&proposal_hash); + match tally { + (_, 0, 0) => >::internal_start_referendum(proposal, democracy::VoteThreshold::SuperMajorityAgainst), + _ => >::internal_start_referendum(proposal, democracy::VoteThreshold::SimpleMajority), + }; + } + } + } + } +} + +impl Executable for Council { + fn execute() { + let n = >::block_number(); + Self::end_block(n); + >::end_block(n); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use ::tests::*; + use runtime_support::Hashable; + use democracy::VoteThreshold; + + type CouncilVoting = super::Module; + + #[test] + fn basic_environment_works() { + with_externalities(&mut new_test_ext(true), || { + System::set_block_number(1); + assert_eq!(Staking::bonding_duration(), 0); + assert_eq!(CouncilVoting::cooloff_period(), 2); + assert_eq!(CouncilVoting::voting_period(), 1); + assert_eq!(CouncilVoting::will_still_be_councillor_at(&1, 1), true); + assert_eq!(CouncilVoting::will_still_be_councillor_at(&1, 10), false); + assert_eq!(CouncilVoting::will_still_be_councillor_at(&4, 10), false); + assert_eq!(CouncilVoting::is_councillor(&1), true); + assert_eq!(CouncilVoting::is_councillor(&4), false); + assert_eq!(CouncilVoting::proposals(), Vec::<(u64, H256)>::new()); + assert_eq!(CouncilVoting::proposal_voters(H256::default()), Vec::::new()); + assert_eq!(CouncilVoting::is_vetoed(&H256::default()), false); + assert_eq!(CouncilVoting::vote_of((H256::default(), 1)), None); + assert_eq!(CouncilVoting::tally(&H256::default()), (0, 0, 3)); + }); + } + + fn bonding_duration_proposal(value: u64) -> Proposal { + Proposal::Staking(staking::PrivCall::set_bonding_duration(value)) + } + + fn cancel_referendum_proposal(id: u32) -> Proposal { + Proposal::Democracy(democracy::PrivCall::cancel_referendum(id)) + } + + #[test] + fn referendum_cancellation_should_work_when_unanimous() { + with_externalities(&mut new_test_ext(true), || { + System::set_block_number(1); + let proposal = bonding_duration_proposal(42); + Democracy::internal_start_referendum(proposal.clone(), VoteThreshold::SuperMajorityApprove); + assert_eq!(Democracy::active_referendums(), vec![(0, 4, proposal, VoteThreshold::SuperMajorityApprove)]); + + let cancellation = cancel_referendum_proposal(0); + let hash = cancellation.blake2_256().into(); + CouncilVoting::propose(&1, Box::new(cancellation)); + CouncilVoting::vote(&2, hash, true); + CouncilVoting::vote(&3, hash, true); + assert_eq!(CouncilVoting::proposals(), vec![(2, hash)]); + CouncilVoting::end_block(System::block_number()); + + System::set_block_number(2); + CouncilVoting::end_block(System::block_number()); + assert_eq!(Democracy::active_referendums(), vec![]); + assert_eq!(Staking::bonding_duration(), 0); + }); + } + + #[test] + fn referendum_cancellation_should_fail_when_not_unanimous() { + with_externalities(&mut new_test_ext(true), || { + System::set_block_number(1); + let proposal = bonding_duration_proposal(42); + Democracy::internal_start_referendum(proposal.clone(), VoteThreshold::SuperMajorityApprove); + + let cancellation = cancel_referendum_proposal(0); + let hash = cancellation.blake2_256().into(); + CouncilVoting::propose(&1, Box::new(cancellation)); + CouncilVoting::vote(&2, hash, true); + CouncilVoting::vote(&3, hash, false); + CouncilVoting::end_block(System::block_number()); + + System::set_block_number(2); + CouncilVoting::end_block(System::block_number()); + assert_eq!(Democracy::active_referendums(), vec![(0, 4, proposal, VoteThreshold::SuperMajorityApprove)]); + }); + } + + #[test] + fn referendum_cancellation_should_fail_when_abstentions() { + with_externalities(&mut new_test_ext(true), || { + System::set_block_number(1); + let proposal = bonding_duration_proposal(42); + Democracy::internal_start_referendum(proposal.clone(), VoteThreshold::SuperMajorityApprove); + + let cancellation = cancel_referendum_proposal(0); + let hash = cancellation.blake2_256().into(); + CouncilVoting::propose(&1, Box::new(cancellation)); + CouncilVoting::vote(&2, hash, true); + CouncilVoting::end_block(System::block_number()); + + System::set_block_number(2); + CouncilVoting::end_block(System::block_number()); + assert_eq!(Democracy::active_referendums(), vec![(0, 4, proposal, VoteThreshold::SuperMajorityApprove)]); + }); + } + + #[test] + fn veto_should_work() { + with_externalities(&mut new_test_ext(true), || { + System::set_block_number(1); + let proposal = bonding_duration_proposal(42); + let hash = proposal.blake2_256().into(); + CouncilVoting::propose(&1, Box::new(proposal.clone())); + CouncilVoting::veto(&2, hash); + assert_eq!(CouncilVoting::proposals().len(), 0); + assert_eq!(Democracy::active_referendums().len(), 0); + }); + } + + #[test] + #[should_panic] + fn double_veto_should_panic() { + with_externalities(&mut new_test_ext(true), || { + System::set_block_number(1); + let proposal = bonding_duration_proposal(42); + let hash = proposal.blake2_256().into(); + CouncilVoting::propose(&1, Box::new(proposal.clone())); + CouncilVoting::veto(&2, hash); + + System::set_block_number(3); + CouncilVoting::propose(&1, Box::new(proposal.clone())); + CouncilVoting::veto(&2, hash); + }); + } + + #[test] + #[should_panic] + fn retry_in_cooloff_should_panic() { + with_externalities(&mut new_test_ext(true), || { + System::set_block_number(1); + let proposal = bonding_duration_proposal(42); + let hash = proposal.blake2_256().into(); + CouncilVoting::propose(&1, Box::new(proposal.clone())); + CouncilVoting::veto(&2, hash); + + System::set_block_number(2); + CouncilVoting::propose(&1, Box::new(proposal.clone())); + }); + } + + #[test] + fn retry_after_cooloff_should_work() { + with_externalities(&mut new_test_ext(true), || { + System::set_block_number(1); + let proposal = bonding_duration_proposal(42); + let hash = proposal.blake2_256().into(); + CouncilVoting::propose(&1, Box::new(proposal.clone())); + CouncilVoting::veto(&2, hash); + + System::set_block_number(3); + CouncilVoting::propose(&1, Box::new(proposal.clone())); + CouncilVoting::vote(&2, hash, false); + CouncilVoting::vote(&3, hash, true); + CouncilVoting::end_block(System::block_number()); + + System::set_block_number(4); + CouncilVoting::end_block(System::block_number()); + assert_eq!(CouncilVoting::proposals().len(), 0); + assert_eq!(Democracy::active_referendums(), vec![(0, 7, bonding_duration_proposal(42), VoteThreshold::SimpleMajority)]); + }); + } + + #[test] + fn alternative_double_veto_should_work() { + with_externalities(&mut new_test_ext(true), || { + System::set_block_number(1); + let proposal = bonding_duration_proposal(42); + let hash = proposal.blake2_256().into(); + CouncilVoting::propose(&1, Box::new(proposal.clone())); + CouncilVoting::veto(&2, hash); + + System::set_block_number(3); + CouncilVoting::propose(&1, Box::new(proposal.clone())); + CouncilVoting::veto(&3, hash); + assert_eq!(CouncilVoting::proposals().len(), 0); + assert_eq!(Democracy::active_referendums().len(), 0); + }); + } + + #[test] + fn simple_propose_should_work() { + with_externalities(&mut new_test_ext(true), || { + System::set_block_number(1); + let proposal = bonding_duration_proposal(42); + let hash = proposal.blake2_256().into(); + CouncilVoting::propose(&1, Box::new(proposal.clone())); + assert_eq!(CouncilVoting::proposals().len(), 1); + assert_eq!(CouncilVoting::proposal_voters(&hash), vec![1]); + assert_eq!(CouncilVoting::vote_of((hash, 1)), Some(true)); + assert_eq!(CouncilVoting::tally(&hash), (1, 0, 2)); + }); + } + + #[test] + fn unvoted_proposal_should_expire_without_action() { + with_externalities(&mut new_test_ext(true), || { + System::set_block_number(1); + let proposal = bonding_duration_proposal(42); + CouncilVoting::propose(&1, Box::new(proposal.clone())); + assert_eq!(CouncilVoting::tally(&proposal.blake2_256().into()), (1, 0, 2)); + CouncilVoting::end_block(System::block_number()); + + System::set_block_number(2); + CouncilVoting::end_block(System::block_number()); + assert_eq!(CouncilVoting::proposals().len(), 0); + assert_eq!(Democracy::active_referendums().len(), 0); + }); + } + + #[test] + fn unanimous_proposal_should_expire_with_biased_referendum() { + with_externalities(&mut new_test_ext(true), || { + System::set_block_number(1); + let proposal = bonding_duration_proposal(42); + CouncilVoting::propose(&1, Box::new(proposal.clone())); + CouncilVoting::vote(&2, proposal.blake2_256().into(), true); + CouncilVoting::vote(&3, proposal.blake2_256().into(), true); + assert_eq!(CouncilVoting::tally(&proposal.blake2_256().into()), (3, 0, 0)); + CouncilVoting::end_block(System::block_number()); + + System::set_block_number(2); + CouncilVoting::end_block(System::block_number()); + assert_eq!(CouncilVoting::proposals().len(), 0); + assert_eq!(Democracy::active_referendums(), vec![(0, 5, proposal, VoteThreshold::SuperMajorityAgainst)]); + }); + } + + #[test] + fn majority_proposal_should_expire_with_unbiased_referendum() { + with_externalities(&mut new_test_ext(true), || { + System::set_block_number(1); + let proposal = bonding_duration_proposal(42); + CouncilVoting::propose(&1, Box::new(proposal.clone())); + CouncilVoting::vote(&2, proposal.blake2_256().into(), true); + CouncilVoting::vote(&3, proposal.blake2_256().into(), false); + assert_eq!(CouncilVoting::tally(&proposal.blake2_256().into()), (2, 1, 0)); + CouncilVoting::end_block(System::block_number()); + + System::set_block_number(2); + CouncilVoting::end_block(System::block_number()); + assert_eq!(CouncilVoting::proposals().len(), 0); + assert_eq!(Democracy::active_referendums(), vec![(0, 5, proposal, VoteThreshold::SimpleMajority)]); + }); + } + + #[test] + #[should_panic] + fn propose_by_public_should_panic() { + with_externalities(&mut new_test_ext(true), || { + System::set_block_number(1); + let proposal = bonding_duration_proposal(42); + CouncilVoting::propose(&4, Box::new(proposal)); + }); + } +} diff --git a/substrate/substrate/runtime/democracy/Cargo.toml b/substrate/substrate/runtime/democracy/Cargo.toml new file mode 100644 index 0000000000..74007bb9e0 --- /dev/null +++ b/substrate/substrate/runtime/democracy/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "substrate-runtime-democracy" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +hex-literal = "0.1.0" +serde = { version = "1.0", default_features = false } +safe-mix = { path = "../../../safe-mix", default_features = false} +substrate-codec = { path = "../../codec", default_features = false } +substrate-primitives = { path = "../../primitives", default_features = false } +substrate-runtime-std = { path = "../../runtime-std", default_features = false } +substrate-runtime-io = { path = "../../runtime-io", default_features = false } +substrate-runtime-support = { path = "../../runtime-support", default_features = false } +substrate-runtime-primitives = { path = "../primitives", default_features = false } +substrate-runtime-consensus = { path = "../consensus", default_features = false } +substrate-runtime-session = { path = "../session", default_features = false } +substrate-runtime-staking = { path = "../staking", default_features = false } +substrate-runtime-system = { path = "../system", default_features = false } + +[features] +default = ["std"] +std = [ + "serde/std", + "safe-mix/std", + "substrate-codec/std", + "substrate-primitives/std", + "substrate-runtime-std/std", + "substrate-runtime-io/std", + "substrate-runtime-support/std", + "substrate-runtime-primitives/std", + "substrate-runtime-consensus/std", + "substrate-runtime-session/std", + "substrate-runtime-staking/std", + "substrate-runtime-system/std", +] diff --git a/substrate/substrate/runtime/democracy/src/lib.rs b/substrate/substrate/runtime/democracy/src/lib.rs new file mode 100644 index 0000000000..2ffe1441a3 --- /dev/null +++ b/substrate/substrate/runtime/democracy/src/lib.rs @@ -0,0 +1,659 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Demo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Demo. If not, see . + +//! Democratic system: Handles administration of general stakeholder voting. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +extern crate serde; + +#[macro_use] +extern crate substrate_runtime_support as runtime_support; + +#[cfg(feature = "std")] +extern crate substrate_primitives; + +#[macro_use] +extern crate substrate_runtime_std as rstd; + +extern crate substrate_codec as codec; +extern crate substrate_runtime_io as runtime_io; +extern crate substrate_runtime_primitives as primitives; +extern crate substrate_runtime_consensus as consensus; +extern crate substrate_runtime_session as session; +extern crate substrate_runtime_staking as staking; +extern crate substrate_runtime_system as system; + +use rstd::prelude::*; +use primitives::traits::{Zero, Executable, RefInto, As}; +use runtime_support::{StorageValue, StorageMap, Parameter, Dispatchable, IsSubType}; + +mod vote_threshold; +pub use vote_threshold::{Approved, VoteThreshold}; + +/// A proposal index. +pub type PropIndex = u32; +/// A referendum index. +pub type ReferendumIndex = u32; + +pub trait Trait: staking::Trait + Sized { + type Proposal: Parameter + Dispatchable + IsSubType>; +} + +decl_module! { + pub struct Module; + pub enum Call where aux: T::PublicAux { + fn propose(aux, proposal: Box, value: T::Balance) = 0; + fn second(aux, proposal: PropIndex) = 1; + fn vote(aux, ref_index: ReferendumIndex, approve_proposal: bool) = 2; + } + pub enum PrivCall { + fn start_referendum(proposal: Box, vote_threshold: VoteThreshold) = 0; + fn cancel_referendum(ref_index: ReferendumIndex) = 1; + } +} + +decl_storage! { + trait Store for Module; + + // The number of (public) proposals that have been made so far. + pub PublicPropCount get(public_prop_count): b"dem:ppc" => default PropIndex; + // The public proposals. Unsorted. + pub PublicProps get(public_props): b"dem:pub" => default Vec<(PropIndex, T::Proposal, T::AccountId)>; + // Those who have locked a deposit. + pub DepositOf get(deposit_of): b"dem:dep:" => map [ PropIndex => (T::Balance, Vec) ]; + // How often (in blocks) new public referenda are launched. + pub LaunchPeriod get(launch_period): b"dem:lau" => required T::BlockNumber; + // The minimum amount to be used as a deposit for a public referendum proposal. + pub MinimumDeposit get(minimum_deposit): b"dem:min" => required T::Balance; + + // How often (in blocks) to check for new votes. + pub VotingPeriod get(voting_period): b"dem:per" => required T::BlockNumber; + + // The next free referendum index, aka the number of referendums started so far. + pub ReferendumCount get(referendum_count): b"dem:rco" => default ReferendumIndex; + // The next referendum index that should be tallied. + pub NextTally get(next_tally): b"dem:nxt" => default ReferendumIndex; + // Information concerning any given referendum. + pub ReferendumInfoOf get(referendum_info): b"dem:pro:" => map [ ReferendumIndex => (T::BlockNumber, T::Proposal, VoteThreshold) ]; + + // Get the voters for the current proposal. + pub VotersFor get(voters_for): b"dem:vtr:" => default map [ ReferendumIndex => Vec ]; + + // Get the vote, if Some, of `who`. + pub VoteOf get(vote_of): b"dem:vot:" => map [ (ReferendumIndex, T::AccountId) => bool ]; +} + +impl Module { + + // exposed immutables. + + /// Get the amount locked in support of `proposal`; false if proposal isn't a valid proposal + /// index. + pub fn locked_for(proposal: PropIndex) -> Option { + Self::deposit_of(proposal).map(|(d, l)| d * T::Balance::sa(l.len())) + } + + /// Return true if `ref_index` is an on-going referendum. + pub fn is_active_referendum(ref_index: ReferendumIndex) -> bool { + >::exists(ref_index) + } + + /// Get all referendums currently active. + pub fn active_referendums() -> Vec<(ReferendumIndex, T::BlockNumber, T::Proposal, VoteThreshold)> { + let next = Self::next_tally(); + let last = Self::referendum_count(); + (next..last).into_iter() + .filter_map(|i| Self::referendum_info(i).map(|(n, p, t)| (i, n, p, t))) + .collect() + } + + /// Get all referendums ready for tally at block `n`. + pub fn maturing_referendums_at(n: T::BlockNumber) -> Vec<(ReferendumIndex, T::BlockNumber, T::Proposal, VoteThreshold)> { + let next = Self::next_tally(); + let last = Self::referendum_count(); + (next..last).into_iter() + .filter_map(|i| Self::referendum_info(i).map(|(n, p, t)| (i, n, p, t))) + .take_while(|&(_, block_number, _, _)| block_number == n) + .collect() + } + + /// Get the voters for the current proposal. + pub fn tally(ref_index: ReferendumIndex) -> (T::Balance, T::Balance) { + Self::voters_for(ref_index).iter() + .map(|a| (>::balance(a), Self::vote_of((ref_index, a.clone())).expect("all items come from `voters`; for an item to be in `voters` there must be a vote registered; qed"))) + .map(|(bal, vote)| if vote { (bal, Zero::zero()) } else { (Zero::zero(), bal) }) + .fold((Zero::zero(), Zero::zero()), |(a, b), (c, d)| (a + c, b + d)) + } + + // dispatching. + + /// Propose a sensitive action to be taken. + fn propose(aux: &T::PublicAux, proposal: Box, value: T::Balance) { + assert!(value >= Self::minimum_deposit()); + assert!(>::deduct_unbonded(aux.ref_into(), value)); + + let index = Self::public_prop_count(); + >::put(index + 1); + >::insert(index, (value, vec![aux.ref_into().clone()])); + + let mut props = Self::public_props(); + props.push((index, (*proposal).clone(), aux.ref_into().clone())); + >::put(props); + } + + /// Propose a sensitive action to be taken. + fn second(aux: &T::PublicAux, proposal: PropIndex) { + let mut deposit = Self::deposit_of(proposal).expect("can only second an existing proposal"); + assert!(>::deduct_unbonded(aux.ref_into(), deposit.0)); + + deposit.1.push(aux.ref_into().clone()); + >::insert(proposal, deposit); + } + + /// Vote in a referendum. If `approve_proposal` is true, the vote is to enact the proposal; + /// false would be a vote to keep the status quo.. + fn vote(aux: &T::PublicAux, ref_index: ReferendumIndex, approve_proposal: bool) { + if !Self::is_active_referendum(ref_index) { + panic!("vote given for invalid referendum.") + } + if >::balance(aux.ref_into()).is_zero() { + panic!("transactor must have balance to signal approval."); + } + if !>::exists(&(ref_index, aux.ref_into().clone())) { + let mut voters = Self::voters_for(ref_index); + voters.push(aux.ref_into().clone()); + >::insert(ref_index, voters); + } + >::insert(&(ref_index, aux.ref_into().clone()), approve_proposal); + } + + /// Start a referendum. + fn start_referendum(proposal: Box, vote_threshold: VoteThreshold) { + Self::inject_referendum(>::block_number() + Self::voting_period(), *proposal, vote_threshold); + } + + /// Remove a referendum. + fn cancel_referendum(ref_index: ReferendumIndex) { + Self::clear_referendum(ref_index); + } + + // exposed mutables. + + /// Start a referendum. Can be called directly by the council. + pub fn internal_start_referendum(proposal: T::Proposal, vote_threshold: VoteThreshold) { + >::inject_referendum(>::block_number() + >::voting_period(), proposal, vote_threshold); + } + + /// Remove a referendum. Can be called directly by the council. + pub fn internal_cancel_referendum(ref_index: ReferendumIndex) { + >::clear_referendum(ref_index); + } + + // private. + + /// Start a referendum + fn inject_referendum( + end: T::BlockNumber, + proposal: T::Proposal, + vote_threshold: VoteThreshold + ) -> ReferendumIndex { + let ref_index = Self::referendum_count(); + if ref_index > 0 && Self::referendum_info(ref_index - 1).map(|i| i.0 > end).unwrap_or(false) { + panic!("Cannot inject a referendum that ends earlier than preceeding referendum"); + } + + >::put(ref_index + 1); + >::insert(ref_index, (end, proposal, vote_threshold)); + ref_index + } + + /// Remove all info on a referendum. + fn clear_referendum(ref_index: ReferendumIndex) { + >::remove(ref_index); + >::remove(ref_index); + for v in Self::voters_for(ref_index) { + >::remove((ref_index, v)); + } + } + + /// Current era is ending; we should finish up any proposals. + fn end_block(now: T::BlockNumber) { + // pick out another public referendum if it's time. + if (now % Self::launch_period()).is_zero() { + let mut public_props = Self::public_props(); + if let Some((winner_index, _)) = public_props.iter() + .enumerate() + .max_by_key(|x| Self::locked_for((x.1).0).expect("All current public proposals have an amount locked")) + { + let (prop_index, proposal, _) = public_props.swap_remove(winner_index); + let (deposit, depositors): (T::Balance, Vec) = + >::take(prop_index).expect("depositors always exist for current proposals"); + // refund depositors + for d in &depositors { + >::refund(d, deposit); + } + >::put(public_props); + Self::inject_referendum(now + Self::voting_period(), proposal, VoteThreshold::SuperMajorityApprove); + } + } + + // tally up votes for any expiring referenda. + for (index, _, proposal, vote_threshold) in Self::maturing_referendums_at(now) { + let (approve, against) = Self::tally(index); + let total_stake = >::total_stake(); + Self::clear_referendum(index); + if vote_threshold.approved(approve, against, total_stake) { + proposal.dispatch(); + } + >::put(index + 1); + } + } +} + +impl Executable for Module { + fn execute() { + Self::end_block(>::block_number()); + } +} + +#[cfg(any(feature = "std", test))] +pub struct GenesisConfig { + pub launch_period: T::BlockNumber, + pub voting_period: T::BlockNumber, + pub minimum_deposit: T::Balance, +} + +#[cfg(any(feature = "std", test))] +impl GenesisConfig { + pub fn new() -> Self { + GenesisConfig { + launch_period: T::BlockNumber::sa(1), + voting_period: T::BlockNumber::sa(1), + minimum_deposit: T::Balance::sa(1), + } + } + + pub fn extended() -> Self { + GenesisConfig { + launch_period: T::BlockNumber::sa(1), + voting_period: T::BlockNumber::sa(3), + minimum_deposit: T::Balance::sa(1), + } + } +} + +#[cfg(any(feature = "std", test))] +impl Default for GenesisConfig { + fn default() -> Self { + GenesisConfig { + launch_period: T::BlockNumber::sa(1000), + voting_period: T::BlockNumber::sa(1000), + minimum_deposit: T::Balance::sa(0), + } + } +} + +#[cfg(any(feature = "std", test))] +impl primitives::BuildExternalities for GenesisConfig +{ + fn build_externalities(self) -> runtime_io::TestExternalities { + use codec::Slicable; + use runtime_io::twox_128; + + map![ + twox_128(>::key()).to_vec() => self.launch_period.encode(), + twox_128(>::key()).to_vec() => self.voting_period.encode(), + twox_128(>::key()).to_vec() => self.minimum_deposit.encode() + ] + } +} + +#[cfg(test)] +mod tests { + use super::*; + use runtime_io::with_externalities; + use substrate_primitives::H256; + use primitives::BuildExternalities; + use primitives::traits::{HasPublicAux, Identity}; + use primitives::testing::{Digest, Header}; + + impl_outer_dispatch! { + pub enum Proposal { + Session = 0, + Staking = 1, + Democracy = 2, + } + } + + pub struct Test; + impl HasPublicAux for Test { + type PublicAux = u64; + } + impl consensus::Trait for Test { + type SessionKey = u64; + } + impl system::Trait for Test { + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = runtime_io::BlakeTwo256; + type Digest = Digest; + type AccountId = u64; + type Header = Header; + } + impl session::Trait for Test { + type PublicAux = ::PublicAux; + type ConvertAccountIdToSessionKey = Identity; + } + impl staking::Trait for Test { + type Balance = u64; + type DetermineContractAddress = staking::DummyContractAddressFor; + } + impl Trait for Test { + type Proposal = Proposal; + } + + fn new_test_ext() -> runtime_io::TestExternalities { + let mut t = system::GenesisConfig::::default().build_externalities(); + t.extend(consensus::GenesisConfig::{ + authorities: vec![], + }.build_externalities()); + t.extend(session::GenesisConfig::{ + session_length: 1, //??? or 2? + validators: vec![10, 20], + }.build_externalities()); + t.extend(staking::GenesisConfig::{ + sessions_per_era: 1, + current_era: 0, + balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], + intentions: vec![], + validator_count: 2, + bonding_duration: 3, + transaction_fee: 0, + }.build_externalities()); + t.extend(GenesisConfig::{ + launch_period: 1, + voting_period: 1, + minimum_deposit: 1, + }.build_externalities()); + t + } + + type System = system::Module; + type Session = session::Module; + type Staking = staking::Module; + type Democracy = Module; + + #[test] + fn params_should_work() { + with_externalities(&mut new_test_ext(), || { + assert_eq!(Democracy::launch_period(), 1); + assert_eq!(Democracy::voting_period(), 1); + assert_eq!(Democracy::minimum_deposit(), 1); + assert_eq!(Democracy::referendum_count(), 0); + assert_eq!(Staking::sessions_per_era(), 1); + assert_eq!(Staking::total_stake(), 210); + }); + } + + fn propose_sessions_per_era(who: u64, value: u64, locked: u64) { + Democracy::propose(&who, Box::new(Proposal::Staking(staking::PrivCall::set_sessions_per_era(value))), locked); + } + + #[test] + fn locked_for_should_work() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + propose_sessions_per_era(1, 2, 2); + propose_sessions_per_era(1, 4, 4); + propose_sessions_per_era(1, 3, 3); + assert_eq!(Democracy::locked_for(0), Some(2)); + assert_eq!(Democracy::locked_for(1), Some(4)); + assert_eq!(Democracy::locked_for(2), Some(3)); + }); + } + + #[test] + fn single_proposal_should_work() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + propose_sessions_per_era(1, 2, 1); + Democracy::end_block(System::block_number()); + + System::set_block_number(2); + let r = 0; + Democracy::vote(&1, r, true); + + assert_eq!(Democracy::referendum_count(), 1); + assert_eq!(Democracy::voters_for(r), vec![1]); + assert_eq!(Democracy::vote_of((r, 1)), Some(true)); + assert_eq!(Democracy::tally(r), (10, 0)); + + Democracy::end_block(System::block_number()); + Staking::check_new_era(); + + assert_eq!(Staking::era_length(), 2); + }); + } + + #[test] + fn deposit_for_proposals_should_be_taken() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + propose_sessions_per_era(1, 2, 5); + Democracy::second(&2, 0); + Democracy::second(&5, 0); + Democracy::second(&5, 0); + Democracy::second(&5, 0); + assert_eq!(Staking::balance(&1), 5); + assert_eq!(Staking::balance(&2), 15); + assert_eq!(Staking::balance(&5), 35); + }); + } + + #[test] + fn deposit_for_proposals_should_be_returned() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + propose_sessions_per_era(1, 2, 5); + Democracy::second(&2, 0); + Democracy::second(&5, 0); + Democracy::second(&5, 0); + Democracy::second(&5, 0); + Democracy::end_block(System::block_number()); + assert_eq!(Staking::balance(&1), 10); + assert_eq!(Staking::balance(&2), 20); + assert_eq!(Staking::balance(&5), 50); + }); + } + + #[test] + #[should_panic] + fn proposal_with_deposit_below_minimum_should_panic() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + propose_sessions_per_era(1, 2, 0); + }); + } + + #[test] + #[should_panic] + fn poor_proposer_should_panic() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + propose_sessions_per_era(1, 2, 11); + }); + } + + #[test] + #[should_panic] + fn poor_seconder_should_panic() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + propose_sessions_per_era(2, 2, 11); + Democracy::second(&1, 0); + }); + } + + fn propose_bonding_duration(who: u64, value: u64, locked: u64) { + Democracy::propose(&who, Box::new(Proposal::Staking(staking::PrivCall::set_bonding_duration(value))), locked); + } + + #[test] + fn runners_up_should_come_after() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(0); + propose_bonding_duration(1, 2, 2); + propose_bonding_duration(1, 4, 4); + propose_bonding_duration(1, 3, 3); + Democracy::end_block(System::block_number()); + + System::set_block_number(1); + Democracy::vote(&1, 0, true); + Democracy::end_block(System::block_number()); + Staking::check_new_era(); + assert_eq!(Staking::bonding_duration(), 4); + + System::set_block_number(2); + Democracy::vote(&1, 1, true); + Democracy::end_block(System::block_number()); + Staking::check_new_era(); + assert_eq!(Staking::bonding_duration(), 3); + + System::set_block_number(3); + Democracy::vote(&1, 2, true); + Democracy::end_block(System::block_number()); + Staking::check_new_era(); + assert_eq!(Staking::bonding_duration(), 2); + }); + } + + fn sessions_per_era_proposal(value: u64) -> Proposal { + Proposal::Staking(staking::PrivCall::set_sessions_per_era(value)) + } + + #[test] + fn simple_passing_should_work() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + let r = Democracy::inject_referendum(1, sessions_per_era_proposal(2), VoteThreshold::SuperMajorityApprove); + Democracy::vote(&1, r, true); + + assert_eq!(Democracy::voters_for(r), vec![1]); + assert_eq!(Democracy::vote_of((r, 1)), Some(true)); + assert_eq!(Democracy::tally(r), (10, 0)); + + Democracy::end_block(System::block_number()); + Staking::check_new_era(); + + assert_eq!(Staking::era_length(), 2); + }); + } + + #[test] + fn cancel_referendum_should_work() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + let r = Democracy::inject_referendum(1, sessions_per_era_proposal(2), VoteThreshold::SuperMajorityApprove); + Democracy::vote(&1, r, true); + Democracy::cancel_referendum(r); + + Democracy::end_block(System::block_number()); + Staking::check_new_era(); + + assert_eq!(Staking::era_length(), 1); + }); + } + + #[test] + fn simple_failing_should_work() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + let r = Democracy::inject_referendum(1, sessions_per_era_proposal(2), VoteThreshold::SuperMajorityApprove); + Democracy::vote(&1, r, false); + + assert_eq!(Democracy::voters_for(r), vec![1]); + assert_eq!(Democracy::vote_of((r, 1)), Some(false)); + assert_eq!(Democracy::tally(r), (0, 10)); + + Democracy::end_block(System::block_number()); + Staking::check_new_era(); + + assert_eq!(Staking::era_length(), 1); + }); + } + + #[test] + fn controversial_voting_should_work() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + let r = Democracy::inject_referendum(1, sessions_per_era_proposal(2), VoteThreshold::SuperMajorityApprove); + Democracy::vote(&1, r, true); + Democracy::vote(&2, r, false); + Democracy::vote(&3, r, false); + Democracy::vote(&4, r, true); + Democracy::vote(&5, r, false); + Democracy::vote(&6, r, true); + + assert_eq!(Democracy::tally(r), (110, 100)); + + Democracy::end_block(System::block_number()); + Staking::check_new_era(); + + assert_eq!(Staking::era_length(), 2); + }); + } + + #[test] + fn controversial_low_turnout_voting_should_work() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + let r = Democracy::inject_referendum(1, sessions_per_era_proposal(2), VoteThreshold::SuperMajorityApprove); + Democracy::vote(&5, r, false); + Democracy::vote(&6, r, true); + + assert_eq!(Democracy::tally(r), (60, 50)); + + Democracy::end_block(System::block_number()); + Staking::check_new_era(); + + assert_eq!(Staking::era_length(), 1); + }); + } + + #[test] + fn passing_low_turnout_voting_should_work() { + with_externalities(&mut new_test_ext(), || { + assert_eq!(Staking::era_length(), 1); + assert_eq!(Staking::total_stake(), 210); + + System::set_block_number(1); + let r = Democracy::inject_referendum(1, sessions_per_era_proposal(2), VoteThreshold::SuperMajorityApprove); + Democracy::vote(&4, r, true); + Democracy::vote(&5, r, false); + Democracy::vote(&6, r, true); + + assert_eq!(Democracy::tally(r), (100, 50)); + + Democracy::end_block(System::block_number()); + Staking::check_new_era(); + + assert_eq!(Staking::era_length(), 2); + }); + } +} diff --git a/substrate/substrate/runtime/democracy/src/vote_threshold.rs b/substrate/substrate/runtime/democracy/src/vote_threshold.rs new file mode 100644 index 0000000000..c40f611e34 --- /dev/null +++ b/substrate/substrate/runtime/democracy/src/vote_threshold.rs @@ -0,0 +1,75 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Demo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Demo. If not, see . + +//! Voting thresholds. + +use primitives::traits::IntegerSquareRoot; +use codec::{Input, Slicable}; +use rstd::ops::{Add, Mul, Div}; + +/// A means of determining if a vote is past pass threshold. +#[derive(Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] +pub enum VoteThreshold { + /// A supermajority of approvals is needed to pass this vote. + SuperMajorityApprove, + /// A supermajority of rejects is needed to fail this vote. + SuperMajorityAgainst, + /// A simple majority of approvals is needed to pass this vote. + SimpleMajority, +} + +impl Slicable for VoteThreshold { + fn decode(input: &mut I) -> Option { + input.read_byte().and_then(|v| match v { + 0 => Some(VoteThreshold::SuperMajorityApprove), + 1 => Some(VoteThreshold::SuperMajorityAgainst), + 2 => Some(VoteThreshold::SimpleMajority), + _ => None, + }) + } + + fn using_encoded R>(&self, f: F) -> R { + f(&[match *self { + VoteThreshold::SuperMajorityApprove => 0u8, + VoteThreshold::SuperMajorityAgainst => 1u8, + VoteThreshold::SimpleMajority => 2u8, + }]) + } +} + +pub trait Approved { + /// Given `approve` votes for and `against` votes against from a total electorate size of + /// `electorate` (`electorate - (approve + against)` are abstainers), then returns true if the + /// overall outcome is in favour of approval. + fn approved(&self, approve: Balance, against: Balance, electorate: Balance) -> bool; +} + +impl + Mul + Div + Copy> Approved for VoteThreshold { + /// Given `approve` votes for and `against` votes against from a total electorate size of + /// `electorate` (`electorate - (approve + against)` are abstainers), then returns true if the + /// overall outcome is in favour of approval. + fn approved(&self, approve: Balance, against: Balance, electorate: Balance) -> bool { + let voters = approve + against; + match *self { + VoteThreshold::SuperMajorityApprove => + voters.integer_sqrt() * approve / electorate.integer_sqrt() > against, + VoteThreshold::SuperMajorityAgainst => + approve > voters.integer_sqrt() * against / electorate.integer_sqrt(), + VoteThreshold::SimpleMajority => approve > against, + } + } +} diff --git a/substrate/substrate/runtime/executive/Cargo.toml b/substrate/substrate/runtime/executive/Cargo.toml new file mode 100644 index 0000000000..5b1280c249 --- /dev/null +++ b/substrate/substrate/runtime/executive/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "substrate-runtime-executive" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +hex-literal = "0.1.0" +serde = { version = "1.0", default_features = false } +substrate-codec = { path = "../../codec", default_features = false } +substrate-runtime-std = { path = "../../runtime-std", default_features = false } +substrate-runtime-io = { path = "../../runtime-io", default_features = false } +substrate-runtime-support = { path = "../../runtime-support", default_features = false } +substrate-runtime-primitives = { path = "../primitives", default_features = false } +substrate-runtime-system = { path = "../system", default_features = false } + +[dev-dependencies] +substrate-primitives = { path = "../../primitives" } +substrate-runtime-session = { path = "../session" } +substrate-runtime-staking = { path = "../staking" } +substrate-runtime-consensus = { path = "../consensus" } + +[features] +default = ["std"] +std = [ + "substrate-runtime-std/std", + "substrate-runtime-support/std", + "serde/std", + "substrate-codec/std", + "substrate-runtime-primitives/std", + "substrate-runtime-io/std", + "substrate-runtime-system/std", +] diff --git a/substrate/substrate/runtime/executive/src/lib.rs b/substrate/substrate/runtime/executive/src/lib.rs new file mode 100644 index 0000000000..a99bd28c98 --- /dev/null +++ b/substrate/substrate/runtime/executive/src/lib.rs @@ -0,0 +1,284 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Demo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Demo. If not, see . + +//! Executive: Handles all of the top-level stuff; essentially just executing blocks/extrinsics. + +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate substrate_runtime_std as rstd; +extern crate substrate_runtime_support as runtime_support; +extern crate substrate_runtime_io as runtime_io; +extern crate substrate_codec as codec; +extern crate substrate_runtime_primitives as primitives; +extern crate substrate_runtime_system as system; + +#[cfg(test)] +#[macro_use] +extern crate hex_literal; + +#[cfg(test)] +extern crate substrate_primitives; + +#[cfg(test)] +extern crate substrate_runtime_consensus as consensus; + +#[cfg(test)] +extern crate substrate_runtime_session as session; + +#[cfg(test)] +extern crate substrate_runtime_staking as staking; + +#[cfg(feature = "std")] extern crate serde; + +use rstd::prelude::*; +use rstd::marker::PhantomData; +use runtime_io::Hashing; +use primitives::traits::{self, Header, Zero, One, Checkable, Applyable, CheckEqual, Executable, MakePayment}; +use codec::Slicable; + +pub struct Executive< + System, + Block, + Payment, + Finalisation, +>(PhantomData<(System, Block, Payment, Finalisation)>); + +impl< + System: system::Trait, + Block: traits::Block

, + Payment: MakePayment, + Finalisation: Executable, +> Executive where + Block::Extrinsic: Checkable + Slicable, + ::Checked: Applyable +{ + /// Start the execution of a particular block. + pub fn initialise_block(header: &System::Header) { + >::initialise(header.number(), header.parent_hash(), header.extrinsics_root()); + } + + fn initial_checks(block: &Block) { + let header = block.header(); + + // check parent_hash is correct. + let n = header.number().clone(); + assert!( + n > System::BlockNumber::zero() && >::block_hash(n - System::BlockNumber::one()) == *header.parent_hash(), + "Parent hash should be valid." + ); + + // check transaction trie root represents the transactions. + let txs = block.extrinsics().iter().map(Slicable::encode).collect::>(); + let txs = txs.iter().map(Vec::as_slice).collect::>(); + let txs_root = System::Hashing::enumerated_trie_root(&txs); + header.extrinsics_root().check_equal(&txs_root); + assert!(header.extrinsics_root() == &txs_root, "Transaction trie root must be valid."); + } + + /// Actually execute all transitioning for `block`. + pub fn execute_block(block: Block) { + Self::initialise_block(block.header()); + + // any initial checks + Self::initial_checks(&block); + + // execute transactions + let (header, extrinsics) = block.deconstruct(); + extrinsics.into_iter().for_each(Self::apply_extrinsic); + + // post-transactional book-keeping. + Finalisation::execute(); + + // any final checks + Self::final_checks(&header); + + // any stuff that we do after taking the storage root. + Self::post_finalise(&header); + } + + /// Finalise the block - it is up the caller to ensure that all header fields are valid + /// except state-root. + pub fn finalise_block() -> System::Header { + Finalisation::execute(); + + let header = >::finalise(); + Self::post_finalise(&header); + + header + } + + /// Apply outside of the block execution function. + /// This doesn't attempt to validate anything regarding the block. + pub fn apply_extrinsic(utx: Block::Extrinsic) { + // Verify the signature is good. + let tx = match utx.check() { + Ok(tx) => tx, + Err(_) => panic!("All transactions should be properly signed"), + }; + + { + // check index + let expected_index = >::account_index(tx.sender()); + assert!(tx.index() == &expected_index, "All transactions should have the correct nonce"); + + // increment nonce in storage + >::inc_account_index(tx.sender()); + } + + // pay any fees. + Payment::make_payment(tx.sender()); + + // decode parameters and dispatch + tx.apply(); + } + + fn final_checks(header: &System::Header) { + // check digest + assert!(header.digest() == &>::digest()); + + // remove temporaries. + >::finalise(); + + // check storage root. + let storage_root = System::Hashing::storage_root(); + header.state_root().check_equal(&storage_root); + assert!(header.state_root() == &storage_root, "Storage root must match that calculated."); + } + + fn post_finalise(header: &System::Header) { + // store the header hash in storage; we can't do it before otherwise there would be a + // cyclic dependency. + >::record_block_hash(header) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use staking::Call; + use runtime_io::with_externalities; + use substrate_primitives::H256; + use primitives::BuildExternalities; + use primitives::traits::{HasPublicAux, Identity, Header as HeaderT}; + use primitives::testing::{Digest, Header, Block}; + + pub struct Test; + impl HasPublicAux for Test { + type PublicAux = u64; + } + impl consensus::Trait for Test { + type SessionKey = u64; + } + impl system::Trait for Test { + type Index = u64; + type BlockNumber = u64; + type Hash = substrate_primitives::H256; + type Hashing = runtime_io::BlakeTwo256; + type Digest = Digest; + type AccountId = u64; + type Header = Header; + } + impl session::Trait for Test { + type PublicAux = ::PublicAux; + type ConvertAccountIdToSessionKey = Identity; + } + impl staking::Trait for Test { + type Balance = u64; + type DetermineContractAddress = staking::DummyContractAddressFor; + } + + type TestXt = primitives::testing::TestXt>; + type Executive = super::Executive, staking::Module, (session::Module, staking::Module)>; + + #[test] + fn staking_balance_transfer_dispatch_works() { + let mut t = system::GenesisConfig::::default().build_externalities(); + t.extend(staking::GenesisConfig:: { + sessions_per_era: 0, + current_era: 0, + balances: vec![(1, 111)], + intentions: vec![], + validator_count: 0, + bonding_duration: 0, + transaction_fee: 10, + }.build_externalities()); + let xt = primitives::testing::TestXt((1, 0, Call::transfer(2, 69))); + with_externalities(&mut t, || { + Executive::initialise_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default())); + Executive::apply_extrinsic(xt); + assert_eq!(>::balance(&1), 32); + assert_eq!(>::balance(&2), 69); + }); + } + + fn new_test_ext() -> runtime_io::TestExternalities { + let mut t = system::GenesisConfig::::default().build_externalities(); + t.extend(consensus::GenesisConfig::::default().build_externalities()); + t.extend(session::GenesisConfig::::default().build_externalities()); + t.extend(staking::GenesisConfig::::default().build_externalities()); + t + } + + #[test] + fn block_import_works() { + with_externalities(&mut new_test_ext(), || { + Executive::execute_block(Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root: hex!("9228e363883f4f5a01981985b5598d1a767e987eb3ccea017a0e14cac7acc79d").into(), + extrinsics_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), + digest: Digest { logs: vec![], }, + }, + extrinsics: vec![], + }); + }); + } + + #[test] + #[should_panic] + fn block_import_of_bad_state_root_fails() { + with_externalities(&mut new_test_ext(), || { + Executive::execute_block(Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root: [0u8; 32].into(), + extrinsics_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), + digest: Digest { logs: vec![], }, + }, + extrinsics: vec![], + }); + }); + } + + #[test] + #[should_panic] + fn block_import_of_bad_extrinsic_root_fails() { + with_externalities(&mut new_test_ext(), || { + Executive::execute_block(Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root: hex!("93dde1251278e65430baf291337ba219bacfa9ad583c52513b12cf1974109a97").into(), + extrinsics_root: [0u8; 32].into(), + digest: Digest { logs: vec![], }, + }, + extrinsics: vec![], + }); + }); + } +} diff --git a/substrate/substrate/runtime/primitives/Cargo.toml b/substrate/substrate/runtime/primitives/Cargo.toml new file mode 100644 index 0000000000..cc3f035715 --- /dev/null +++ b/substrate/substrate/runtime/primitives/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "substrate-runtime-primitives" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +num-traits = { version = "0.2", default_features = false } +integer-sqrt = "0.1.0" +serde = { version = "1.0", optional = true } +serde_derive = { version = "1.0", optional = true } +substrate-codec = { path = "../../codec", default_features = false } +substrate-primitives = { path = "../../primitives", default_features = false } +substrate-runtime-std = { path = "../../runtime-std", default_features = false } +substrate-runtime-io = { path = "../../runtime-io", default_features = false } +substrate-runtime-support = { path = "../../runtime-support", default_features = false } + +[features] +default = ["std"] +std = [ + "num-traits/std", + "serde", + "serde_derive", + "substrate-runtime-std/std", + "substrate-runtime-io/std", + "substrate-runtime-support/std", + "substrate-codec/std", + "substrate-primitives/std", +] diff --git a/substrate/substrate/runtime/primitives/src/generic.rs b/substrate/substrate/runtime/primitives/src/generic.rs new file mode 100644 index 0000000000..81c7ca44c6 --- /dev/null +++ b/substrate/substrate/runtime/primitives/src/generic.rs @@ -0,0 +1,398 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Demo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Demo. If not, see . + +//! Generic implementations of Extrinsic/Header/Block. + +#[cfg(feature = "std")] use serde::Serialize; +use rstd::prelude::*; +use codec::{Slicable, Input}; +use runtime_support::AuxDispatchable; +use traits; +use rstd::ops; + +#[cfg(feature = "std")] +use std::fmt::{self, Debug}; + +#[cfg(feature = "std")] +pub trait MaybeSerializeDebug: Serialize + Debug {} +#[cfg(feature = "std")] +impl MaybeSerializeDebug for T {} + +#[cfg(not(feature = "std"))] +pub trait MaybeSerializeDebug {} +#[cfg(not(feature = "std"))] +impl MaybeSerializeDebug for T {} + +pub trait Member: MaybeSerializeDebug + Eq + PartialEq + Clone {} +impl Member for T {} + +/// A vetted and verified extrinsic from the external world. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Debug))] +pub struct Extrinsic where + AccountId: Member, + Index: Member, + Call: Member, +{ + /// Who signed it (note this is not a signature). + pub signed: AccountId, + /// The number of extrinsics have come before from the same signer. + pub index: Index, + /// The function that should be called. + pub function: Call, +} + +impl Slicable for Extrinsic where + AccountId: Member + Slicable, + Index: Member + Slicable, + Call: Member + Slicable +{ + fn decode(input: &mut I) -> Option { + Some(Extrinsic { + signed: Slicable::decode(input)?, + index: Slicable::decode(input)?, + function: Slicable::decode(input)?, + }) + } + + fn encode(&self) -> Vec { + let mut v = Vec::new(); + + self.signed.using_encoded(|s| v.extend(s)); + self.index.using_encoded(|s| v.extend(s)); + self.function.using_encoded(|s| v.extend(s)); + + v + } +} + +/// A extrinsics right from the external world. Unchecked. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize))] +pub struct UncheckedExtrinsic where + AccountId: Member, + Index: Member, + Call: Member, + Signature: Member +{ + /// The actual extrinsic information. + pub extrinsic: Extrinsic, + /// The signature; should be an Ed25519 signature applied to the serialised `extrinsic` field. + pub signature: Signature, +} + +impl Slicable for UncheckedExtrinsic where + AccountId: Member + Slicable, + Index: Member + Slicable, + Call: Member + Slicable, + Signature: Member + Slicable +{ + fn decode(input: &mut I) -> Option { + // This is a little more complicated than usual since the binary format must be compatible + // with substrate's generic `Vec` type. Basically this just means accepting that there + // will be a prefix of u32, which has the total number of bytes following (we don't need + // to use this). + let _length_do_not_remove_me_see_above: u32 = Slicable::decode(input)?; + + Some(UncheckedExtrinsic { + extrinsic: Slicable::decode(input)?, + signature: Slicable::decode(input)?, + }) + } + + fn encode(&self) -> Vec { + let mut v = Vec::new(); + + // need to prefix with the total length as u32 to ensure it's binary comptible with + // Vec. we'll make room for it here, then overwrite once we know the length. + v.extend(&[0u8; 4]); + + self.extrinsic.signed.using_encoded(|s| v.extend(s)); + self.extrinsic.index.using_encoded(|s| v.extend(s)); + self.extrinsic.function.using_encoded(|s| v.extend(s)); + self.signature.using_encoded(|s| v.extend(s)); + + let length = (v.len() - 4) as u32; + length.using_encoded(|s| v[0..4].copy_from_slice(s)); + + v + } +} + +#[cfg(feature = "std")] +impl fmt::Debug for UncheckedExtrinsic where + AccountId: Member, + Index: Member, + Call: Member, + Signature: Member, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "UncheckedExtrinsic({:?})", self.extrinsic) + } +} + +impl traits::Checkable for UncheckedExtrinsic where + AccountId: Member, + Index: Member, + Call: Member, + Signature: Member + traits::Verify, + Extrinsic: Slicable +{ + type Checked = CheckedExtrinsic; + + fn check(self) -> Result { + if ::codec::Slicable::using_encoded(&self.extrinsic, |msg| + self.signature.verify(msg, &self.extrinsic.signed) + ) { + Ok(CheckedExtrinsic(self)) + } else { + Err(self) + } + } +} + +/// A type-safe indicator that a extrinsic has been checked. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct CheckedExtrinsic + (UncheckedExtrinsic) +where + AccountId: Member, + Index: Member, + Call: Member, + Signature: Member; + +impl CheckedExtrinsic +where + AccountId: Member, + Index: Member, + Call: Member, + Signature: Member +{ + /// Get a reference to the checked signature. + pub fn signature(&self) -> &Signature { + &self.0.signature + } +} + +impl ops::Deref + for CheckedExtrinsic +where + AccountId: Member, + Index: Member, + Call: Member, + Signature: Member +{ + type Target = Extrinsic; + + fn deref(&self) -> &Self::Target { + &self.0.extrinsic + } +} + +impl traits::Applyable + for CheckedExtrinsic +where + AccountId: Member, + Index: Member, + Call: Member + AuxDispatchable, + Signature: Member +{ + type Index = Index; + type AccountId = AccountId; + + fn index(&self) -> &Self::Index { + &self.0.extrinsic.index + } + + fn sender(&self) -> &Self::AccountId { + &self.0.extrinsic.signed + } + + fn apply(self) { + let xt = self.0.extrinsic; + xt.function.dispatch(&xt.signed); + } +} + +#[derive(Default, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Debug, Serialize))] +pub struct Digest { + pub logs: Vec, +} +impl Slicable for Digest where + Item: Member + Slicable +{ + fn decode(input: &mut I) -> Option { + Some(Digest { logs: Slicable::decode(input)? }) + } + fn using_encoded R>(&self, f: F) -> R { + self.logs.using_encoded(f) + } +} +impl traits::Digest for Digest where + Item: Member + Slicable +{ + type Item = Item; + fn push(&mut self, item: Self::Item) { + self.logs.push(item); + } +} + +/// Abstraction over a block header for a substrate chain. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Debug, Serialize))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "std", serde(deny_unknown_fields))] +pub struct Header where + Number: Member, + Hash: Member, + DigestItem: Member, +{ + /// The parent hash. + pub parent_hash: Hash, + /// The block number. + pub number: Number, + /// The state trie merkle root + pub state_root: Hash, + /// The merkle root of the extrinsics. + pub extrinsics_root: Hash, + /// A chain-specific digest of data useful for light clients or referencing auxiliary data. + pub digest: Digest, +} + +impl Slicable for Header where + Number: Member + Slicable, + Hash: Member + Slicable, + DigestItem: Member + Slicable, +{ + fn decode(input: &mut I) -> Option { + Some(Header { + parent_hash: Slicable::decode(input)?, + number: Slicable::decode(input)?, + state_root: Slicable::decode(input)?, + extrinsics_root: Slicable::decode(input)?, + digest: Slicable::decode(input)?, + }) + } + + fn encode(&self) -> Vec { + let mut v = Vec::new(); + self.parent_hash.using_encoded(|s| v.extend(s)); + self.number.using_encoded(|s| v.extend(s)); + self.state_root.using_encoded(|s| v.extend(s)); + self.extrinsics_root.using_encoded(|s| v.extend(s)); + self.digest.using_encoded(|s| v.extend(s)); + v + } +} +impl traits::Header for Header where + Number: Member + Slicable, + Hash: Member + Slicable, + DigestItem: Member + Slicable, + { + type Number = Number; + type Hash = Hash; + type Digest = Digest; + + fn number(&self) -> &Self::Number { &self.number } + fn extrinsics_root(&self) -> &Self::Hash { &self.extrinsics_root } + fn state_root(&self) -> &Self::Hash { &self.state_root } + fn parent_hash(&self) -> &Self::Hash { &self.parent_hash } + fn digest(&self) -> &Self::Digest { &self.digest } + fn new( + number: Self::Number, + extrinsics_root: Self::Hash, + state_root: Self::Hash, + parent_hash: Self::Hash, + digest: Self::Digest + ) -> Self { + Header { + number, extrinsics_root: extrinsics_root, state_root, parent_hash, digest + } + } +} + +/// Abstraction over a substrate block. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Debug, Serialize))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "std", serde(deny_unknown_fields))] +pub struct Block where + Number: Member, + Hash: Member, + DigestItem: Member, + AccountId: Member, + Index: Member, + Call: Member, + Signature: Member +{ + /// The block header. + pub header: Header, + /// The accompanying extrinsics. + pub extrinsics: Vec>, +} + +impl Slicable + for Block +where + Number: Member, + Hash: Member, + DigestItem: Member, + AccountId: Member, + Index: Member, + Call: Member, + Signature: Member, + Header: Slicable, + UncheckedExtrinsic: Slicable, +{ + fn decode(input: &mut I) -> Option { + Some(Block { + header: Slicable::decode(input)?, + extrinsics: Slicable::decode(input)?, + }) + } + fn encode(&self) -> Vec { + let mut v: Vec = Vec::new(); + v.extend(self.header.encode()); + v.extend(self.extrinsics.encode()); + v + } +} + +impl traits::Block + for Block +where + Number: Member + Slicable, + Hash: Member + Slicable, + DigestItem: Member + Slicable, + AccountId: Member, + Index: Member, + Call: Member, + Signature: Member +{ + type Extrinsic = UncheckedExtrinsic; + type Header = Header; + fn header(&self) -> &Self::Header { + &self.header + } + fn extrinsics(&self) -> &[Self::Extrinsic] { + &self.extrinsics[..] + } + fn deconstruct(self) -> (Self::Header, Vec) { + (self.header, self.extrinsics) + } +} diff --git a/substrate/substrate/runtime/primitives/src/lib.rs b/substrate/substrate/runtime/primitives/src/lib.rs new file mode 100644 index 0000000000..69a3039de6 --- /dev/null +++ b/substrate/substrate/runtime/primitives/src/lib.rs @@ -0,0 +1,87 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Demo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Demo. If not, see . + +//! System manager: Handles all of the top-level stuff; executing block/transaction, setting code +//! and depositing logs. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +extern crate serde; + +#[cfg(feature = "std")] +#[macro_use] +extern crate serde_derive; + +extern crate num_traits; +extern crate integer_sqrt; +extern crate substrate_runtime_std as rstd; +extern crate substrate_runtime_io as runtime_io; +extern crate substrate_runtime_support as runtime_support; +extern crate substrate_codec as codec; +extern crate substrate_primitives; + +#[cfg(feature = "std")] use std::collections::HashMap; + +#[cfg(feature = "std")] +pub mod testing; + +pub mod traits; +pub mod generic; + +#[cfg(feature = "std")] +pub type BuiltExternalities = HashMap, Vec>; + +#[cfg(feature = "std")] +pub trait BuildExternalities { + fn build_externalities(self) -> BuiltExternalities; +} + +#[macro_export] +macro_rules! __impl_outer_config_types { + ($concrete:ident $config:ident $snake:ident $($rest:ident)*) => { + #[cfg(any(feature = "std", test))] + pub type $config = $snake::GenesisConfig<$concrete>; + __impl_outer_config_types! {$concrete $($rest)*} + }; + ($concrete:ident) => () +} + +#[macro_export] +/// Implement the output "meta" module configuration struct. +macro_rules! impl_outer_config { + ( pub struct $main:ident for $concrete:ident { $( $config:ident => $snake:ident, )* } ) => { + __impl_outer_config_types! { $concrete $( $config $snake )* } + #[cfg(any(feature = "std", test))] + pub struct $main { + $( + pub $snake: Option<$config>, + )* + } + #[cfg(any(feature = "std", test))] + impl $crate::BuildExternalities for $main { + fn build_externalities(self) -> $crate::BuiltExternalities { + let mut s = $crate::BuiltExternalities::new(); + $( + if let Some(extra) = self.$snake { + s.extend(extra.build_externalities()); + } + )* + s + } + } + } +} diff --git a/substrate/substrate/runtime/primitives/src/testing.rs b/substrate/substrate/runtime/primitives/src/testing.rs new file mode 100644 index 0000000000..7300d8d176 --- /dev/null +++ b/substrate/substrate/runtime/primitives/src/testing.rs @@ -0,0 +1,150 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Demo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Demo. If not, see . + +//! Testing utilities. + +use serde; +use codec::{Slicable, Input}; +use runtime_support::AuxDispatchable; +use substrate_primitives::H256; +use traits::{self, Checkable, Applyable}; + +#[derive(Default, PartialEq, Eq, Clone, Serialize, Debug)] +pub struct Digest { + pub logs: Vec, +} +impl Slicable for Digest { + fn decode(input: &mut I) -> Option { + Vec::::decode(input).map(|logs| Digest { logs }) + } + fn using_encoded R>(&self, f: F) -> R { + self.logs.using_encoded(f) + } +} +impl traits::Digest for Digest { + type Item = u64; + fn push(&mut self, item: Self::Item) { + self.logs.push(item); + } +} + +#[derive(PartialEq, Eq, Clone, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +pub struct Header { + pub parent_hash: H256, + pub number: u64, + pub state_root: H256, + pub extrinsics_root: H256, + pub digest: Digest, +} +impl Slicable for Header { + fn decode(input: &mut I) -> Option { + Some(Header { + parent_hash: Slicable::decode(input)?, + number: Slicable::decode(input)?, + state_root: Slicable::decode(input)?, + extrinsics_root: Slicable::decode(input)?, + digest: Slicable::decode(input)?, + }) + } + + fn encode(&self) -> Vec { + let mut v = Vec::new(); + self.parent_hash.using_encoded(|s| v.extend(s)); + self.number.using_encoded(|s| v.extend(s)); + self.state_root.using_encoded(|s| v.extend(s)); + self.extrinsics_root.using_encoded(|s| v.extend(s)); + self.digest.using_encoded(|s| v.extend(s)); + v + } +} +impl traits::Header for Header { + type Number = u64; + type Hash = H256; + type Digest = Digest; + fn number(&self) -> &Self::Number { &self.number } + fn extrinsics_root(&self) -> &Self::Hash { &self.extrinsics_root } + fn state_root(&self) -> &Self::Hash { &self.state_root } + fn parent_hash(&self) -> &Self::Hash { &self.parent_hash } + fn digest(&self) -> &Self::Digest { &self.digest } + fn new( + number: Self::Number, + extrinsics_root: Self::Hash, + state_root: Self::Hash, + parent_hash: Self::Hash, + digest: Self::Digest + ) -> Self { + Header { + number, extrinsics_root: extrinsics_root, state_root, parent_hash, digest + } + } +} + +#[derive(PartialEq, Eq, Clone, Serialize, Debug)] +pub struct Block { + pub header: Header, + pub extrinsics: Vec, +} +impl Slicable for Block { + fn decode(input: &mut I) -> Option { + Some(Block { + header: Slicable::decode(input)?, + extrinsics: Slicable::decode(input)?, + }) + } + fn encode(&self) -> Vec { + let mut v: Vec = Vec::new(); + v.extend(self.header.encode()); + v.extend(self.extrinsics.encode()); + v + } +} +impl traits::Block for Block { + type Extrinsic = Xt; + type Header = Header; + fn header(&self) -> &Self::Header { + &self.header + } + fn extrinsics(&self) -> &[Self::Extrinsic] { + &self.extrinsics[..] + } + fn deconstruct(self) -> (Self::Header, Vec) { + (self.header, self.extrinsics) + } +} + +#[derive(PartialEq, Eq, Clone, Serialize, Debug)] +pub struct TestXt(pub (u64, u64, Call)); +impl Slicable for TestXt { + fn decode(input: &mut I) -> Option { + Some(TestXt(Slicable::decode(input)?)) + } + fn encode(&self) -> Vec { + self.0.encode() + } +} +impl Checkable for TestXt { + type Checked = Self; + fn check(self) -> Result { Ok(self) } +} +impl + Slicable + Sized + serde::Serialize> Applyable for TestXt { + type AccountId = u64; + type Index = u64; + fn sender(&self) -> &u64 { &(self.0).0 } + fn index(&self) -> &u64 { &(self.0).1 } + fn apply(self) { (self.0).2.dispatch(&(self.0).0); } +} diff --git a/substrate/substrate/runtime/primitives/src/traits.rs b/substrate/substrate/runtime/primitives/src/traits.rs new file mode 100644 index 0000000000..1e2008c976 --- /dev/null +++ b/substrate/substrate/runtime/primitives/src/traits.rs @@ -0,0 +1,293 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Demo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Demo. If not, see . + +//! Primitives for the runtime modules. + +use rstd::prelude::*; +use rstd; +#[cfg(not(feature = "std"))] use runtime_io; +use substrate_primitives; +use codec::{Input, Slicable}; +use substrate_primitives::hash::H512; +pub use integer_sqrt::IntegerSquareRoot; +pub use num_traits::{Zero, One, Bounded}; +use rstd::ops::{Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; + +/// Means of signature verification. +pub trait Verify { + /// Type of the signer. + type Signer; + /// Verify a signature. + fn verify(&self, msg: &[u8], signer: &Self::Signer) -> bool; +} + +/// Ed25519 signature verify. +#[derive(Eq, PartialEq, Clone)] +#[cfg_attr(feature = "std", derive(Debug, Serialize))] +pub struct Ed25519Signature(H512); +impl Verify for Ed25519Signature { + type Signer = [u8; 32]; + fn verify(&self, msg: &[u8], signer: &Self::Signer) -> bool { + ::runtime_io::ed25519_verify(&(self.0).0, msg, &signer[..]) + } +} +impl Slicable for Ed25519Signature { + fn decode(input: &mut I) -> Option { Some(Ed25519Signature(Slicable::decode(input)?,)) } + fn using_encoded R>(&self, f: F) -> R { self.0.using_encoded(f) } +} +impl From for Ed25519Signature { + fn from(h: H512) -> Ed25519Signature { + Ed25519Signature(h) + } +} + +/// Simple payment making trait, operating on a single generic `AccountId` type. +pub trait MakePayment { + /// Make some sort of payment concerning `who`. + fn make_payment(who: &AccountId); +} + +impl MakePayment for () { + fn make_payment(_: &T) {} +} + +/// Extensible conversion trait. Generic over both source and destination types. +pub trait Convert { + /// Make conversion. + fn convert(a: A) -> B; +} + +/// Simple trait similar to `Into`, except that it can be used to convert numerics between each +/// other. +pub trait As { + /// Convert forward (ala `Into::into`). + fn as_(self) -> T; + /// Convert backward (ala `From::from`). + fn sa(T) -> Self; +} + +macro_rules! impl_numerics { + ( $( $t:ty ),* ) => { + $( + impl_numerics!($t: u8, u16, u32, u64, usize, i8, i16, i32, i64, isize,); + )* + }; + ( $f:ty : $t:ty, $( $rest:ty, )* ) => { + impl As<$t> for $f { + fn as_(self) -> $t { self as $t } + fn sa(t: $t) -> Self { t as Self } + } + impl_numerics!($f: $( $rest, )*); + }; + ( $f:ty : ) => {} +} + +impl_numerics!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize); + +pub struct Identity; +impl Convert for Identity { + fn convert(a: T) -> T { a } +} + +pub trait HasPublicAux { + type PublicAux; +} + +pub trait RefInto { + fn ref_into(&self) -> &T; +} +impl RefInto for T { + fn ref_into(&self) -> &T { &self } +} + +pub trait SimpleArithmetic: + Zero + One + IntegerSquareRoot + As + + Add + AddAssign + + Sub + SubAssign + + Mul + MulAssign + + Div + DivAssign + + Rem + RemAssign + + PartialOrd + Ord +{} +impl + + Add + AddAssign + + Sub + SubAssign + + Mul + MulAssign + + Div + DivAssign + + Rem + RemAssign + + PartialOrd + Ord +> SimpleArithmetic for T {} + +pub trait SimpleBitOps: + Sized + + rstd::ops::BitOr + + rstd::ops::BitAnd +{} +impl + + rstd::ops::BitAnd +> SimpleBitOps for T {} + +/// Something that can be executed. +pub trait Executable { + fn execute(); +} + +impl Executable for () { + fn execute() {} +} +impl Executable for (A, B) { + fn execute() { + A::execute(); + B::execute(); + } +} + +/// Something that acts like a `Digest` - it can have `Log`s `push`ed onto it and these `Log`s are +/// each `Slicable`. +pub trait Digest { + type Item: Sized; + fn push(&mut self, item: Self::Item); +} + +impl Digest for substrate_primitives::Digest { + type Item = substrate_primitives::block::Log; + fn push(&mut self, item: Self::Item) { + self.logs.push(item); + } +} + +/// Something which fulfills the abstract idea of a Substrate header. It has types for a `Number`, +/// a `Hash` and a `Digest`. It provides access to an `extrinsics_root`, `state_root` and +/// `parent_hash`, as well as a `digest` and a block `number`. +/// +/// You can also create a `new` one from those fields. +pub trait Header: Sized + Slicable { + type Number: Sized; + type Hash: Sized; + type Digest: Sized; + fn number(&self) -> &Self::Number; + fn extrinsics_root(&self) -> &Self::Hash; + fn state_root(&self) -> &Self::Hash; + fn parent_hash(&self) -> &Self::Hash; + fn digest(&self) -> &Self::Digest; + fn new( + number: Self::Number, + extrinsics_root: Self::Hash, + state_root: Self::Hash, + parent_hash: Self::Hash, + digest: Self::Digest + ) -> Self; +} + +impl Header for substrate_primitives::Header { + type Number = substrate_primitives::block::Number; + type Hash = substrate_primitives::block::HeaderHash; + type Digest = substrate_primitives::block::Digest; + fn number(&self) -> &Self::Number { &self.number } + fn extrinsics_root(&self) -> &Self::Hash { &self.transaction_root } + fn state_root(&self) -> &Self::Hash { &self.state_root } + fn parent_hash(&self) -> &Self::Hash { &self.parent_hash } + fn digest(&self) -> &Self::Digest { &self.digest } + fn new( + number: Self::Number, + extrinsics_root: Self::Hash, + state_root: Self::Hash, + parent_hash: Self::Hash, + digest: Self::Digest + ) -> Self { + substrate_primitives::Header { + number: number, + transaction_root: extrinsics_root, + state_root: state_root, + parent_hash: parent_hash, + digest: digest, + } + } +} + +/// Something which fulfills the abstract idea of a Substrate block. It has types for an +/// `Extrinsic` piece of information as well as a `Header`. +/// +/// You can get an iterator over each of the `extrinsics` and retrieve the `header`. +pub trait Block { + type Extrinsic: Sized; + type Header: Header; + fn header(&self) -> &Self::Header; + fn extrinsics(&self) -> &[Self::Extrinsic]; + fn deconstruct(self) -> (Self::Header, Vec); +} + +impl Block for substrate_primitives::Block { + type Extrinsic = substrate_primitives::block::Transaction; + type Header = substrate_primitives::Header; + fn header(&self) -> &Self::Header { + &self.header + } + fn extrinsics(&self) -> &[Self::Extrinsic] { + &self.transactions[..] + } + fn deconstruct(self) -> (Self::Header, Vec) { + (self.header, self.transactions) + } +} + +/// A "checkable" piece of information, used by the standard Substrate Executive in order to +/// check the validity of a piece of extrinsic information, usually by verifying the signature. +pub trait Checkable: Sized { + type Checked: Sized; + fn check(self) -> Result; +} + +/// An "executable" piece of information, used by the standard Substrate Executive in order to +/// enact a piece of extrinsic information by marshalling and dispatching to a named functioon +/// call. +/// +/// Also provides information on to whom this information is attributable and an index that allows +/// each piece of attributable information to be disambiguated. +pub trait Applyable { + type AccountId; + type Index; + fn index(&self) -> &Self::Index; + fn sender(&self) -> &Self::AccountId; + fn apply(self); +} + +/// Something that can be checked for equality and printed out to a debug channel if bad. +pub trait CheckEqual { + fn check_equal(&self, other: &Self); +} + +impl CheckEqual for substrate_primitives::H256 { + #[cfg(feature = "std")] + fn check_equal(&self, other: &Self) { + use substrate_primitives::hexdisplay::HexDisplay; + if &self.0 != &other.0 { + println!("Hash: given={}, expected={}", HexDisplay::from(&self.0), HexDisplay::from(&other.0)); + } + } + + #[cfg(not(feature = "std"))] + fn check_equal(&self, other: &Self) { + if self != other { + runtime_io::print("Hash not equal"); + runtime_io::print(&self.0[..]); + runtime_io::print(&other.0[..]); + } + } +} diff --git a/substrate/substrate/runtime/session/Cargo.toml b/substrate/substrate/runtime/session/Cargo.toml new file mode 100644 index 0000000000..17bdeb7264 --- /dev/null +++ b/substrate/substrate/runtime/session/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "substrate-runtime-session" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +hex-literal = "0.1.0" +serde = { version = "1.0", default_features = false } +safe-mix = { path = "../../../safe-mix", default_features = false} +substrate-keyring = { path = "../../keyring", optional = true } +substrate-codec = { path = "../../codec", default_features = false } +substrate-primitives = { path = "../../primitives", default_features = false } +substrate-runtime-std = { path = "../../runtime-std", default_features = false } +substrate-runtime-io = { path = "../../runtime-io", default_features = false } +substrate-runtime-support = { path = "../../runtime-support", default_features = false } +substrate-runtime-primitives = { path = "../primitives", default_features = false } +substrate-runtime-consensus = { path = "../consensus", default_features = false } +substrate-runtime-system = { path = "../system", default_features = false } + +[features] +default = ["std"] +std = [ + "serde/std", + "safe-mix/std", + "substrate-keyring", + "substrate-codec/std", + "substrate-primitives/std", + "substrate-runtime-std/std", + "substrate-runtime-io/std", + "substrate-runtime-support/std", + "substrate-runtime-primitives/std", + "substrate-runtime-consensus/std", + "substrate-runtime-system/std", +] diff --git a/substrate/substrate/runtime/session/src/lib.rs b/substrate/substrate/runtime/session/src/lib.rs new file mode 100644 index 0000000000..cdaa9302eb --- /dev/null +++ b/substrate/substrate/runtime/session/src/lib.rs @@ -0,0 +1,345 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Demo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Demo. If not, see . + +//! Session manager: is told the validators and allows them to manage their session keys for the +//! consensus module. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +extern crate serde; + +#[cfg(any(feature = "std", test))] +extern crate substrate_keyring as keyring; + +#[cfg(any(feature = "std", test))] +extern crate substrate_primitives; + +#[cfg_attr(feature = "std", macro_use)] +extern crate substrate_runtime_std as rstd; + +#[macro_use] +extern crate substrate_runtime_support as runtime_support; + +extern crate substrate_runtime_io as runtime_io; +extern crate substrate_codec as codec; +extern crate substrate_runtime_primitives as primitives; +extern crate substrate_runtime_consensus as consensus; +extern crate substrate_runtime_system as system; + +use rstd::prelude::*; +use primitives::traits::{Zero, One, RefInto, Executable, Convert}; +use runtime_support::{StorageValue, StorageMap}; + +pub trait Trait: consensus::Trait + system::Trait { + type PublicAux: RefInto; + type ConvertAccountIdToSessionKey: Convert; +} + +decl_module! { + pub struct Module; + pub enum Call where aux: T::PublicAux { + fn set_key(aux, key: T::SessionKey) = 0; + } + pub enum PrivCall { + fn set_length(new: T::BlockNumber) = 0; + fn force_new_session() = 1; + } +} +decl_storage! { + trait Store for Module; + + // The current set of validators. + pub Validators get(validators): b"ses:val" => required Vec; + // Current length of the session. + pub SessionLength get(length): b"ses:len" => required T::BlockNumber; + // Current index of the session. + pub CurrentIndex get(current_index): b"ses:ind" => required T::BlockNumber; + + // Block at which the session length last changed. + LastLengthChange: b"ses:llc" => T::BlockNumber; + // The next key for a given validator. + NextKeyFor: b"ses:nxt:" => map [ T::AccountId => T::SessionKey ]; + // The next session length. + NextSessionLength: b"ses:nln" => T::BlockNumber; +} + +impl Module { + /// The number of validators currently. + pub fn validator_count() -> u32 { + >::get().len() as u32 // TODO: can probably optimised + } + + /// The last length change, if there was one, zero if not. + pub fn last_length_change() -> T::BlockNumber { + >::get().unwrap_or_else(T::BlockNumber::zero) + } + + /// Sets the session key of `_validator` to `_key`. This doesn't take effect until the next + /// session. + fn set_key(aux: &T::PublicAux, key: T::SessionKey) { + // set new value for next session + >::insert(aux.ref_into(), key) + } + + /// Set a new era length. Won't kick in until the next era change (at current length). + fn set_length(new: T::BlockNumber) { + >::put(new); + } + + /// Forces a new session. + fn force_new_session() { + Self::rotate_session(); + } + + // INTERNAL API (available to other runtime modules) + + /// Set the current set of validators. + /// + /// Called by `staking::next_era()` only. `next_session` should be called after this in order to + /// update the session keys to the next validator set. + pub fn set_validators(new: &[T::AccountId]) { + >::put(&new.to_vec()); // TODO: optimise. + >::set_authorities( + &new.iter().cloned().map(T::ConvertAccountIdToSessionKey::convert).collect::>() + ); + } + + /// Hook to be called after transaction processing. + pub fn check_rotate_session() { + // do this last, after the staking system has had chance to switch out the authorities for the + // new set. + // check block number and call next_session if necessary. + let block_number = >::block_number(); + if ((block_number - Self::last_length_change()) % Self::length()).is_zero() { + Self::rotate_session(); + } + } + + /// Move onto next session: register the new authority set. + pub fn rotate_session() { + // Increment current session index. + >::put(>::get() + One::one()); + + // Enact era length change. + if let Some(next_len) = >::take() { + let block_number = >::block_number(); + >::put(next_len); + >::put(block_number); + } + + // Update any changes in session keys. + Self::validators().iter().enumerate().for_each(|(i, v)| { + if let Some(n) = >::take(v) { + >::set_authority(i as u32, &n); + } + }); + } +} + +impl Executable for Module { + fn execute() { + Self::check_rotate_session(); + } +} + +#[cfg(any(feature = "std", test))] +pub struct GenesisConfig { + pub session_length: T::BlockNumber, + pub validators: Vec, +} + +#[cfg(any(feature = "std", test))] +impl GenesisConfig where T::AccountId: From { + pub fn simple() -> Self where T::AccountId: From<[u8; 32]> { + use primitives::traits::As; + use keyring::Keyring::*; + let three = [3u8; 32]; + GenesisConfig { + session_length: T::BlockNumber::sa(2), + validators: vec![T::AccountId::from(One), T::AccountId::from(Two), T::AccountId::from(three)], + } + } + + pub fn extended() -> Self { + use primitives::traits::As; + use keyring::Keyring::*; + GenesisConfig { + session_length: T::BlockNumber::sa(1), + validators: vec![T::AccountId::from(Alice), T::AccountId::from(Bob), T::AccountId::from(Charlie)], + } + } +} + +#[cfg(any(feature = "std", test))] +impl Default for GenesisConfig { + fn default() -> Self { + use primitives::traits::As; + GenesisConfig { + session_length: T::BlockNumber::sa(1000), + validators: vec![], + } + } +} + +#[cfg(any(feature = "std", test))] +impl primitives::BuildExternalities for GenesisConfig +{ + fn build_externalities(self) -> runtime_io::TestExternalities { + use runtime_io::twox_128; + use codec::Slicable; + use primitives::traits::As; + map![ + twox_128(>::key()).to_vec() => self.session_length.encode(), + twox_128(>::key()).to_vec() => T::BlockNumber::sa(0).encode(), + twox_128(>::key()).to_vec() => self.validators.encode() + ] + } +} + +#[cfg(test)] +mod tests { + use super::*; + use runtime_io::with_externalities; + use substrate_primitives::H256; + use primitives::BuildExternalities; + use primitives::traits::{HasPublicAux, Identity}; + use primitives::testing::{Digest, Header}; + + pub struct Test; + impl HasPublicAux for Test { + type PublicAux = u64; + } + impl consensus::Trait for Test { + type SessionKey = u64; + } + impl system::Trait for Test { + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = runtime_io::BlakeTwo256; + type Digest = Digest; + type AccountId = u64; + type Header = Header; + } + impl Trait for Test { + type PublicAux = ::PublicAux; + type ConvertAccountIdToSessionKey = Identity; + } + + type System = system::Module; + type Consensus = consensus::Module; + type Session = Module; + + fn new_test_ext() -> runtime_io::TestExternalities { + let mut t = system::GenesisConfig::::default().build_externalities(); + t.extend(consensus::GenesisConfig::{ + authorities: vec![1, 2, 3], + }.build_externalities()); + t.extend(GenesisConfig::{ + session_length: 2, + validators: vec![1, 2, 3], + }.build_externalities()); + t + } + + #[test] + fn simple_setup_should_work() { + with_externalities(&mut new_test_ext(), || { + assert_eq!(Consensus::authorities(), vec![1, 2, 3]); + assert_eq!(Session::length(), 2); + assert_eq!(Session::validators(), vec![1, 2, 3]); + }); + } + + #[test] + fn session_length_change_should_work() { + with_externalities(&mut new_test_ext(), || { + // Block 1: Change to length 3; no visible change. + System::set_block_number(1); + Session::set_length(3); + Session::check_rotate_session(); + assert_eq!(Session::length(), 2); + assert_eq!(Session::current_index(), 0); + + // Block 2: Length now changed to 3. Index incremented. + System::set_block_number(2); + Session::set_length(3); + Session::check_rotate_session(); + assert_eq!(Session::length(), 3); + assert_eq!(Session::current_index(), 1); + + // Block 3: Length now changed to 3. Index incremented. + System::set_block_number(3); + Session::check_rotate_session(); + assert_eq!(Session::length(), 3); + assert_eq!(Session::current_index(), 1); + + // Block 4: Change to length 2; no visible change. + System::set_block_number(4); + Session::set_length(2); + Session::check_rotate_session(); + assert_eq!(Session::length(), 3); + assert_eq!(Session::current_index(), 1); + + // Block 5: Length now changed to 2. Index incremented. + System::set_block_number(5); + Session::check_rotate_session(); + assert_eq!(Session::length(), 2); + assert_eq!(Session::current_index(), 2); + + // Block 6: No change. + System::set_block_number(6); + Session::check_rotate_session(); + assert_eq!(Session::length(), 2); + assert_eq!(Session::current_index(), 2); + + // Block 7: Next index. + System::set_block_number(7); + Session::check_rotate_session(); + assert_eq!(Session::length(), 2); + assert_eq!(Session::current_index(), 3); + }); + } + + #[test] + fn session_change_should_work() { + with_externalities(&mut new_test_ext(), || { + // Block 1: No change + System::set_block_number(1); + Session::check_rotate_session(); + assert_eq!(Consensus::authorities(), vec![1, 2, 3]); + + // Block 2: Session rollover, but no change. + System::set_block_number(2); + Session::check_rotate_session(); + assert_eq!(Consensus::authorities(), vec![1, 2, 3]); + + // Block 3: Set new key for validator 2; no visible change. + System::set_block_number(3); + Session::set_key(&2, 5); + assert_eq!(Consensus::authorities(), vec![1, 2, 3]); + + Session::check_rotate_session(); + assert_eq!(Consensus::authorities(), vec![1, 2, 3]); + + // Block 4: Session rollover, authority 2 changes. + System::set_block_number(4); + Session::check_rotate_session(); + assert_eq!(Consensus::authorities(), vec![1, 5, 3]); + }); + } +} diff --git a/substrate/substrate/runtime/staking/Cargo.toml b/substrate/substrate/runtime/staking/Cargo.toml new file mode 100644 index 0000000000..75350d1319 --- /dev/null +++ b/substrate/substrate/runtime/staking/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "substrate-runtime-staking" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +hex-literal = "0.1.0" +serde = { version = "1.0", default_features = false } +safe-mix = { path = "../../../safe-mix", default_features = false} +substrate-keyring = { path = "../../keyring", optional = true } +substrate-codec = { path = "../../codec", default_features = false } +substrate-primitives = { path = "../../primitives", default_features = false } +substrate-runtime-std = { path = "../../runtime-std", default_features = false } +substrate-runtime-io = { path = "../../runtime-io", default_features = false } +substrate-runtime-support = { path = "../../runtime-support", default_features = false } +substrate-runtime-primitives = { path = "../primitives", default_features = false } +substrate-runtime-consensus = { path = "../consensus", default_features = false } +substrate-runtime-system = { path = "../system", default_features = false } +substrate-runtime-session = { path = "../session", default_features = false } + +[features] +default = ["std"] +std = [ + "serde/std", + "safe-mix/std", + "substrate-keyring", + "substrate-codec/std", + "substrate-primitives/std", + "substrate-runtime-std/std", + "substrate-runtime-io/std", + "substrate-runtime-support/std", + "substrate-runtime-primitives/std", + "substrate-runtime-session/std", + "substrate-runtime-system/std", +] diff --git a/substrate/substrate/runtime/staking/src/lib.rs b/substrate/substrate/runtime/staking/src/lib.rs new file mode 100644 index 0000000000..947b08b240 --- /dev/null +++ b/substrate/substrate/runtime/staking/src/lib.rs @@ -0,0 +1,1017 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Demo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Demo. If not, see . + +//! Staking manager: Handles balances and periodically determines the best set of validators. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +extern crate serde; + +#[macro_use] +extern crate substrate_runtime_support as runtime_support; + +#[cfg_attr(feature = "std", macro_use)] +extern crate substrate_runtime_std as rstd; + +extern crate substrate_codec as codec; +extern crate substrate_primitives; +extern crate substrate_runtime_io as runtime_io; +extern crate substrate_runtime_primitives as primitives; +extern crate substrate_runtime_consensus as consensus; +extern crate substrate_runtime_session as session; +extern crate substrate_runtime_system as system; + +#[cfg(test)] use std::fmt::Debug; +use rstd::prelude::*; +use rstd::cmp; +use rstd::cell::RefCell; +use rstd::marker::PhantomData; +use rstd::collections::btree_map::{BTreeMap, Entry}; +use codec::Slicable; +use runtime_support::{StorageValue, StorageMap, Parameter}; +use primitives::traits::{Zero, One, Bounded, RefInto, SimpleArithmetic, Executable, MakePayment}; + +#[cfg(test)] +#[derive(Debug, PartialEq, Clone)] +pub enum LockStatus { + Liquid, + LockedUntil(BlockNumber), + Staked, +} + +#[cfg(not(test))] +#[derive(PartialEq, Clone)] +pub enum LockStatus { + Liquid, + LockedUntil(BlockNumber), + Staked, +} + +pub trait ContractAddressFor { + fn contract_address_for(code: &[u8], origin: &AccountId) -> AccountId; +} + +impl ContractAddressFor for Hashing where + Hashing: runtime_io::Hashing, + AccountId: Sized + Slicable + From, + Hashing::Output: Slicable +{ + fn contract_address_for(code: &[u8], origin: &AccountId) -> AccountId { + let mut dest_pre = Hashing::hash(code).encode(); + origin.using_encoded(|s| dest_pre.extend(s)); + AccountId::from(Hashing::hash(&dest_pre)) + } +} + +pub trait Trait: system::Trait + session::Trait { + /// The balance of an account. + type Balance: Parameter + SimpleArithmetic + Default + Copy; + type DetermineContractAddress: ContractAddressFor; +} + +decl_module! { + pub struct Module; + pub enum Call where aux: T::PublicAux { + fn transfer(aux, dest: T::AccountId, value: T::Balance) = 0; + fn stake(aux) = 1; + fn unstake(aux) = 2; + } + pub enum PrivCall { + fn set_sessions_per_era(new: T::BlockNumber) = 0; + fn set_bonding_duration(new: T::BlockNumber) = 1; + fn set_validator_count(new: u32) = 2; + fn force_new_era() = 3; + } +} + +decl_storage! { + trait Store for Module; + + // The length of the bonding duration in eras. + pub BondingDuration get(bonding_duration): b"sta:loc" => required T::BlockNumber; + // The length of a staking era in sessions. + pub ValidatorCount get(validator_count): b"sta:vac" => required u32; + // The length of a staking era in sessions. + pub SessionsPerEra get(sessions_per_era): b"sta:spe" => required T::BlockNumber; + // The total amount of stake on the system. + pub TotalStake get(total_stake): b"sta:tot" => required T::Balance; + // The fee to be paid for making a transaction. + pub TransactionFee get(transaction_fee): b"sta:fee" => required T::Balance; + + // The current era index. + pub CurrentEra get(current_era): b"sta:era" => required T::BlockNumber; + // All the accounts with a desire to stake. + pub Intentions: b"sta:wil:" => default Vec; + // The next value of sessions per era. + pub NextSessionsPerEra get(next_sessions_per_era): b"sta:nse" => T::BlockNumber; + // The block number at which the era length last changed. + pub LastEraLengthChange get(last_era_length_change): b"sta:lec" => default T::BlockNumber; + + // The balance of a given account. + pub FreeBalance get(free_balance): b"sta:bal:" => default map [ T::AccountId => T::Balance ]; + + // The amount of the balance of a given account that is exterally reserved; this can still get + // slashed, but gets slashed last of all. + pub ReservedBalance get(reserved_balance): b"sta:lbo:" => default map [ T::AccountId => T::Balance ]; + + // The block at which the `who`'s funds become entirely liquid. + pub Bondage get(bondage): b"sta:bon:" => default map [ T::AccountId => T::BlockNumber ]; + + // The code associated with an account. + pub CodeOf: b"sta:cod:" => default map [ T::AccountId => Vec ]; // TODO Vec values should be optimised to not do a length prefix. + + // The storage items associated with an account/key. + pub StorageOf: b"sta:sto:" => map [ (T::AccountId, Vec) => Vec ]; // TODO: keys should also be able to take AsRef to ensure Vecs can be passed as &[u8] +} + +impl Module { + + // PUBLIC IMMUTABLES + + /// The length of a staking era in blocks. + pub fn era_length() -> T::BlockNumber { + Self::sessions_per_era() * >::length() + } + + /// The combined balance of `who`. + pub fn balance(who: &T::AccountId) -> T::Balance { + Self::free_balance(who) + Self::reserved_balance(who) + } + + /// Some result as `slash(who, value)` (but without the side-effects) asuming there are no + /// balance changes in the meantime. + pub fn can_slash(who: &T::AccountId, value: T::Balance) -> bool { + Self::balance(who) >= value + } + + /// The block at which the `who`'s funds become entirely liquid. + pub fn unlock_block(who: &T::AccountId) -> LockStatus { + match Self::bondage(who) { + i if i == T::BlockNumber::max_value() => LockStatus::Staked, + i if i <= >::block_number() => LockStatus::Liquid, + i => LockStatus::LockedUntil(i), + } + } + + /// Create a smart-contract account. + pub fn create(aux: &T::PublicAux, code: &[u8], value: T::Balance) { + // commit anything that made it this far to storage + if let Some(commit) = Self::effect_create(aux.ref_into(), code, value, DirectExt) { + Self::commit_state(commit); + } + } + + // PUBLIC DISPATCH + + /// Transfer some unlocked staking balance to another staker. + /// TODO: probably want to state gas-limit and gas-price. + fn transfer(aux: &T::PublicAux, dest: T::AccountId, value: T::Balance) { + // commit anything that made it this far to storage + if let Some(commit) = Self::effect_transfer(aux.ref_into(), &dest, value, DirectExt) { + Self::commit_state(commit); + } + } + + /// Declare the desire to stake for the transactor. + /// + /// Effects will be felt at the beginning of the next era. + fn stake(aux: &T::PublicAux) { + let mut intentions = >::get(); + // can't be in the list twice. + assert!(intentions.iter().find(|&t| t == aux.ref_into()).is_none(), "Cannot stake if already staked."); + intentions.push(aux.ref_into().clone()); + >::put(intentions); + >::insert(aux.ref_into(), T::BlockNumber::max_value()); + } + + /// Retract the desire to stake for the transactor. + /// + /// Effects will be felt at the beginning of the next era. + fn unstake(aux: &T::PublicAux) { + let mut intentions = >::get(); + if let Some(position) = intentions.iter().position(|t| t == aux.ref_into()) { + intentions.swap_remove(position); + } else { + panic!("Cannot unstake if not already staked."); + } + >::put(intentions); + >::insert(aux.ref_into(), Self::current_era() + Self::bonding_duration()); + } + + // PRIV DISPATCH + + /// Set the number of sessions in an era. + fn set_sessions_per_era(new: T::BlockNumber) { + >::put(&new); + } + + /// The length of the bonding duration in eras. + fn set_bonding_duration(new: T::BlockNumber) { + >::put(&new); + } + + /// The length of a staking era in sessions. + fn set_validator_count(new: u32) { + >::put(&new); + } + + /// Force there to be a new era. This also forces a new session immediately after. + fn force_new_era() { + Self::new_era(); + >::rotate_session(); + } + + // PUBLIC MUTABLES (DANGEROUS) + + /// Deduct from an unbonded balance. true if it happened. + pub fn deduct_unbonded(who: &T::AccountId, value: T::Balance) -> bool { + if let LockStatus::Liquid = Self::unlock_block(who) { + let b = Self::free_balance(who); + if b >= value { + >::insert(who, b - value); + return true; + } + } + false + } + + /// Refund some balance. + pub fn refund(who: &T::AccountId, value: T::Balance) { + >::insert(who, Self::free_balance(who) + value) + } + + /// Will slash any balance, but prefer free over reserved. + pub fn slash(who: &T::AccountId, value: T::Balance) -> bool { + let free_balance = Self::free_balance(who); + let free_slash = cmp::min(free_balance, value); + >::insert(who, &(free_balance - free_slash)); + if free_slash < value { + Self::slash_reserved(who, value - free_slash) + } else { + true + } + } + + /// Moves `value` from balance to reserved balance. + pub fn reserve_balance(who: &T::AccountId, value: T::Balance) { + let b = Self::free_balance(who); + assert!(b >= value); + >::insert(who, b - value); + >::insert(who, Self::reserved_balance(who) + value); + } + + /// Moves `value` from reserved balance to balance. + pub fn unreserve_balance(who: &T::AccountId, value: T::Balance) { + let b = Self::reserved_balance(who); + let value = cmp::min(b, value); + >::insert(who, b - value); + >::insert(who, Self::free_balance(who) + value); + } + + /// Moves `value` from reserved balance to balance. + pub fn slash_reserved(who: &T::AccountId, value: T::Balance) -> bool { + let b = Self::reserved_balance(who); + let slash = cmp::min(b, value); + >::insert(who, b - slash); + value == slash + } + + /// Moves `value` from reserved balance to balance. + pub fn transfer_reserved_balance(slashed: &T::AccountId, beneficiary: &T::AccountId, value: T::Balance) -> bool { + let b = Self::reserved_balance(slashed); + let slash = cmp::min(b, value); + >::insert(slashed, b - slash); + >::insert(beneficiary, Self::free_balance(beneficiary) + slash); + slash == value + } + + /// Hook to be called after to transaction processing. + pub fn check_new_era() { + // check block number and call new_era if necessary. + if (>::block_number() - Self::last_era_length_change()) % Self::era_length() == Zero::zero() { + Self::new_era(); + } + } + + /// The era has changed - enact new staking set. + /// + /// NOTE: This always happens immediately before a session change to ensure that new validators + /// get a chance to set their session keys. + fn new_era() { + // Increment current era. + >::put(&(>::get() + One::one())); + + // Enact era length change. + if let Some(next_spe) = Self::next_sessions_per_era() { + if next_spe != Self::sessions_per_era() { + >::put(&next_spe); + >::put(&>::block_number()); + } + } + + // evaluate desired staking amounts and nominations and optimise to find the best + // combination of validators, then use session::internal::set_validators(). + // for now, this just orders would-be stakers by their balances and chooses the top-most + // >::get() of them. + let mut intentions = >::get() + .into_iter() + .map(|v| (Self::balance(&v), v)) + .collect::>(); + intentions.sort_unstable_by(|&(ref b1, _), &(ref b2, _)| b2.cmp(&b1)); + >::set_validators( + &intentions.into_iter() + .map(|(_, v)| v) + .take(>::get() as usize) + .collect::>() + ); + } +} + +impl Executable for Module { + fn execute() { + Self::check_new_era(); + } +} + +// Each identity's stake may be in one of three bondage states, given by an integer: +// - n | n <= >::get(): inactive: free to be transferred. +// - ~0: active: currently representing a validator. +// - n | n > >::get(): deactivating: recently representing a validator and not yet +// ready for transfer. + +struct ChangeEntry { + balance: Option, + code: Option>, + storage: BTreeMap, Option>>, +} + +// Cannot derive(Default) since it erroneously bounds T by Default. +impl Default for ChangeEntry { + fn default() -> Self { + ChangeEntry { + balance: Default::default(), + code: Default::default(), + storage: Default::default(), + } + } +} + +impl ChangeEntry { + pub fn balance_changed(b: T::Balance) -> Self { + ChangeEntry { balance: Some(b), code: None, storage: Default::default() } + } +} + +type State = BTreeMap<::AccountId, ChangeEntry>; + +trait Externalities { + fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option>; + fn get_code(&self, account: &T::AccountId) -> Vec; + fn get_balance(&self, account: &T::AccountId) -> T::Balance; +} + +struct Ext where + F1 : Fn(&T::AccountId, &[u8]) -> Option>, + F3 : Fn(&T::AccountId) -> Vec, + F5 : Fn(&T::AccountId) -> T::Balance +{ + do_get_storage: F1, + do_get_code: F3, + do_get_balance: F5, + _unused: PhantomData, +} + +struct DirectExt; +impl Externalities for DirectExt { + fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option> { + >::get(&(account.clone(), location.to_vec())) + } + fn get_code(&self, account: &T::AccountId) -> Vec { + >::get(account) + } + fn get_balance(&self, account: &T::AccountId) -> T::Balance { + >::get(account) + } +} + +impl Externalities for Ext where + F1 : Fn(&T::AccountId, &[u8]) -> Option>, + F3 : Fn(&T::AccountId) -> Vec, + F5 : Fn(&T::AccountId) -> T::Balance +{ + fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option> { + (self.do_get_storage)(account, location) + } + fn get_code(&self, account: &T::AccountId) -> Vec { + (self.do_get_code)(account) + } + fn get_balance(&self, account: &T::AccountId) -> T::Balance { + (self.do_get_balance)(account) + } +} + +impl Module { + fn commit_state(s: State) { + for (address, changed) in s.into_iter() { + if let Some(balance) = changed.balance { + >::insert(&address, balance); + } + if let Some(code) = changed.code { + >::insert(&address, &code); + } + for (k, v) in changed.storage.into_iter() { + if let Some(value) = v { + >::insert((address.clone(), k), &value); + } else { + >::remove((address.clone(), k)); + } + } + } + } + + fn merge_state(commit_state: State, local: &mut State) { + for (address, changed) in commit_state.into_iter() { + match local.entry(address) { + Entry::Occupied(e) => { + let mut value = e.into_mut(); + if changed.balance.is_some() { + value.balance = changed.balance; + } + if changed.code.is_some() { + value.code = changed.code; + } + value.storage.extend(changed.storage.into_iter()); + } + Entry::Vacant(e) => { + e.insert(changed); + } + } + } + } + + fn effect_create>( + transactor: &T::AccountId, + code: &[u8], + value: T::Balance, + ext: E + ) -> Option> { + let from_balance = ext.get_balance(transactor); + // TODO: a fee. + assert!(from_balance >= value); + + let dest = T::DetermineContractAddress::contract_address_for(code, transactor); + + // early-out if degenerate. + if &dest == transactor { + return None; + } + + let mut local = BTreeMap::new(); + + // two inserts are safe + assert!(&dest != transactor); + local.insert(dest, ChangeEntry { balance: Some(value), code: Some(code.to_vec()), storage: Default::default() }); + local.insert(transactor.clone(), ChangeEntry::balance_changed(from_balance - value)); + + Some(local) + } + + fn effect_transfer>( + transactor: &T::AccountId, + dest: &T::AccountId, + value: T::Balance, + ext: E + ) -> Option> { + let from_balance = ext.get_balance(transactor); + assert!(from_balance >= value); + + let to_balance = ext.get_balance(dest); + assert!(>::get(transactor) <= >::get(dest)); + assert!(to_balance + value > to_balance); // no overflow + + // TODO: a fee, based upon gaslimit/gasprice. + // TODO: consider storing upper-bound for contract's gas limit in fixed-length runtime + // code in contract itself and use that. + + let local: RefCell> = RefCell::new(BTreeMap::new()); + + if transactor != dest { + let mut local = local.borrow_mut(); + local.insert(transactor.clone(), ChangeEntry::balance_changed(from_balance - value)); + local.insert(dest.clone(), ChangeEntry::balance_changed(to_balance + value)); + } + + let should_commit = { + // Our local ext: Should be used for any transfers and creates that happen internally. + let ext = || Ext { + do_get_storage: |account: &T::AccountId, location: &[u8]| + local.borrow().get(account) + .and_then(|a| a.storage.get(location)) + .cloned() + .unwrap_or_else(|| ext.get_storage(account, location)), + do_get_code: |account: &T::AccountId| + local.borrow().get(account) + .and_then(|a| a.code.clone()) + .unwrap_or_else(|| ext.get_code(account)), + do_get_balance: |account: &T::AccountId| + local.borrow().get(account) + .and_then(|a| a.balance) + .unwrap_or_else(|| ext.get_balance(account)), + _unused: Default::default(), + }; + let mut _transfer = |inner_dest: &T::AccountId, value: T::Balance| { + if let Some(commit_state) = Self::effect_transfer(dest, inner_dest, value, ext()) { + Self::merge_state(commit_state, &mut *local.borrow_mut()); + } + }; + let mut _create = |code: &[u8], value: T::Balance| { + if let Some(commit_state) = Self::effect_create(dest, code, value, ext()) { + Self::merge_state(commit_state, &mut *local.borrow_mut()); + } + }; + let mut _put_storage = |location: Vec, value: Option>| { + local.borrow_mut() + .entry(dest.clone()) + .or_insert(Default::default()) + .storage.insert(location, value); + }; + + // TODO: logging (logs are just appended into a notable storage-based vector and cleared every + // block). + // TODO: execute code with ext(), put_storage, create and transfer as externalities. + true + }; + + if should_commit { + Some(local.into_inner()) + } else { + None + } + } +} + +impl MakePayment for Module { + fn make_payment(transactor: &T::AccountId) { + let b = Self::free_balance(transactor); + let transaction_fee = Self::transaction_fee(); + assert!(b >= transaction_fee, "attempt to transact without enough funds to pay fee"); + >::insert(transactor, b - transaction_fee); + } +} + +#[cfg(any(feature = "std", test))] +pub struct DummyContractAddressFor; +#[cfg(any(feature = "std", test))] +impl ContractAddressFor for DummyContractAddressFor { + fn contract_address_for(_code: &[u8], origin: &u64) -> u64 { + origin + 1 + } +} + +#[cfg(any(feature = "std", test))] +pub struct GenesisConfig { + pub sessions_per_era: T::BlockNumber, + pub current_era: T::BlockNumber, + pub balances: Vec<(T::AccountId, T::Balance)>, + pub intentions: Vec, + pub validator_count: u64, + pub bonding_duration: T::BlockNumber, + pub transaction_fee: T::Balance, +} + +#[cfg(any(feature = "std", test))] +impl GenesisConfig where T::AccountId: From { + pub fn simple() -> Self { + use primitives::traits::As; + GenesisConfig { + sessions_per_era: T::BlockNumber::sa(2), + current_era: T::BlockNumber::sa(0), + balances: vec![(T::AccountId::from(1), T::Balance::sa(111))], + intentions: vec![T::AccountId::from(1), T::AccountId::from(2), T::AccountId::from(3)], + validator_count: 3, + bonding_duration: T::BlockNumber::sa(0), + transaction_fee: T::Balance::sa(0), + } + } + + pub fn extended() -> Self { + use primitives::traits::As; + GenesisConfig { + sessions_per_era: T::BlockNumber::sa(3), + current_era: T::BlockNumber::sa(1), + balances: vec![ + (T::AccountId::from(1), T::Balance::sa(10)), + (T::AccountId::from(2), T::Balance::sa(20)), + (T::AccountId::from(3), T::Balance::sa(30)), + (T::AccountId::from(4), T::Balance::sa(40)), + (T::AccountId::from(5), T::Balance::sa(50)), + (T::AccountId::from(6), T::Balance::sa(60)), + (T::AccountId::from(7), T::Balance::sa(1)) + ], + intentions: vec![T::AccountId::from(1), T::AccountId::from(2), T::AccountId::from(3)], + validator_count: 3, + bonding_duration: T::BlockNumber::sa(0), + transaction_fee: T::Balance::sa(1), + } + } +} + +#[cfg(any(feature = "std", test))] +impl Default for GenesisConfig { + fn default() -> Self { + use primitives::traits::As; + GenesisConfig { + sessions_per_era: T::BlockNumber::sa(1000), + current_era: T::BlockNumber::sa(0), + balances: vec![], + intentions: vec![], + validator_count: 0, + bonding_duration: T::BlockNumber::sa(1000), + transaction_fee: T::Balance::sa(0), + } + } +} + +#[cfg(any(feature = "std", test))] +impl primitives::BuildExternalities for GenesisConfig { + fn build_externalities(self) -> runtime_io::TestExternalities { + use runtime_io::twox_128; + use codec::Slicable; + + let total_stake: T::Balance = self.balances.iter().fold(Zero::zero(), |acc, &(_, n)| acc + n); + + let mut r: runtime_io::TestExternalities = map![ + twox_128(>::key()).to_vec() => self.intentions.encode(), + twox_128(>::key()).to_vec() => self.sessions_per_era.encode(), + twox_128(>::key()).to_vec() => self.validator_count.encode(), + twox_128(>::key()).to_vec() => self.bonding_duration.encode(), + twox_128(>::key()).to_vec() => self.transaction_fee.encode(), + twox_128(>::key()).to_vec() => self.current_era.encode(), + twox_128(>::key()).to_vec() => total_stake.encode() + ]; + + for (who, value) in self.balances.into_iter() { + r.insert(twox_128(&>::key_for(who)).to_vec(), value.encode()); + } + r + } +} + +#[cfg(test)] +mod tests { + use super::*; + use runtime_io::with_externalities; + use substrate_primitives::H256; + use primitives::BuildExternalities; + use primitives::traits::{HasPublicAux, Identity}; + use primitives::testing::{Digest, Header}; + + pub struct Test; + impl HasPublicAux for Test { + type PublicAux = u64; + } + impl consensus::Trait for Test { + type SessionKey = u64; + } + impl system::Trait for Test { + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = runtime_io::BlakeTwo256; + type Digest = Digest; + type AccountId = u64; + type Header = Header; + } + impl session::Trait for Test { + type PublicAux = ::PublicAux; + type ConvertAccountIdToSessionKey = Identity; + } + impl Trait for Test { + type Balance = u64; + type DetermineContractAddress = DummyContractAddressFor; + } + + fn new_test_ext(session_length: u64, sessions_per_era: u64, current_era: u64, monied: bool) -> runtime_io::TestExternalities { + let mut t = system::GenesisConfig::::default().build_externalities(); + t.extend(consensus::GenesisConfig::{ + authorities: vec![], + }.build_externalities()); + t.extend(session::GenesisConfig::{ + session_length, + validators: vec![10, 20], + }.build_externalities()); + t.extend(GenesisConfig::{ + sessions_per_era, + current_era, + balances: if monied { vec![(1, 10), (2, 20), (3, 30), (4, 40)] } else { vec![] }, + intentions: vec![], + validator_count: 2, + bonding_duration: 3, + transaction_fee: 0, + }.build_externalities()); + t + } + + type System = system::Module; + type Session = session::Module; + type Staking = Module; + + #[test] + fn staking_should_work() { + with_externalities(&mut new_test_ext(1, 2, 0, true), || { + assert_eq!(Staking::era_length(), 2); + assert_eq!(Staking::validator_count(), 2); + assert_eq!(Staking::bonding_duration(), 3); + assert_eq!(Session::validators(), vec![10, 20]); + + // Block 1: Add three validators. No obvious change. + System::set_block_number(1); + Staking::stake(&1); + Staking::stake(&2); + Staking::stake(&4); + Staking::check_new_era(); + assert_eq!(Session::validators(), vec![10, 20]); + + // Block 2: New validator set now. + System::set_block_number(2); + Staking::check_new_era(); + assert_eq!(Session::validators(), vec![4, 2]); + + // Block 3: Unstake highest, introduce another staker. No change yet. + System::set_block_number(3); + Staking::stake(&3); + Staking::unstake(&4); + Staking::check_new_era(); + + // Block 4: New era - validators change. + System::set_block_number(4); + Staking::check_new_era(); + assert_eq!(Session::validators(), vec![3, 2]); + + // Block 5: Transfer stake from highest to lowest. No change yet. + System::set_block_number(5); + Staking::transfer(&4, 1, 40); + Staking::check_new_era(); + + // Block 6: Lowest now validator. + System::set_block_number(6); + Staking::check_new_era(); + assert_eq!(Session::validators(), vec![1, 3]); + + // Block 7: Unstake three. No change yet. + System::set_block_number(7); + Staking::unstake(&3); + Staking::check_new_era(); + assert_eq!(Session::validators(), vec![1, 3]); + + // Block 8: Back to one and two. + System::set_block_number(8); + Staking::check_new_era(); + assert_eq!(Session::validators(), vec![1, 2]); + }); + } + + #[test] + fn staking_eras_work() { + with_externalities(&mut new_test_ext(1, 2, 0, true), || { + assert_eq!(Staking::era_length(), 2); + assert_eq!(Staking::sessions_per_era(), 2); + assert_eq!(Staking::last_era_length_change(), 0); + assert_eq!(Staking::current_era(), 0); + + // Block 1: No change. + System::set_block_number(1); + Staking::check_new_era(); + assert_eq!(Staking::sessions_per_era(), 2); + assert_eq!(Staking::last_era_length_change(), 0); + assert_eq!(Staking::current_era(), 0); + + // Block 2: Simple era change. + System::set_block_number(2); + Staking::check_new_era(); + assert_eq!(Staking::sessions_per_era(), 2); + assert_eq!(Staking::last_era_length_change(), 0); + assert_eq!(Staking::current_era(), 1); + + // Block 3: Schedule an era length change; no visible changes. + System::set_block_number(3); + Staking::set_sessions_per_era(3); + Staking::check_new_era(); + assert_eq!(Staking::sessions_per_era(), 2); + assert_eq!(Staking::last_era_length_change(), 0); + assert_eq!(Staking::current_era(), 1); + + // Block 4: Era change kicks in. + System::set_block_number(4); + Staking::check_new_era(); + assert_eq!(Staking::sessions_per_era(), 3); + assert_eq!(Staking::last_era_length_change(), 4); + assert_eq!(Staking::current_era(), 2); + + // Block 5: No change. + System::set_block_number(5); + Staking::check_new_era(); + assert_eq!(Staking::sessions_per_era(), 3); + assert_eq!(Staking::last_era_length_change(), 4); + assert_eq!(Staking::current_era(), 2); + + // Block 6: No change. + System::set_block_number(6); + Staking::check_new_era(); + assert_eq!(Staking::sessions_per_era(), 3); + assert_eq!(Staking::last_era_length_change(), 4); + assert_eq!(Staking::current_era(), 2); + + // Block 7: Era increment. + System::set_block_number(7); + Staking::check_new_era(); + assert_eq!(Staking::sessions_per_era(), 3); + assert_eq!(Staking::last_era_length_change(), 4); + assert_eq!(Staking::current_era(), 3); + }); + } + + #[test] + fn staking_balance_works() { + with_externalities(&mut new_test_ext(1, 3, 1, false), || { + >::insert(1, 42); + assert_eq!(Staking::free_balance(&1), 42); + assert_eq!(Staking::reserved_balance(&1), 0); + assert_eq!(Staking::balance(&1), 42); + assert_eq!(Staking::free_balance(&2), 0); + assert_eq!(Staking::reserved_balance(&2), 0); + assert_eq!(Staking::balance(&2), 0); + }); + } + + #[test] + fn staking_balance_transfer_works() { + with_externalities(&mut new_test_ext(1, 3, 1, false), || { + >::insert(1, 111); + Staking::transfer(&1, 2, 69); + assert_eq!(Staking::balance(&1), 42); + assert_eq!(Staking::balance(&2), 69); + }); + } + + #[test] + #[should_panic] + fn staking_balance_transfer_when_bonded_panics() { + with_externalities(&mut new_test_ext(1, 3, 1, false), || { + >::insert(1, 111); + Staking::stake(&1); + Staking::transfer(&1, 2, 69); + }); + } + + #[test] + fn reserving_balance_should_work() { + with_externalities(&mut new_test_ext(1, 3, 1, false), || { + >::insert(1, 111); + + assert_eq!(Staking::balance(&1), 111); + assert_eq!(Staking::free_balance(&1), 111); + assert_eq!(Staking::reserved_balance(&1), 0); + + Staking::reserve_balance(&1, 69); + + assert_eq!(Staking::balance(&1), 111); + assert_eq!(Staking::free_balance(&1), 42); + assert_eq!(Staking::reserved_balance(&1), 69); + }); + } + + #[test] + #[should_panic] + fn staking_balance_transfer_when_reserved_panics() { + with_externalities(&mut new_test_ext(1, 3, 1, false), || { + >::insert(1, 111); + Staking::reserve_balance(&1, 69); + Staking::transfer(&1, 2, 69); + }); + } + + #[test] + fn deducting_balance_should_work() { + with_externalities(&mut new_test_ext(1, 3, 1, false), || { + >::insert(1, 111); + assert!(Staking::deduct_unbonded(&1, 69)); + assert_eq!(Staking::free_balance(&1), 42); + }); + } + + #[test] + fn deducting_balance_should_fail_when_bonded() { + with_externalities(&mut new_test_ext(1, 3, 1, false), || { + >::insert(1, 111); + >::insert(1, 2); + System::set_block_number(1); + assert_eq!(Staking::unlock_block(&1), LockStatus::LockedUntil(2)); + assert!(!Staking::deduct_unbonded(&1, 69)); + }); + } + + #[test] + fn refunding_balance_should_work() { + with_externalities(&mut new_test_ext(1, 3, 1, false), || { + >::insert(1, 42); + Staking::refund(&1, 69); + assert_eq!(Staking::free_balance(&1), 111); + }); + } + + #[test] + fn slashing_balance_should_work() { + with_externalities(&mut new_test_ext(1, 3, 1, false), || { + >::insert(1, 111); + Staking::reserve_balance(&1, 69); + assert!(Staking::slash(&1, 69)); + assert_eq!(Staking::free_balance(&1), 0); + assert_eq!(Staking::reserved_balance(&1), 42); + }); + } + + #[test] + fn slashing_incomplete_balance_should_work() { + with_externalities(&mut new_test_ext(1, 3, 1, false), || { + >::insert(1, 42); + Staking::reserve_balance(&1, 21); + assert!(!Staking::slash(&1, 69)); + assert_eq!(Staking::free_balance(&1), 0); + assert_eq!(Staking::reserved_balance(&1), 0); + }); + } + + #[test] + fn unreserving_balance_should_work() { + with_externalities(&mut new_test_ext(1, 3, 1, false), || { + >::insert(1, 111); + Staking::reserve_balance(&1, 111); + Staking::unreserve_balance(&1, 42); + assert_eq!(Staking::reserved_balance(&1), 69); + assert_eq!(Staking::free_balance(&1), 42); + }); + } + + #[test] + fn slashing_reserved_balance_should_work() { + with_externalities(&mut new_test_ext(1, 3, 1, false), || { + >::insert(1, 111); + Staking::reserve_balance(&1, 111); + assert!(Staking::slash_reserved(&1, 42)); + assert_eq!(Staking::reserved_balance(&1), 69); + assert_eq!(Staking::free_balance(&1), 0); + }); + } + + #[test] + fn slashing_incomplete_reserved_balance_should_work() { + with_externalities(&mut new_test_ext(1, 3, 1, false), || { + >::insert(1, 111); + Staking::reserve_balance(&1, 42); + assert!(!Staking::slash_reserved(&1, 69)); + assert_eq!(Staking::free_balance(&1), 69); + assert_eq!(Staking::reserved_balance(&1), 0); + }); + } + + #[test] + fn transferring_reserved_balance_should_work() { + with_externalities(&mut new_test_ext(1, 3, 1, false), || { + >::insert(1, 111); + Staking::reserve_balance(&1, 111); + assert!(Staking::transfer_reserved_balance(&1, &2, 42)); + assert_eq!(Staking::reserved_balance(&1), 69); + assert_eq!(Staking::free_balance(&1), 0); + assert_eq!(Staking::reserved_balance(&2), 0); + assert_eq!(Staking::free_balance(&2), 42); + }); + } + + #[test] + fn transferring_incomplete_reserved_balance_should_work() { + with_externalities(&mut new_test_ext(1, 3, 1, false), || { + >::insert(1, 111); + Staking::reserve_balance(&1, 42); + assert!(!Staking::transfer_reserved_balance(&1, &2, 69)); + assert_eq!(Staking::reserved_balance(&1), 0); + assert_eq!(Staking::free_balance(&1), 69); + assert_eq!(Staking::reserved_balance(&2), 0); + assert_eq!(Staking::free_balance(&2), 42); + }); + } +} diff --git a/substrate/substrate/runtime/system/Cargo.toml b/substrate/substrate/runtime/system/Cargo.toml new file mode 100644 index 0000000000..89d4e48e20 --- /dev/null +++ b/substrate/substrate/runtime/system/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "substrate-runtime-system" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +hex-literal = "0.1.0" +serde = { version = "1.0", default_features = false } +safe-mix = { path = "../../../safe-mix", default_features = false} +substrate-codec = { path = "../../codec", default_features = false } +substrate-primitives = { path = "../../primitives", default_features = false } +substrate-runtime-std = { path = "../../runtime-std", default_features = false } +substrate-runtime-io = { path = "../../runtime-io", default_features = false } +substrate-runtime-support = { path = "../../runtime-support", default_features = false } +substrate-runtime-primitives = { path = "../primitives", default_features = false } + +[features] +default = ["std"] +std = [ + "serde/std", + "safe-mix/std", + "substrate-codec/std", + "substrate-primitives/std", + "substrate-runtime-std/std", + "substrate-runtime-io/std", + "substrate-runtime-support/std", + "substrate-runtime-primitives/std", +] diff --git a/substrate/substrate/runtime/system/src/lib.rs b/substrate/substrate/runtime/system/src/lib.rs new file mode 100644 index 0000000000..84f89678a6 --- /dev/null +++ b/substrate/substrate/runtime/system/src/lib.rs @@ -0,0 +1,178 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Demo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Demo. If not, see . + +//! System manager: Handles lowest level stuff like depositing logs, basic set up and take down of +//! temporary storage entries, access to old block hashes. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg_attr(any(feature = "std", test), macro_use)] +extern crate substrate_runtime_std as rstd; + +#[macro_use] +extern crate substrate_runtime_support as runtime_support; + +#[cfg(feature = "std")] +extern crate serde; + +extern crate substrate_runtime_io as runtime_io; +extern crate substrate_codec as codec; +extern crate substrate_runtime_primitives as primitives; +extern crate safe_mix; + +use rstd::prelude::*; +use runtime_io::Hashing; +use primitives::traits::{self, CheckEqual, SimpleArithmetic, SimpleBitOps, Zero, One, Bounded}; +use runtime_support::{StorageValue, StorageMap, Parameter}; +use safe_mix::TripletMix; + +#[cfg(any(feature = "std", test))] +use rstd::marker::PhantomData; +#[cfg(any(feature = "std", test))] +use codec::Slicable; + +#[cfg(any(feature = "std", test))] +use runtime_io::{twox_128, TestExternalities}; + +pub trait Trait { + type Index: Parameter + Default + SimpleArithmetic + Copy; + type BlockNumber: Parameter + SimpleArithmetic + Default + Bounded + Copy; + type Hash: Parameter + SimpleBitOps + Default + Copy + CheckEqual; + type Hashing: Hashing; + type Digest: Parameter + Default + traits::Digest; + type AccountId: Parameter + Ord + Default; + type Header: traits::Header; +} + +decl_module! { + pub struct Module; +} + +decl_storage! { + trait Store for Module; + + pub AccountIndex get(account_index): b"sys:non" => default map [ T::AccountId => T::Index ]; + pub BlockHash get(block_hash): b"sys:old" => required map [ T::BlockNumber => T::Hash ]; + + RandomSeed get(random_seed): b"sys:rnd" => required T::Hash; + // The current block number being processed. Set by `execute_block`. + Number get(block_number): b"sys:num" => required T::BlockNumber; + ParentHash get(parent_hash): b"sys:pha" => required T::Hash; + ExtrinsicsRoot get(extrinsics_root): b"sys:txr" => required T::Hash; + Digest get(digest): b"sys:dig" => default T::Digest; +} + +impl Module { + /// Start the execution of a particular block. + pub fn initialise(number: &T::BlockNumber, parent_hash: &T::Hash, txs_root: &T::Hash) { + // populate environment. + >::put(number); + >::put(parent_hash); + >::put(txs_root); + >::put(Self::calculate_random()); + } + + /// Remove temporary "environment" entries in storage. + pub fn finalise() -> T::Header { + >::kill(); + + let number = >::take(); + let parent_hash = >::take(); + let digest = >::take(); + let extrinsics_root = >::take(); + let storage_root = T::Hashing::storage_root(); + ::new(number, extrinsics_root, storage_root, parent_hash, digest) + } + + /// Deposits a log and ensures it matches the blocks log data. + pub fn deposit_log(item: ::Item) { + let mut l = >::get(); + traits::Digest::push(&mut l, item); + >::put(l); + } + + /// Records a particular block number and hash combination. + pub fn record_block_hash>(header: &H) { + // store the header hash in storage; we can't do it before otherwise there would be a + // cyclic dependency. + >::insert(header.number(), &T::Hashing::hash_of(header)); + } + + /// Initializes the state following the determination of the genesis block. + pub fn initialise_genesis_state>(header: &H) { + Self::record_block_hash(header); + } + + /// Calculate the current block's random seed. + fn calculate_random() -> T::Hash { + (0..81) + .scan( + { let mut n = Self::block_number().clone(); n -= T::BlockNumber::one(); n }, + |c, _| { if *c > T::BlockNumber::zero() { *c -= T::BlockNumber::one() }; Some(c.clone()) + }) + .map(Self::block_hash) + .triplet_mix() + } + + /// Get the basic externalities for this module, useful for tests. + #[cfg(any(feature = "std", test))] + pub fn externalities() -> TestExternalities { + map![ + twox_128(&>::key_for(T::BlockNumber::zero())).to_vec() => [69u8; 32].encode(), // TODO: replace with Hash::default().encode + twox_128(>::key()).to_vec() => T::BlockNumber::one().encode(), + twox_128(>::key()).to_vec() => [69u8; 32].encode(), // TODO: replace with Hash::default().encode + twox_128(>::key()).to_vec() => T::Hash::default().encode() + ] + } + + /// Set the block number to something in particular. Can be used as an alternative to + /// `initialise` for tests that don't need to bother with the other environment entries. + #[cfg(any(feature = "std", test))] + pub fn set_block_number(n: T::BlockNumber) { + >::put(n); + } + + /// Increment a particular account's nonce by 1. + pub fn inc_account_index(who: &T::AccountId) { + >::insert(who, Self::account_index(who) + T::Index::one()); + } +} + +#[cfg(any(feature = "std", test))] +pub struct GenesisConfig(PhantomData); + +#[cfg(any(feature = "std", test))] +impl Default for GenesisConfig { + fn default() -> Self { + GenesisConfig(PhantomData) + } +} + +#[cfg(any(feature = "std", test))] +impl primitives::BuildExternalities for GenesisConfig +{ + fn build_externalities(self) -> runtime_io::TestExternalities { + use runtime_io::twox_128; + use codec::Slicable; + + map![ + twox_128(&>::key_for(T::BlockNumber::zero())).to_vec() => [69u8; 32].encode(), + twox_128(>::key()).to_vec() => 1u64.encode(), + twox_128(>::key()).to_vec() => [69u8; 32].encode(), + twox_128(>::key()).to_vec() => [0u8; 32].encode() + ] + } +} diff --git a/substrate/substrate/runtime/timestamp/Cargo.toml b/substrate/substrate/runtime/timestamp/Cargo.toml new file mode 100644 index 0000000000..f9382e24be --- /dev/null +++ b/substrate/substrate/runtime/timestamp/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "substrate-runtime-timestamp" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +hex-literal = "0.1.0" +serde = { version = "1.0", default_features = false } +substrate-runtime-std = { path = "../../runtime-std", default_features = false } +substrate-runtime-support = { path = "../../runtime-support", default_features = false } +substrate-runtime-primitives = { path = "../primitives", default_features = false } +substrate-codec = { path = "../../codec", default_features = false } + +[dev-dependencies] +substrate-runtime-io = { path = "../../runtime-io", default_features = true } + +[features] +default = ["std"] +std = [ + "substrate-runtime-std/std", + "substrate-runtime-support/std", + "substrate-runtime-primitives/std", + "serde/std", + "substrate-codec/std", +] diff --git a/substrate/substrate/runtime/timestamp/src/lib.rs b/substrate/substrate/runtime/timestamp/src/lib.rs new file mode 100644 index 0000000000..c651fd8753 --- /dev/null +++ b/substrate/substrate/runtime/timestamp/src/lib.rs @@ -0,0 +1,93 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Demo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Demo. If not, see . + +//! Timestamp manager: just handles the current timestamp. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg_attr(test, macro_use)] +extern crate substrate_runtime_std as rstd; + +#[macro_use] +extern crate substrate_runtime_support as runtime_support; + +#[cfg(test)] +extern crate substrate_runtime_io as runtime_io; + +extern crate substrate_runtime_primitives as runtime_primitives; +extern crate substrate_codec as codec; + +use runtime_support::{StorageValue, Parameter}; +use runtime_primitives::traits::HasPublicAux; + +pub trait Trait: HasPublicAux { + type Value: Parameter + Default; +} + +decl_module! { + pub struct Module; + pub enum Call where aux: T::PublicAux { + fn set(aux, now: T::Value) = 0; + } +} + +decl_storage! { + pub trait Store for Module; + pub Now get(now): b"tim:val" => required T::Value; +} + +impl Module { + pub fn get() -> T::Value { + ::Now::get() + } + + /// Set the current time. + fn set(_aux: &T::PublicAux, now: T::Value) { + ::Now::put(now); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use runtime_io::{with_externalities, twox_128, TestExternalities}; + use codec::Joiner; + use runtime_support::storage::StorageValue; + + struct TraitImpl; + impl HasPublicAux for TraitImpl { + type PublicAux = u64; + } + impl Trait for TraitImpl { + type Value = u64; + } + type Timestamp = Module; + + #[test] + fn timestamp_works() { + + let mut t: TestExternalities = map![ + twox_128(::Now::key()).to_vec() => vec![].and(&42u64) + ]; + + with_externalities(&mut t, || { + assert_eq!(::Now::get(), 42); + Timestamp::aux_dispatch(Call::set(69), &0); + assert_eq!(Timestamp::now(), 69); + }); + } +} diff --git a/substrate/substrate/test-runtime/src/transaction.rs b/substrate/substrate/test-runtime/src/transaction.rs index 81fd37f779..19ddba99e4 100644 --- a/substrate/substrate/test-runtime/src/transaction.rs +++ b/substrate/substrate/test-runtime/src/transaction.rs @@ -53,7 +53,7 @@ impl Slicable for Transaction { } } -impl ::codec::NonTrivialSlicable for Transaction {} + #[cfg(test)] mod tests { diff --git a/substrate/substrate/test-runtime/src/unchecked_transaction.rs b/substrate/substrate/test-runtime/src/unchecked_transaction.rs index 72b60098c1..0aff8d4727 100644 --- a/substrate/substrate/test-runtime/src/unchecked_transaction.rs +++ b/substrate/substrate/test-runtime/src/unchecked_transaction.rs @@ -60,7 +60,7 @@ impl Slicable for UncheckedTransaction { } } -impl ::codec::NonTrivialSlicable for UncheckedTransaction {} + #[cfg(test)] mod tests { diff --git a/substrate/substrate/test-runtime/wasm/Cargo.lock b/substrate/substrate/test-runtime/wasm/Cargo.lock index 8993d9c049..6f379e9dad 100644 --- a/substrate/substrate/test-runtime/wasm/Cargo.lock +++ b/substrate/substrate/test-runtime/wasm/Cargo.lock @@ -621,8 +621,9 @@ name = "substrate-runtime-support" version = "0.1.0" dependencies = [ "ed25519 0.1.0", - "environmental 0.1.0", "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", diff --git a/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index 997a70bdad4faa95d7b9a7096b4cf86a1b7c58d0..1e934f702c35daf2bf0aafe6fee1a556848f281c 100644 GIT binary patch literal 33039 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 C>x#Dk literal 25981 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